Merge "Find activity in task with same user" into tm-qpr-dev
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index c10c380..41a784a 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -26,7 +26,7 @@
hidden_api_txt_exclude_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/exclude.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
-ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check -i ${REPO_ROOT}/frameworks/base/ktfmt_includes.txt ${PREUPLOAD_FILES}
+ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check -i ${REPO_ROOT}/frameworks/base/packages/SystemUI/ktfmt_includes.txt ${PREUPLOAD_FILES}
ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
diff --git a/apct-tests/perftests/surfaceflinger/Android.bp b/apct-tests/perftests/surfaceflinger/Android.bp
new file mode 100644
index 0000000..0c28bce
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/Android.bp
@@ -0,0 +1,40 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "SurfaceFlingerPerfTests",
+ srcs: ["src/**/*.java"],
+ libs: ["android.test.runner.stubs"],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.ext.junit",
+ "androidx.annotation_annotation",
+ "apct-perftests-utils",
+ "collector-device-lib",
+ "platform-test-annotations",
+ ],
+ test_suites: ["device-tests"],
+ data: [":perfetto_artifacts"],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/apct-tests/perftests/surfaceflinger/AndroidManifest.xml b/apct-tests/perftests/surfaceflinger/AndroidManifest.xml
new file mode 100644
index 0000000..26f2586
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.perftests.surfaceflinger">
+
+ <!-- permission needed to write perfetto trace and read/write simpleperf report -->
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application android:label="SurfaceFlingerPerfTests">
+ <uses-library android:name="android.test.runner" />
+ <activity android:name="android.surfaceflinger.SurfaceFlingerTestActivity"
+ android:exported="true">
+
+ <intent-filter>
+ <action android:name="com.android.perftests.core.PERFTEST" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.perftests.surfaceflinger">
+ </instrumentation>
+</manifest>
diff --git a/apct-tests/perftests/surfaceflinger/AndroidTest.xml b/apct-tests/perftests/surfaceflinger/AndroidTest.xml
new file mode 100644
index 0000000..53e5d99
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/AndroidTest.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs SurfaceFlingerPerfTests metric instrumentation.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-metric-instrumentation" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
+ <option name="test-file-name" value="SurfaceFlingerPerfTests.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <option name="force-skip-system-props" value="true" />
+ <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+ <option name="run-command" value="cmd window dismiss-keyguard" />
+ <option name="run-command" value="cmd package compile -m speed android.perftests.surfaceflinger" />
+ </target_preparer>
+
+ <!-- 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" />
+ </target_preparer>
+
+ <!-- Needed for storing the perfetto trace files in the sdcard/test_results-->
+ <option name="isolated-storage" value="false" />
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="package" value="android.perftests.surfaceflinger" />
+ <option name="hidden-api-checks" value="false"/>
+
+ <!-- Listener related args for collecting the traces and waiting for the device to stabilize. -->
+ <option name="device-listeners" value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener,android.device.collectors.SimpleperfListener" />
+
+ <!-- Guarantee that user defined RunListeners will be running before any of the default listeners defined in this runner. -->
+ <option name="instrumentation-arg" key="newRunListenerMode" value="true" />
+
+ <!-- PerfettoListener related arguments -->
+ <option name="instrumentation-arg" key="perfetto_config_text_proto" value="true" />
+ <option name="instrumentation-arg" key="perfetto_config_file" value="trace_config.textproto" />
+
+ <!-- SimpleperfListener related arguments -->
+ <option name="instrumentation-arg" key="report" value="true" />
+ <option name="instrumentation-arg" key="arguments" value="""" />
+ <option name="instrumentation-arg" key="events_to_record" value="instructions,cpu-cycles,raw-l3d-cache-refill,sched:sched_waking" />
+ <option name="instrumentation-arg" key="processes_to_record" value="surfaceflinger" />
+ <option name="instrumentation-arg" key="symbols_to_report" value=""android::SurfaceFlinger::commit(;android::SurfaceFlinger::composite("" />
+
+ <!-- ProcLoadListener related arguments -->
+ <!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting the test run -->
+ <option name="instrumentation-arg" key="procload-collector:per_run" value="true" />
+ <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3" />
+ <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000" />
+ <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000" />
+
+ </test>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/data/local/tmp/SurfaceFlingerPerfTests" />
+ <!-- Needed for pulling the collected trace config on to the host -->
+ <option name="pull-pattern-keys" value="perfetto_file_path" />
+ <option name="pull-pattern-keys" value="simpleperf_file_path" />
+ </metrics_collector>
+
+</configuration>
diff --git a/apct-tests/perftests/surfaceflinger/OWNERS b/apct-tests/perftests/surfaceflinger/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/apct-tests/perftests/surfaceflinger/README.md b/apct-tests/perftests/surfaceflinger/README.md
new file mode 100644
index 0000000..0dec70f
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/README.md
@@ -0,0 +1,34 @@
+## SurfaceFlinger performance tests
+
+### Precondition
+To reduce the variance of the test, if `perf-setup.sh` (platform_testing/scripts/perf-setup)
+is available, it is better to use the following instructions to lock CPU and GPU frequencies.
+```
+m perf-setup
+PERF_SETUP_PATH=/data/local/tmp/perf-setup.sh
+adb push $OUT/$PERF_SETUP_PATH $PERF_SETUP_PATH
+adb shell chmod +x $PERF_SETUP_PATH
+adb shell $PERF_SETUP_PATH
+```
+
+### Example to run
+Use `atest`
+```
+atest SurfaceFlingerPerfTests:SurfaceFlingerPerfTest -- \
+ --module-arg SurfaceFlingerPerfTests:instrumentation-arg:kill-bg:=true
+```
+Use `am instrument`
+```
+adb shell am instrument -w -r -e class android.surfaceflinger.SurfaceFlingerPerfTest \
+ -e kill-bg true \
+ com.android.perftests.surfaceflinger/androidx.test.runner.AndroidJUnitRunner
+```
+* `kill-bg` is optional.
+
+Test arguments
+- kill-bg
+ * boolean: Kill background process before running test.
+- profiling-iterations
+ * int: Run the extra iterations with enabling method profiling.
+- profiling-sampling
+ * int: The interval (0=trace each method, default is 10) of sample profiling in microseconds.
diff --git a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/BufferFlinger.java b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/BufferFlinger.java
new file mode 100644
index 0000000..52fb8a6
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/BufferFlinger.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.surfaceflinger;
+
+import android.annotation.ColorInt;
+import android.graphics.Canvas;
+import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.hardware.HardwareBuffer;
+import android.hardware.SyncFence;
+import android.view.SurfaceControl;
+
+import java.util.concurrent.ArrayBlockingQueue;
+
+/**
+ * Allocates n amount of buffers to a SurfaceControl using a Queue implementation. Executes a
+ * releaseCallback so a buffer can be safely re-used.
+ *
+ * @hide
+ */
+public class BufferFlinger {
+ ArrayBlockingQueue<GraphicBuffer> mBufferQ;
+
+ public BufferFlinger(int numOfBuffers, @ColorInt int color) {
+ mBufferQ = new ArrayBlockingQueue<>(numOfBuffers);
+
+ while (numOfBuffers > 0) {
+ GraphicBuffer buffer = GraphicBuffer.create(500, 500,
+ PixelFormat.RGBA_8888,
+ GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER
+ | GraphicBuffer.USAGE_SW_WRITE_RARELY);
+
+ Canvas canvas = buffer.lockCanvas();
+ canvas.drawColor(color);
+ buffer.unlockCanvasAndPost(canvas);
+
+ mBufferQ.add(buffer);
+ numOfBuffers--;
+ }
+ }
+
+ public void addBuffer(SurfaceControl.Transaction t, SurfaceControl surfaceControl)
+ throws InterruptedException {
+ GraphicBuffer buffer = mBufferQ.take();
+ t.setBuffer(surfaceControl,
+ HardwareBuffer.createFromGraphicBuffer(buffer),
+ null,
+ (SyncFence fence) -> {
+ releaseCallback(fence, buffer);
+ });
+ }
+
+ public void releaseCallback(SyncFence fence, GraphicBuffer buffer) {
+ if (fence != null) {
+ fence.awaitForever();
+ }
+ mBufferQ.add(buffer);
+ }
+
+ public void freeBuffers() {
+ for (GraphicBuffer buffer : mBufferQ) {
+ buffer.destroy();
+ }
+ }
+}
diff --git a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java
new file mode 100644
index 0000000..45d164c
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.surfaceflinger;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.view.SurfaceControl;
+
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class SurfaceFlingerPerfTest {
+ protected ActivityScenarioRule<SurfaceFlingerTestActivity> mActivityRule =
+ new ActivityScenarioRule<>(SurfaceFlingerTestActivity.class);
+ protected PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+ private SurfaceFlingerTestActivity mActivity;
+ static final int BUFFER_COUNT = 2;
+
+ @Rule
+ public final RuleChain mAllRules = RuleChain
+ .outerRule(mPerfStatusReporter)
+ .around(mActivityRule);
+ @Before
+ public void setup() {
+ mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
+ }
+
+ @After
+ public void teardown() {
+ mSurfaceControls.forEach(SurfaceControl::release);
+ mByfferTrackers.forEach(BufferFlinger::freeBuffers);
+ }
+
+
+ private ArrayList<BufferFlinger> mByfferTrackers = new ArrayList<>();
+ private BufferFlinger createBufferTracker(int color) {
+ BufferFlinger bufferTracker = new BufferFlinger(BUFFER_COUNT, color);
+ mByfferTrackers.add(bufferTracker);
+ return bufferTracker;
+ }
+
+ private ArrayList<SurfaceControl> mSurfaceControls = new ArrayList<>();
+ private SurfaceControl createSurfaceControl() throws InterruptedException {
+ SurfaceControl sc = mActivity.createChildSurfaceControl();
+ mSurfaceControls.add(sc);
+ return sc;
+ }
+
+ @Test
+ public void singleBuffer() throws Exception {
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ bufferTracker.addBuffer(t, sc);
+ t.show(sc);
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ bufferTracker.addBuffer(t, sc);
+ t.apply();
+ }
+ }
+
+ static int getRandomColorComponent() {
+ return new Random().nextInt(155) + 100;
+ }
+
+ @Test
+ public void multipleBuffers() throws Exception {
+ final int MAX_BUFFERS = 10;
+
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.argb(getRandomColorComponent(),
+ getRandomColorComponent(), getRandomColorComponent(),
+ getRandomColorComponent()));
+ bufferTracker.addBuffer(t, sc);
+ t.setPosition(sc, i * 10, i * 10);
+ t.show(sc);
+ }
+ t.apply(true);
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ mByfferTrackers.get(i).addBuffer(t, mSurfaceControls.get(i));
+ }
+ t.apply();
+ }
+ }
+
+ @Test
+ public void multipleOpaqueBuffers() throws Exception {
+ final int MAX_BUFFERS = 10;
+
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.rgb(getRandomColorComponent(),
+ getRandomColorComponent(), getRandomColorComponent()));
+ bufferTracker.addBuffer(t, sc);
+ t.setOpaque(sc, true);
+ t.setPosition(sc, i * 10, i * 10);
+ t.show(sc);
+ }
+ t.apply(true);
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ mByfferTrackers.get(i).addBuffer(t, mSurfaceControls.get(i));
+ }
+ t.apply();
+ }
+ }
+
+ @Test
+ public void geometryChanges() throws Exception {
+ final int MAX_POSITION = 10;
+ final float MAX_SCALE = 2.0f;
+
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ bufferTracker.addBuffer(t, sc);
+ t.show(sc).apply(true);
+
+ int step = 0;
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ step = ++step % MAX_POSITION;
+ t.setPosition(sc, step, step);
+ float scale = ((step * MAX_SCALE) / MAX_POSITION) + 0.5f;
+ t.setScale(sc, scale, scale);
+ t.apply();
+ }
+ }
+
+ @Test
+ public void geometryWithBufferChanges() throws Exception {
+ final int MAX_POSITION = 10;
+
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ bufferTracker.addBuffer(t, sc);
+ t.show(sc).apply(true);
+
+ int step = 0;
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ step = ++step % MAX_POSITION;
+ t.setPosition(sc, step, step);
+ float scale = ((step * 2.0f) / MAX_POSITION) + 0.5f;
+ t.setScale(sc, scale, scale);
+ bufferTracker.addBuffer(t, sc);
+ t.apply();
+ }
+ }
+
+ @Test
+ public void addRemoveLayers() throws Exception {
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ SurfaceControl childSurfaceControl = new SurfaceControl.Builder()
+ .setName("childLayer").setBLASTLayer().build();
+ bufferTracker.addBuffer(t, childSurfaceControl);
+ t.reparent(childSurfaceControl, sc);
+ t.apply();
+ t.remove(childSurfaceControl).apply();
+ }
+ }
+
+ @Test
+ public void displayScreenshot() throws Exception {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Bitmap screenshot =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot();
+ screenshot.recycle();
+ }
+ }
+
+ @Test
+ public void layerScreenshot() throws Exception {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Bitmap screenshot =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot(
+ mActivity.getWindow());
+ screenshot.recycle();
+ }
+ }
+
+}
diff --git a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java
new file mode 100644
index 0000000..832a0cd
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.surfaceflinger;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.SurfaceControl;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.WindowManager;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * A simple activity used for testing, e.g. performance of activity switching, or as a base
+ * container of testing view.
+ */
+public class SurfaceFlingerTestActivity extends Activity {
+ public TestSurfaceView mTestSurfaceView;
+ SurfaceControl mSurfaceControl;
+ CountDownLatch mIsReady = new CountDownLatch(1);
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ mTestSurfaceView = new TestSurfaceView(this);
+ setContentView(mTestSurfaceView);
+ }
+
+ public SurfaceControl createChildSurfaceControl() throws InterruptedException {
+ return mTestSurfaceView.getChildSurfaceControlHelper();
+ }
+
+ public class TestSurfaceView extends SurfaceView {
+ public TestSurfaceView(Context context) {
+ super(context);
+ SurfaceHolder holder = getHolder();
+ holder.addCallback(new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ mIsReady.countDown();
+ }
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width,
+ int height) {}
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ }
+ });
+ }
+
+ public SurfaceControl getChildSurfaceControlHelper() throws InterruptedException {
+ mIsReady.await();
+ SurfaceHolder holder = getHolder();
+
+ // check to see if surface is valid
+ if (holder.getSurface().isValid()) {
+ mSurfaceControl = getSurfaceControl();
+ }
+ return new SurfaceControl.Builder()
+ .setName("ChildSurfaceControl")
+ .setParent(mSurfaceControl)
+ .build();
+ }
+ }
+}
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 19de1a5..2b09e6ba 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -286,7 +286,8 @@
method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void setActiveDream(@Nullable android.content.ComponentName);
method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void setDreamOverlay(@Nullable android.content.ComponentName);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setScreensaverEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void startDream(@NonNull android.content.ComponentName);
+ method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void setSystemDreamComponent(@Nullable android.content.ComponentName);
+ method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void startDream();
method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void stopDream();
}
@@ -2412,6 +2413,16 @@
method public final boolean shouldShowComplications();
}
+ public class DreamService extends android.app.Service implements android.view.Window.Callback {
+ method @Nullable public static android.service.dreams.DreamService.DreamMetadata getDreamMetadata(@NonNull android.content.Context, @Nullable android.content.pm.ServiceInfo);
+ }
+
+ public static final class DreamService.DreamMetadata {
+ field @Nullable public final android.graphics.drawable.Drawable previewImage;
+ field @Nullable public final android.content.ComponentName settingsActivity;
+ field @NonNull public final boolean showComplications;
+ }
+
}
package android.service.notification {
@@ -3398,11 +3409,13 @@
method @NonNull public android.window.WindowContainerTransaction createTaskFragment(@NonNull android.window.TaskFragmentCreationParams);
method @NonNull public android.window.WindowContainerTransaction deleteTaskFragment(@NonNull android.window.WindowContainerToken);
method public int describeContents();
+ method @NonNull public android.window.WindowContainerTransaction removeTask(@NonNull android.window.WindowContainerToken);
method @NonNull public android.window.WindowContainerTransaction reorder(@NonNull android.window.WindowContainerToken, boolean);
method @NonNull public android.window.WindowContainerTransaction reparent(@NonNull android.window.WindowContainerToken, @Nullable android.window.WindowContainerToken, boolean);
method @NonNull public android.window.WindowContainerTransaction reparentActivityToTaskFragment(@NonNull android.os.IBinder, @NonNull android.os.IBinder);
method @NonNull public android.window.WindowContainerTransaction reparentChildren(@NonNull android.window.WindowContainerToken, @Nullable android.window.WindowContainerToken);
method @NonNull public android.window.WindowContainerTransaction reparentTasks(@Nullable android.window.WindowContainerToken, @Nullable android.window.WindowContainerToken, @Nullable int[], @Nullable int[], boolean);
+ method @NonNull public android.window.WindowContainerTransaction requestFocusOnTaskFragment(@NonNull android.os.IBinder);
method @NonNull public android.window.WindowContainerTransaction scheduleFinishEnterPip(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setActivityWindowingMode(@NonNull android.window.WindowContainerToken, int);
method @NonNull public android.window.WindowContainerTransaction setAdjacentRoots(@NonNull android.window.WindowContainerToken, @NonNull android.window.WindowContainerToken);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index a70a1a8..51efdba 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -534,9 +534,8 @@
// A reusable token for other purposes, e.g. content capture, translation. It shouldn't be
// used without security checks
public IBinder shareableActivityToken;
- // The token of the initial TaskFragment that embedded this activity. Do not rely on it
- // after creation because the activity could be reparented.
- @Nullable public IBinder mInitialTaskFragmentToken;
+ // The token of the TaskFragment that embedded this activity.
+ @Nullable public IBinder mTaskFragmentToken;
int ident;
@UnsupportedAppUsage
Intent intent;
@@ -620,7 +619,7 @@
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client,
IBinder assistToken, IBinder shareableActivityToken, boolean launchedFromBubble,
- IBinder initialTaskFragmentToken) {
+ IBinder taskFragmentToken) {
this.token = token;
this.assistToken = assistToken;
this.shareableActivityToken = shareableActivityToken;
@@ -641,7 +640,7 @@
compatInfo);
mActivityOptions = activityOptions;
mLaunchedFromBubble = launchedFromBubble;
- mInitialTaskFragmentToken = initialTaskFragmentToken;
+ mTaskFragmentToken = taskFragmentToken;
init();
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 692d3f3..cb64173 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1906,7 +1906,6 @@
OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
OP_SCHEDULE_EXACT_ALARM,
OP_MANAGE_MEDIA,
- OP_GET_USAGE_STATS,
};
/**
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index c0aebee..7bfb1b5 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -48,6 +48,13 @@
private String mPkg;
/**
+ * The maximum string length for any string contained in this automatic zen rule. This pertains
+ * both to fields in the rule itself (such as its name) and items with sub-fields.
+ * @hide
+ */
+ public static final int MAX_STRING_LENGTH = 1000;
+
+ /**
* Creates an automatic zen rule.
*
* @param name The name of the rule.
@@ -93,10 +100,10 @@
public AutomaticZenRule(@NonNull String name, @Nullable ComponentName owner,
@Nullable ComponentName configurationActivity, @NonNull Uri conditionId,
@Nullable ZenPolicy policy, int interruptionFilter, boolean enabled) {
- this.name = name;
- this.owner = owner;
- this.configurationActivity = configurationActivity;
- this.conditionId = conditionId;
+ this.name = getTrimmedString(name);
+ this.owner = getTrimmedComponentName(owner);
+ this.configurationActivity = getTrimmedComponentName(configurationActivity);
+ this.conditionId = getTrimmedUri(conditionId);
this.interruptionFilter = interruptionFilter;
this.enabled = enabled;
this.mZenPolicy = policy;
@@ -115,12 +122,14 @@
public AutomaticZenRule(Parcel source) {
enabled = source.readInt() == ENABLED;
if (source.readInt() == ENABLED) {
- name = source.readString();
+ name = getTrimmedString(source.readString());
}
interruptionFilter = source.readInt();
- conditionId = source.readParcelable(null, android.net.Uri.class);
- owner = source.readParcelable(null, android.content.ComponentName.class);
- configurationActivity = source.readParcelable(null, android.content.ComponentName.class);
+ conditionId = getTrimmedUri(source.readParcelable(null, android.net.Uri.class));
+ owner = getTrimmedComponentName(
+ source.readParcelable(null, android.content.ComponentName.class));
+ configurationActivity = getTrimmedComponentName(
+ source.readParcelable(null, android.content.ComponentName.class));
creationTime = source.readLong();
mZenPolicy = source.readParcelable(null, android.service.notification.ZenPolicy.class);
mModified = source.readInt() == ENABLED;
@@ -196,7 +205,7 @@
* Sets the representation of the state that causes this rule to become active.
*/
public void setConditionId(Uri conditionId) {
- this.conditionId = conditionId;
+ this.conditionId = getTrimmedUri(conditionId);
}
/**
@@ -211,7 +220,7 @@
* Sets the name of this rule.
*/
public void setName(String name) {
- this.name = name;
+ this.name = getTrimmedString(name);
}
/**
@@ -243,7 +252,7 @@
* that are not backed by {@link android.service.notification.ConditionProviderService}.
*/
public void setConfigurationActivity(@Nullable ComponentName componentName) {
- this.configurationActivity = componentName;
+ this.configurationActivity = getTrimmedComponentName(componentName);
}
/**
@@ -333,4 +342,35 @@
return new AutomaticZenRule[size];
}
};
+
+ /**
+ * If the package or class name of the provided ComponentName are longer than MAX_STRING_LENGTH,
+ * return a trimmed version that truncates each of the package and class name at the max length.
+ */
+ private static ComponentName getTrimmedComponentName(ComponentName cn) {
+ if (cn == null) return null;
+ return new ComponentName(getTrimmedString(cn.getPackageName()),
+ getTrimmedString(cn.getClassName()));
+ }
+
+ /**
+ * Returns a truncated copy of the string if the string is longer than MAX_STRING_LENGTH.
+ */
+ private static String getTrimmedString(String input) {
+ if (input != null && input.length() > MAX_STRING_LENGTH) {
+ return input.substring(0, MAX_STRING_LENGTH);
+ }
+ return input;
+ }
+
+ /**
+ * Returns a truncated copy of the Uri by trimming the string representation to the maximum
+ * string length.
+ */
+ private static Uri getTrimmedUri(Uri input) {
+ if (input != null && input.toString().length() > MAX_STRING_LENGTH) {
+ return Uri.parse(getTrimmedString(input.toString()));
+ }
+ return input;
+ }
}
diff --git a/core/java/android/app/DreamManager.java b/core/java/android/app/DreamManager.java
index 00af1c02..7c8b0fd 100644
--- a/core/java/android/app/DreamManager.java
+++ b/core/java/android/app/DreamManager.java
@@ -18,7 +18,6 @@
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
@@ -86,16 +85,23 @@
}
/**
- * Starts dream service with name "name".
+ * Starts dreaming.
+ *
+ * The system dream component, if set by {@link DreamManager#setSystemDreamComponent}, will be
+ * started.
+ * Otherwise, starts the active dream set by {@link DreamManager#setActiveDream}.
*
* <p>This is only used for testing the dream service APIs.
*
+ * @see DreamManager#setActiveDream(ComponentName)
+ * @see DreamManager#setSystemDreamComponent(ComponentName)
+ *
* @hide
*/
@TestApi
@UserHandleAware
@RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)
- public void startDream(@NonNull ComponentName name) {
+ public void startDream() {
try {
mService.dream();
} catch (RemoteException e) {
@@ -142,6 +148,25 @@
}
/**
+ * Sets or clears the system dream component.
+ *
+ * The system dream component, when set, will be shown instead of the user configured dream
+ * when the system starts dreaming (not dozing). If the system is dreaming at the time the
+ * system dream is set or cleared, it immediately switches dream.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)
+ public void setSystemDreamComponent(@Nullable ComponentName dreamComponent) {
+ try {
+ mService.setSystemDreamComponent(dreamComponent);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Sets the active dream on the device to be "dreamComponent".
*
* <p>This is only used for testing the dream service APIs.
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 02be051..52732d3 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -72,6 +72,7 @@
import android.view.IWindowFocusObserver;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationAdapter;
+import android.window.BackAnimationAdaptor;
import android.window.IWindowOrganizerController;
import android.window.BackNavigationInfo;
import android.window.SplashScreenView;
@@ -356,5 +357,5 @@
* @param focusObserver a remote callback to nofify shell when the focused window lost focus.
*/
android.window.BackNavigationInfo startBackNavigation(in boolean requestAnimation,
- in IWindowFocusObserver focusObserver);
+ in IWindowFocusObserver focusObserver, in BackAnimationAdaptor adaptor);
}
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index 807bd57..2b245aa 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -20,7 +20,6 @@
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
-import android.content.pm.ParceledListSlice;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -68,7 +67,7 @@
private CharSequence mName;
private String mDescription;
private boolean mBlocked;
- private ParceledListSlice<NotificationChannel> mChannels;
+ private List<NotificationChannel> mChannels = new ArrayList<>();
// Bitwise representation of fields that have been changed by the user
private int mUserLockedFields;
@@ -103,8 +102,7 @@
} else {
mDescription = null;
}
- mChannels = in.readParcelable(
- NotificationChannelGroup.class.getClassLoader(), ParceledListSlice.class);
+ in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader(), android.app.NotificationChannel.class);
mBlocked = in.readBoolean();
mUserLockedFields = in.readInt();
}
@@ -131,7 +129,7 @@
} else {
dest.writeByte((byte) 0);
}
- dest.writeParcelable(mChannels, flags);
+ dest.writeParcelableList(mChannels, flags);
dest.writeBoolean(mBlocked);
dest.writeInt(mUserLockedFields);
}
@@ -161,7 +159,7 @@
* Returns the list of channels that belong to this group
*/
public List<NotificationChannel> getChannels() {
- return mChannels == null ? new ArrayList<>() : mChannels.getList();
+ return mChannels;
}
/**
@@ -195,8 +193,15 @@
/**
* @hide
*/
+ public void addChannel(NotificationChannel channel) {
+ mChannels.add(channel);
+ }
+
+ /**
+ * @hide
+ */
public void setChannels(List<NotificationChannel> channels) {
- mChannels = new ParceledListSlice<>(channels);
+ mChannels = channels;
}
/**
@@ -331,7 +336,7 @@
proto.write(NotificationChannelGroupProto.NAME, mName.toString());
proto.write(NotificationChannelGroupProto.DESCRIPTION, mDescription);
proto.write(NotificationChannelGroupProto.IS_BLOCKED, mBlocked);
- for (NotificationChannel channel : mChannels.getList()) {
+ for (NotificationChannel channel : mChannels) {
channel.dumpDebug(proto, NotificationChannelGroupProto.CHANNELS);
}
proto.end(token);
diff --git a/core/java/android/app/ambientcontext/AmbientContextCallback.java b/core/java/android/app/ambientcontext/AmbientContextCallback.java
new file mode 100644
index 0000000..9133d7f
--- /dev/null
+++ b/core/java/android/app/ambientcontext/AmbientContextCallback.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.ambientcontext;
+
+import android.annotation.NonNull;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Callback for listening to Ambient Context events and status changes. See {@link
+ * AmbientContextManager#registerObserver(AmbientContextEventRequest, AmbientContextCallback,
+ * Executor)}
+ *
+ * @hide
+ */
+public interface AmbientContextCallback {
+ /**
+ * Called when AmbientContextManager service detects events.
+ *
+ * @param events a list of detected events.
+ */
+ void onEvents(@NonNull List<AmbientContextEvent> events);
+
+ /**
+ * Called with a statusCode when
+ * {@link AmbientContextManager#registerObserver(AmbientContextEventRequest,
+ * Executor, AmbientContextCallback)} completes, to indicate if the registration is successful
+ *
+ * @param statusCode the status of the service.
+ */
+ void onRegistrationComplete(@NonNull @AmbientContextManager.StatusCode int statusCode);
+}
diff --git a/core/java/android/app/ambientcontext/AmbientContextEvent.java b/core/java/android/app/ambientcontext/AmbientContextEvent.java
index 11e695ad..af48fde 100644
--- a/core/java/android/app/ambientcontext/AmbientContextEvent.java
+++ b/core/java/android/app/ambientcontext/AmbientContextEvent.java
@@ -59,11 +59,21 @@
*/
public static final int EVENT_SNORE = 2;
+ /**
+ * The integer indicating a double-tap event was detected.
+ * For detecting this event type, there's no specific consent activity to request access, but
+ * the consent is implied through the double tap toggle in the Settings app.
+ *
+ * @hide
+ */
+ public static final int EVENT_BACK_DOUBLE_TAP = 3;
+
/** @hide */
@IntDef(prefix = { "EVENT_" }, value = {
EVENT_UNKNOWN,
EVENT_COUGH,
EVENT_SNORE,
+ EVENT_BACK_DOUBLE_TAP,
}) public @interface EventCode {}
/** The integer indicating an unknown level. */
@@ -150,7 +160,8 @@
@IntDef(prefix = "EVENT_", value = {
EVENT_UNKNOWN,
EVENT_COUGH,
- EVENT_SNORE
+ EVENT_SNORE,
+ EVENT_BACK_DOUBLE_TAP
})
@Retention(RetentionPolicy.SOURCE)
@DataClass.Generated.Member
@@ -166,6 +177,8 @@
return "EVENT_COUGH";
case EVENT_SNORE:
return "EVENT_SNORE";
+ case EVENT_BACK_DOUBLE_TAP:
+ return "EVENT_BACK_DOUBLE_TAP";
default: return Integer.toHexString(value);
}
}
@@ -478,10 +491,10 @@
}
@DataClass.Generated(
- time = 1642040319323L,
+ time = 1659950304931L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/app/ambientcontext/AmbientContextEvent.java",
- inputSignatures = "public static final int EVENT_UNKNOWN\npublic static final int EVENT_COUGH\npublic static final int EVENT_SNORE\npublic static final int LEVEL_UNKNOWN\npublic static final int LEVEL_LOW\npublic static final int LEVEL_MEDIUM_LOW\npublic static final int LEVEL_MEDIUM\npublic static final int LEVEL_MEDIUM_HIGH\npublic static final int LEVEL_HIGH\nprivate final @android.app.ambientcontext.AmbientContextEvent.EventCode int mEventType\nprivate final @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) @android.annotation.NonNull java.time.Instant mStartTime\nprivate final @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) @android.annotation.NonNull java.time.Instant mEndTime\nprivate final @android.app.ambientcontext.AmbientContextEvent.LevelValue int mConfidenceLevel\nprivate final @android.app.ambientcontext.AmbientContextEvent.LevelValue int mDensityLevel\nprivate static int defaultEventType()\nprivate static @android.annotation.NonNull java.time.Instant defaultStartTime()\nprivate static @android.annotation.NonNull java.time.Instant defaultEndTime()\nprivate static int defaultConfidenceLevel()\nprivate static int defaultDensityLevel()\nclass AmbientContextEvent extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=false, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+ inputSignatures = "public static final int EVENT_UNKNOWN\npublic static final int EVENT_COUGH\npublic static final int EVENT_SNORE\npublic static final int EVENT_BACK_DOUBLE_TAP\npublic static final int LEVEL_UNKNOWN\npublic static final int LEVEL_LOW\npublic static final int LEVEL_MEDIUM_LOW\npublic static final int LEVEL_MEDIUM\npublic static final int LEVEL_MEDIUM_HIGH\npublic static final int LEVEL_HIGH\nprivate final @android.app.ambientcontext.AmbientContextEvent.EventCode int mEventType\nprivate final @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) @android.annotation.NonNull java.time.Instant mStartTime\nprivate final @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) @android.annotation.NonNull java.time.Instant mEndTime\nprivate final @android.app.ambientcontext.AmbientContextEvent.LevelValue int mConfidenceLevel\nprivate final @android.app.ambientcontext.AmbientContextEvent.LevelValue int mDensityLevel\nprivate static int defaultEventType()\nprivate static @android.annotation.NonNull java.time.Instant defaultStartTime()\nprivate static @android.annotation.NonNull java.time.Instant defaultEndTime()\nprivate static int defaultConfidenceLevel()\nprivate static int defaultDensityLevel()\nclass AmbientContextEvent extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=false, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/app/ambientcontext/AmbientContextManager.java b/core/java/android/app/ambientcontext/AmbientContextManager.java
index 7f913e7..e45dfdf 100644
--- a/core/java/android/app/ambientcontext/AmbientContextManager.java
+++ b/core/java/android/app/ambientcontext/AmbientContextManager.java
@@ -153,7 +153,7 @@
* eventTypes.add(AmbientContextEvent.EVENT_SNORE);
*
* // Create Consumer
- * Consumer<Integer> statusConsumer = response -> {
+ * Consumer<Integer> statusConsumer = status -> {
* int status = status.getStatusCode();
* if (status == AmbientContextManager.STATUS_SUCCESS) {
* // Show user it's enabled
@@ -282,7 +282,7 @@
Preconditions.checkArgument(!resultPendingIntent.isImmutable());
try {
RemoteCallback callback = new RemoteCallback(result -> {
- int statusCode = result.getInt(STATUS_RESPONSE_BUNDLE_KEY);
+ int statusCode = result.getInt(STATUS_RESPONSE_BUNDLE_KEY);
final long identity = Binder.clearCallingIdentity();
try {
executor.execute(() -> statusConsumer.accept(statusCode));
@@ -297,6 +297,72 @@
}
/**
+ * Allows app to register as a {@link AmbientContextEvent} observer. Same as {@link
+ * #registerObserver(AmbientContextEventRequest, PendingIntent, Executor, Consumer)},
+ * but use {@link AmbientContextCallback} instead of {@link PendingIntent} as a callback on
+ * detected events.
+ * Registering another observer from the same package that has already been
+ * registered will override the previous observer. If the same app previously calls
+ * {@link #registerObserver(AmbientContextEventRequest, AmbientContextCallback, Executor)},
+ * and now calls
+ * {@link #registerObserver(AmbientContextEventRequest, PendingIntent, Executor, Consumer)},
+ * the previous observer will be replaced with the new observer with the PendingIntent callback.
+ * Or vice versa.
+ *
+ * When the registration completes, a status will be returned to client through
+ * {@link AmbientContextCallback#onRegistrationComplete(int)}.
+ * If the AmbientContextManager service is not enabled yet, or the underlying detection service
+ * is not running yet, {@link AmbientContextManager#STATUS_SERVICE_UNAVAILABLE} will be
+ * returned, and the detection won't be really started.
+ * If the underlying detection service feature is not enabled, or the requested event type is
+ * not enabled yet, {@link AmbientContextManager#STATUS_NOT_SUPPORTED} will be returned, and the
+ * detection won't be really started.
+ * If there is no user consent, {@link AmbientContextManager#STATUS_ACCESS_DENIED} will be
+ * returned, and the detection won't be really started.
+ * Otherwise, it will try to start the detection. And if it starts successfully, it will return
+ * {@link AmbientContextManager#STATUS_SUCCESS}. If it fails to start the detection, then
+ * it will return {@link AmbientContextManager#STATUS_SERVICE_UNAVAILABLE}
+ * After registerObserver succeeds and when the service detects an event, the service will
+ * trigger {@link AmbientContextCallback#onEvents(List)}.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT)
+ public void registerObserver(
+ @NonNull AmbientContextEventRequest request,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull AmbientContextCallback ambientContextCallback) {
+ try {
+ IAmbientContextObserver observer = new IAmbientContextObserver.Stub() {
+ @Override
+ public void onEvents(List<AmbientContextEvent> events) throws RemoteException {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> ambientContextCallback.onEvents(events));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void onRegistrationComplete(int statusCode) throws RemoteException {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(
+ () -> ambientContextCallback.onRegistrationComplete(statusCode));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ };
+
+ mService.registerObserverWithCallback(request, mContext.getPackageName(), observer);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Unregisters the requesting app as an {@code AmbientContextEvent} observer. Unregistering an
* observer that was already unregistered or never registered will have no effect.
*/
diff --git a/core/java/android/app/ambientcontext/IAmbientContextManager.aidl b/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
index 0d9ecfd..8f06e76 100644
--- a/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
+++ b/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
@@ -18,6 +18,7 @@
import android.app.PendingIntent;
import android.app.ambientcontext.AmbientContextEventRequest;
+import android.app.ambientcontext.IAmbientContextObserver;
import android.os.RemoteCallback;
/**
@@ -29,6 +30,11 @@
void registerObserver(in AmbientContextEventRequest request,
in PendingIntent resultPendingIntent,
in RemoteCallback statusCallback);
+
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT)")
+ void registerObserverWithCallback(in AmbientContextEventRequest request,
+ String packageName,
+ in IAmbientContextObserver observer);
void unregisterObserver(in String callingPackage);
void queryServiceStatus(in int[] eventTypes, in String callingPackage,
in RemoteCallback statusCallback);
diff --git a/core/java/android/app/ambientcontext/IAmbientContextObserver.aidl b/core/java/android/app/ambientcontext/IAmbientContextObserver.aidl
new file mode 100644
index 0000000..529e2fe
--- /dev/null
+++ b/core/java/android/app/ambientcontext/IAmbientContextObserver.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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 android.app.ambientcontext;
+
+import android.app.ambientcontext.AmbientContextEvent;
+
+/**
+ * Callback interface of AmbientContextManager.
+ *
+ * @hide
+ */
+oneway interface IAmbientContextObserver {
+ void onEvents(in List<AmbientContextEvent> events);
+ void onRegistrationComplete(in int statusCode);
+}
+
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index fe81df0..cc303fb 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -70,7 +70,7 @@
private final Handler mHandler;
private final int mHostId;
private final Callbacks mCallbacks;
- private final SparseArray<AppWidgetHostView> mViews = new SparseArray<>();
+ private final SparseArray<AppWidgetHostListener> mListeners = new SparseArray<>();
private InteractionHandler mInteractionHandler;
static class Callbacks extends IAppWidgetHost.Stub {
@@ -171,6 +171,15 @@
this(context, hostId, null, context.getMainLooper());
}
+ @Nullable
+ private AppWidgetHostListener getListener(final int appWidgetId) {
+ AppWidgetHostListener tempListener = null;
+ synchronized (mListeners) {
+ tempListener = mListeners.get(appWidgetId);
+ }
+ return tempListener;
+ }
+
/**
* @hide
*/
@@ -210,11 +219,11 @@
return;
}
final int[] idsToUpdate;
- synchronized (mViews) {
- int N = mViews.size();
- idsToUpdate = new int[N];
- for (int i = 0; i < N; i++) {
- idsToUpdate[i] = mViews.keyAt(i);
+ synchronized (mListeners) {
+ int n = mListeners.size();
+ idsToUpdate = new int[n];
+ for (int i = 0; i < n; i++) {
+ idsToUpdate[i] = mListeners.keyAt(i);
}
}
List<PendingHostUpdate> updates;
@@ -349,14 +358,11 @@
if (sService == null) {
return;
}
- synchronized (mViews) {
- mViews.remove(appWidgetId);
- try {
- sService.deleteAppWidgetId(mContextOpPackageName, appWidgetId);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
+ removeListener(appWidgetId);
+ try {
+ sService.deleteAppWidgetId(mContextOpPackageName, appWidgetId);
+ } catch (RemoteException e) {
+ throw new RuntimeException("system server dead?", e);
}
}
@@ -412,9 +418,7 @@
AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
view.setInteractionHandler(mInteractionHandler);
view.setAppWidget(appWidgetId, appWidget);
- synchronized (mViews) {
- mViews.put(appWidgetId, view);
- }
+ addListener(appWidgetId, view);
RemoteViews views;
try {
views = sService.getAppWidgetViews(mContextOpPackageName, appWidgetId);
@@ -439,24 +443,52 @@
* Called when the AppWidget provider for a AppWidget has been upgraded to a new apk.
*/
protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) {
- AppWidgetHostView v;
+ AppWidgetHostListener v = getListener(appWidgetId);
// Convert complex to dp -- we are getting the AppWidgetProviderInfo from the
// AppWidgetService, which doesn't have our context, hence we need to do the
// conversion here.
appWidget.updateDimensions(mDisplayMetrics);
- synchronized (mViews) {
- v = mViews.get(appWidgetId);
- }
if (v != null) {
- v.resetAppWidget(appWidget);
+ v.onUpdateProviderInfo(appWidget);
}
}
+ /**
+ * This interface specifies the actions to be performed on the app widget based on the calls
+ * from the service
+ *
+ * @hide
+ */
+ public interface AppWidgetHostListener {
+
+ /**
+ * This function is called when the service want to reset the app widget provider info
+ * @param appWidget The new app widget provider info
+ *
+ * @hide
+ */
+ void onUpdateProviderInfo(@Nullable AppWidgetProviderInfo appWidget);
+
+ /**
+ * This function is called when the RemoteViews of the app widget is updated
+ * @param views The new RemoteViews to be set for the app widget
+ *
+ * @hide
+ */
+ void updateAppWidget(@Nullable RemoteViews views);
+
+ /**
+ * This function is called when the view ID is changed for the app widget
+ * @param viewId The new view ID to be be set for the widget
+ *
+ * @hide
+ */
+ void onViewDataChanged(int viewId);
+ }
+
void dispatchOnAppWidgetRemoved(int appWidgetId) {
- synchronized (mViews) {
- mViews.remove(appWidgetId);
- }
+ removeListener(appWidgetId);
onAppWidgetRemoved(appWidgetId);
}
@@ -476,23 +508,43 @@
// Does nothing
}
- void updateAppWidgetView(int appWidgetId, RemoteViews views) {
- AppWidgetHostView v;
- synchronized (mViews) {
- v = mViews.get(appWidgetId);
+ /**
+ * Create an AppWidgetHostListener for the given widget.
+ * The AppWidgetHost retains a pointer to the newly-created listener.
+ * @param appWidgetId The ID of the app widget for which to add the listener
+ * @param listener The listener interface that deals with actions towards the widget view
+ *
+ * @hide
+ */
+ public void addListener(int appWidgetId, @NonNull AppWidgetHostListener listener) {
+ synchronized (mListeners) {
+ mListeners.put(appWidgetId, listener);
}
+ }
+
+ /**
+ * Delete the listener for the given widget
+ * @param appWidgetId The ID of the app widget for which the listener is to be deleted
+
+ * @hide
+ */
+ public void removeListener(int appWidgetId) {
+ synchronized (mListeners) {
+ mListeners.remove(appWidgetId);
+ }
+ }
+
+ void updateAppWidgetView(int appWidgetId, RemoteViews views) {
+ AppWidgetHostListener v = getListener(appWidgetId);
if (v != null) {
v.updateAppWidget(views);
}
}
void viewDataChanged(int appWidgetId, int viewId) {
- AppWidgetHostView v;
- synchronized (mViews) {
- v = mViews.get(appWidgetId);
- }
+ AppWidgetHostListener v = getListener(appWidgetId);
if (v != null) {
- v.viewDataChanged(viewId);
+ v.onViewDataChanged(viewId);
}
}
@@ -500,8 +552,8 @@
* Clear the list of Views that have been created by this AppWidgetHost.
*/
protected void clearViews() {
- synchronized (mViews) {
- mViews.clear();
+ synchronized (mListeners) {
+ mListeners.clear();
}
}
}
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index e3bca9c..fe10b7f 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -66,7 +66,7 @@
* between updates, and will try recycling old views for each incoming
* {@link RemoteViews}.
*/
-public class AppWidgetHostView extends FrameLayout {
+public class AppWidgetHostView extends FrameLayout implements AppWidgetHost.AppWidgetHostListener {
static final String TAG = "AppWidgetHostView";
private static final String KEY_JAILED_ARRAY = "jail";
@@ -492,8 +492,11 @@
/**
* Update the AppWidgetProviderInfo for this view, and reset it to the
* initial layout.
+ *
+ * @hide
*/
- void resetAppWidget(AppWidgetProviderInfo info) {
+ @Override
+ public void onUpdateProviderInfo(@Nullable AppWidgetProviderInfo info) {
setAppWidget(mAppWidgetId, info);
mViewMode = VIEW_MODE_NOINIT;
updateAppWidget(null);
@@ -503,6 +506,7 @@
* Process a set of {@link RemoteViews} coming in as an update from the
* AppWidget provider. Will animate into these new views as needed
*/
+ @Override
public void updateAppWidget(RemoteViews remoteViews) {
mLastInflatedRemoteViews = remoteViews;
applyRemoteViews(remoteViews, true);
@@ -693,8 +697,11 @@
/**
* Process data-changed notifications for the specified view in the specified
* set of {@link RemoteViews} views.
+ *
+ * @hide
*/
- void viewDataChanged(int viewId) {
+ @Override
+ public void onViewDataChanged(int viewId) {
View v = findViewById(viewId);
if ((v != null) && (v instanceof AdapterView<?>)) {
AdapterView<?> adapterView = (AdapterView<?>) v;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 0bbe8c4..4be5e14 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1119,6 +1119,16 @@
public static final long OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN = 208648326L;
/**
+ * Overrides the min aspect ratio restriction in portrait fullscreen in order to use all
+ * available screen space.
+ * @hide
+ */
+ @ChangeId
+ @Disabled
+ @Overridable
+ public static final long OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN = 218959984L;
+
+ /**
* Compares activity window layout min width/height with require space for multi window to
* determine if it can be put into multi window mode.
*/
diff --git a/core/java/android/hardware/biometrics/IBiometricContextListener.aidl b/core/java/android/hardware/biometrics/IBiometricContextListener.aidl
index 55cab52..2e8e763 100644
--- a/core/java/android/hardware/biometrics/IBiometricContextListener.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricContextListener.aidl
@@ -23,5 +23,8 @@
* @hide
*/
oneway interface IBiometricContextListener {
- void onDozeChanged(boolean isDozing);
+ // Called when doze or awake (screen on) status changes.
+ // These may be called while the device is still transitioning to the new state
+ // (i.e. about to become awake or enter doze)
+ void onDozeChanged(boolean isDozing, boolean isAwake);
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index d6d3a97..dff2f7e 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -1204,6 +1204,20 @@
* to begin with, {@link #onPhysicalCameraUnavailable} may be invoked after
* {@link #onCameraAvailable}.</p>
*
+ * <p>Limitation: Opening a logical camera disables the {@link #onPhysicalCameraAvailable}
+ * and {@link #onPhysicalCameraUnavailable} callbacks for its physical cameras. For example,
+ * if app A opens the camera device:</p>
+ *
+ * <ul>
+ *
+ * <li>All apps subscribing to ActivityCallback get {@link #onCameraUnavailable}.</li>
+ *
+ * <li>No app (including app A) subscribing to ActivityCallback gets
+ * {@link #onPhysicalCameraAvailable} or {@link #onPhysicalCameraUnavailable}, because
+ * the logical camera is unavailable (some app is using it).</li>
+ *
+ * </ul>
+ *
* <p>The default implementation of this method does nothing.</p>
*
* @param cameraId The unique identifier of the logical multi-camera.
@@ -1221,11 +1235,24 @@
* A previously-available physical camera has become unavailable for use.
*
* <p>By default, all of the physical cameras of a logical multi-camera are
- * available, so {@link #onPhysicalCameraAvailable} is not called for any of the physical
- * cameras of a logical multi-camera, when {@link #onCameraAvailable} for the logical
- * multi-camera is invoked. If some specific physical cameras are unavailable
- * to begin with, {@link #onPhysicalCameraUnavailable} may be invoked after
- * {@link #onCameraAvailable}.</p>
+ * unavailable if the logical camera itself is unavailable.
+ * No availability callbacks will be called for any of the physical
+ * cameras of its parent logical multi-camera, when {@link #onCameraUnavailable} for
+ * the logical multi-camera is invoked.</p>
+ *
+ * <p>Limitation: Opening a logical camera disables the {@link #onPhysicalCameraAvailable}
+ * and {@link #onPhysicalCameraUnavailable} callbacks for its physical cameras. For example,
+ * if app A opens the camera device:</p>
+ *
+ * <ul>
+ *
+ * <li>All apps subscribing to ActivityCallback get {@link #onCameraUnavailable}.</li>
+ *
+ * <li>No app (including app A) subscribing to ActivityCallback gets
+ * {@link #onPhysicalCameraAvailable} or {@link #onPhysicalCameraUnavailable}, because
+ * the logical camera is unavailable (some app is using it).</li>
+ *
+ * </ul>
*
* <p>The default implementation of this method does nothing.</p>
*
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index c614cdb..72d8122 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -1433,10 +1433,17 @@
}
@NonNull
- private static float[] createEnrollStageThresholds(@NonNull Context context) {
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ private float[] createEnrollStageThresholds(@NonNull Context context) {
// TODO(b/200604947): Fetch this value from FingerprintService, rather than internal config
- final String[] enrollStageThresholdStrings = context.getResources().getStringArray(
- com.android.internal.R.array.config_udfps_enroll_stage_thresholds);
+ final String[] enrollStageThresholdStrings;
+ if (isPowerbuttonFps()) {
+ enrollStageThresholdStrings = context.getResources().getStringArray(
+ com.android.internal.R.array.config_sfps_enroll_stage_thresholds);
+ } else {
+ enrollStageThresholdStrings = context.getResources().getStringArray(
+ com.android.internal.R.array.config_udfps_enroll_stage_thresholds);
+ }
final float[] enrollStageThresholds = new float[enrollStageThresholdStrings.length];
for (int i = 0; i < enrollStageThresholds.length; i++) {
diff --git a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java
index be57372..d6f191e 100644
--- a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java
+++ b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java
@@ -37,6 +37,7 @@
import android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest;
import android.os.PersistableBundle;
import android.util.ArraySet;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.vcn.util.PersistableBundleUtils;
@@ -58,6 +59,8 @@
*/
@VisibleForTesting(visibility = Visibility.PRIVATE)
public final class IkeSessionParamsUtils {
+ private static final String TAG = IkeSessionParamsUtils.class.getSimpleName();
+
private static final String SERVER_HOST_NAME_KEY = "SERVER_HOST_NAME_KEY";
private static final String SA_PROPOSALS_KEY = "SA_PROPOSALS_KEY";
private static final String LOCAL_ID_KEY = "LOCAL_ID_KEY";
@@ -72,6 +75,13 @@
private static final String NATT_KEEPALIVE_DELAY_SEC_KEY = "NATT_KEEPALIVE_DELAY_SEC_KEY";
private static final String IKE_OPTIONS_KEY = "IKE_OPTIONS_KEY";
+ // TODO: b/243181760 Use the IKE API when they are exposed
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public static final int IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION = 6;
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public static final int IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES = 7;
+
private static final Set<Integer> IKE_OPTIONS = new ArraySet<>();
static {
@@ -80,6 +90,26 @@
IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_MOBIKE);
IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_FORCE_PORT_4500);
IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT);
+ IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_REKEY_MOBILITY);
+ IKE_OPTIONS.add(IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION);
+ IKE_OPTIONS.add(IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES);
+ }
+
+ /**
+ * Check if an IKE option is supported in the IPsec module installed on the device
+ *
+ * <p>This method ensures caller to safely access options that are added between dessert
+ * releases.
+ */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public static boolean isIkeOptionValid(int option) {
+ try {
+ new IkeSessionParams.Builder().addIkeOption(option);
+ return true;
+ } catch (IllegalArgumentException e) {
+ Log.d(TAG, "Option not supported; discarding: " + option);
+ return false;
+ }
}
/** Serializes an IkeSessionParams to a PersistableBundle. */
@@ -130,7 +160,7 @@
// IKE_OPTION is defined in IKE module and added in the IkeSessionParams
final List<Integer> enabledIkeOptions = new ArrayList<>();
for (int option : IKE_OPTIONS) {
- if (params.hasIkeOption(option)) {
+ if (isIkeOptionValid(option) && params.hasIkeOption(option)) {
enabledIkeOptions.add(option);
}
}
@@ -205,12 +235,16 @@
// Clear IKE Options that are by default enabled
for (int option : IKE_OPTIONS) {
- builder.removeIkeOption(option);
+ if (isIkeOptionValid(option)) {
+ builder.removeIkeOption(option);
+ }
}
final int[] optionArray = in.getIntArray(IKE_OPTIONS_KEY);
for (int option : optionArray) {
- builder.addIkeOption(option);
+ if (isIkeOptionValid(option)) {
+ builder.addIkeOption(option);
+ }
}
return builder.build();
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 0418a4b..b599028 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -438,8 +438,11 @@
map.ensureCapacity(count);
}
try {
+ // recycleParcel being false implies that we do not own the parcel. In this case, do
+ // not use lazy values to be safe, as the parcel could be recycled outside of our
+ // control.
recycleParcel &= parcelledData.readArrayMap(map, count, !parcelledByNative,
- /* lazy */ true, mClassLoader);
+ /* lazy */ recycleParcel, mClassLoader);
} catch (BadParcelableException e) {
if (sShouldDefuse) {
Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
@@ -1845,7 +1848,6 @@
// bundle immediately; neither of which is obvious.
synchronized (this) {
initializeFromParcelLocked(parcel, /*recycleParcel=*/ false, isNativeBundle);
- unparcel(/* itemwise */ true);
}
return;
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 801d34d..06c35b5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -956,7 +956,16 @@
public static final int NUM_WIFI_BATCHED_SCAN_BINS = 5;
- public static final int NUM_USER_ACTIVITY_TYPES = PowerManager.USER_ACTIVITY_EVENT_MAX + 1;
+ /**
+ * Note that these must match the constants in android.os.PowerManager.
+ * Also, if the user activity types change, the BatteryStatsImpl.VERSION must
+ * also be bumped.
+ */
+ static final String[] USER_ACTIVITY_TYPES = {
+ "other", "button", "touch", "accessibility", "attention"
+ };
+
+ public static final int NUM_USER_ACTIVITY_TYPES = USER_ACTIVITY_TYPES.length;
public abstract void noteUserActivityLocked(int type);
public abstract boolean hasUserActivity();
@@ -6168,7 +6177,7 @@
}
sb.append(val);
sb.append(" ");
- sb.append(PowerManager.userActivityEventToString(i));
+ sb.append(Uid.USER_ACTIVITY_TYPES[i]);
}
}
if (hasData) {
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index e5de3e1..e1d15de 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -74,6 +74,7 @@
String getUserAccount(int userId);
void setUserAccount(int userId, String accountName);
long getUserCreationTime(int userId);
+ boolean isUserSwitcherEnabled(int mUserId);
boolean isRestricted(int userId);
boolean canHaveRestrictedProfile(int userId);
int getUserSerialNumber(int userId);
diff --git a/core/java/android/os/IVibratorManagerService.aidl b/core/java/android/os/IVibratorManagerService.aidl
index a0d6ce1..fb9752f 100644
--- a/core/java/android/os/IVibratorManagerService.aidl
+++ b/core/java/android/os/IVibratorManagerService.aidl
@@ -30,7 +30,7 @@
boolean unregisterVibratorStateListener(int vibratorId, in IVibratorStateListener listener);
boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId,
in CombinedVibration vibration, in VibrationAttributes attributes);
- void vibrate(int uid, String opPkg, in CombinedVibration vibration,
+ void vibrate(int uid, int displayId, String opPkg, in CombinedVibration vibration,
in VibrationAttributes attributes, String reason, IBinder token);
void cancelVibrate(int usageFilter, IBinder token);
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 8a203e0..13ca2c3 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -345,44 +345,6 @@
public static final int USER_ACTIVITY_EVENT_DEVICE_STATE = 6;
/**
- * @hide
- */
- public static final int USER_ACTIVITY_EVENT_MAX = USER_ACTIVITY_EVENT_DEVICE_STATE;
-
- /**
- * @hide
- */
- @IntDef(prefix = { "USER_ACTIVITY_EVENT_" }, value = {
- USER_ACTIVITY_EVENT_OTHER,
- USER_ACTIVITY_EVENT_BUTTON,
- USER_ACTIVITY_EVENT_TOUCH,
- USER_ACTIVITY_EVENT_ACCESSIBILITY,
- USER_ACTIVITY_EVENT_ATTENTION,
- USER_ACTIVITY_EVENT_FACE_DOWN,
- USER_ACTIVITY_EVENT_DEVICE_STATE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface UserActivityEvent{}
-
- /**
- *
- * Convert the user activity event to a string for debugging purposes.
- * @hide
- */
- public static String userActivityEventToString(@UserActivityEvent int userActivityEvent) {
- switch (userActivityEvent) {
- case USER_ACTIVITY_EVENT_OTHER: return "other";
- case USER_ACTIVITY_EVENT_BUTTON: return "button";
- case USER_ACTIVITY_EVENT_TOUCH: return "touch";
- case USER_ACTIVITY_EVENT_ACCESSIBILITY: return "accessibility";
- case USER_ACTIVITY_EVENT_ATTENTION: return "attention";
- case USER_ACTIVITY_EVENT_FACE_DOWN: return "faceDown";
- case USER_ACTIVITY_EVENT_DEVICE_STATE: return "deviceState";
- default: return Integer.toString(userActivityEvent);
- }
- }
-
- /**
* User activity flag: If already dimmed, extend the dim timeout
* but do not brighten. This flag is useful for keeping the screen on
* a little longer without causing a visible change such as when
diff --git a/core/java/android/os/SystemVibratorManager.java b/core/java/android/os/SystemVibratorManager.java
index c690df2..eb2a712 100644
--- a/core/java/android/os/SystemVibratorManager.java
+++ b/core/java/android/os/SystemVibratorManager.java
@@ -137,7 +137,8 @@
return;
}
try {
- mService.vibrate(uid, opPkg, effect, attributes, reason, mToken);
+ mService.vibrate(uid, mContext.getAssociatedDisplayId(), opPkg, effect, attributes,
+ reason, mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index b2f7c60..5487a12 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -5132,23 +5132,13 @@
})
@UserHandleAware
public boolean isUserSwitcherEnabled(boolean showEvenIfNotActionable) {
- if (!supportsMultipleUsers()) {
- return false;
- }
- if (hasUserRestrictionForUser(DISALLOW_USER_SWITCH, mUserId)) {
- return false;
- }
- // If Demo Mode is on, don't show user switcher
- if (isDeviceInDemoMode(mContext)) {
- return false;
- }
- // Check the Settings.Global.USER_SWITCHER_ENABLED that the user can toggle on/off.
- final boolean userSwitcherSettingOn = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.USER_SWITCHER_ENABLED,
- Resources.getSystem().getBoolean(R.bool.config_showUserSwitcherByDefault) ? 1 : 0)
- != 0;
- if (!userSwitcherSettingOn) {
- return false;
+
+ try {
+ if (!mService.isUserSwitcherEnabled(mUserId)) {
+ return false;
+ }
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
// The feature is enabled. But is it worth showing?
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 592673e..1fcdd60 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9142,14 +9142,12 @@
public static final String SCREENSAVER_DEFAULT_COMPONENT = "screensaver_default_component";
/**
- * The complications that are enabled to be shown over the screensaver by the user. Holds
- * a comma separated list of
- * {@link com.android.settingslib.dream.DreamBackend.ComplicationType}.
+ * Whether complications are enabled to be shown over the screensaver by the user.
*
* @hide
*/
- public static final String SCREENSAVER_ENABLED_COMPLICATIONS =
- "screensaver_enabled_complications";
+ public static final String SCREENSAVER_COMPLICATIONS_ENABLED =
+ "screensaver_complications_enabled";
/**
diff --git a/core/java/android/service/dreams/DreamManagerInternal.java b/core/java/android/service/dreams/DreamManagerInternal.java
index 7bf5c38..6956cd4 100644
--- a/core/java/android/service/dreams/DreamManagerInternal.java
+++ b/core/java/android/service/dreams/DreamManagerInternal.java
@@ -46,6 +46,12 @@
public abstract boolean isDreaming();
/**
+ * Ask the power manager to nap. It will eventually call back into startDream() if/when it is
+ * appropriate to start dreaming.
+ */
+ public abstract void requestDream();
+
+ /**
* Called by the ActivityTaskManagerService to verify that the startDreamActivity
* request comes from the current active dream component.
*
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 2d461c6..7515538 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.TestApi;
import android.app.Activity;
import android.app.ActivityTaskManager;
import android.app.AlarmManager;
@@ -1124,7 +1125,8 @@
* @hide
*/
@Nullable
- public static DreamMetadata getDreamMetadata(Context context,
+ @TestApi
+ public static DreamMetadata getDreamMetadata(@NonNull Context context,
@Nullable ServiceInfo serviceInfo) {
if (serviceInfo == null) return null;
@@ -1183,7 +1185,8 @@
}
}
- private static ComponentName convertToComponentName(String flattenedString,
+ @Nullable
+ private static ComponentName convertToComponentName(@Nullable String flattenedString,
ServiceInfo serviceInfo) {
if (flattenedString == null) {
return null;
@@ -1193,7 +1196,17 @@
return new ComponentName(serviceInfo.packageName, flattenedString);
}
- return ComponentName.unflattenFromString(flattenedString);
+ // Ensure that the component is from the same package as the dream service. If not,
+ // treat the component as invalid and return null instead.
+ final ComponentName cn = ComponentName.unflattenFromString(flattenedString);
+ if (cn == null) return null;
+ if (!cn.getPackageName().equals(serviceInfo.packageName)) {
+ Log.w(TAG,
+ "Inconsistent package name in component: " + cn.getPackageName()
+ + ", should be: " + serviceInfo.packageName);
+ return null;
+ }
+ return cn;
}
/**
@@ -1489,6 +1502,7 @@
*
* @hide
*/
+ @TestApi
public static final class DreamMetadata {
@Nullable
public final ComponentName settingsActivity;
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
index 53ae657..609425c 100644
--- a/core/java/android/service/dreams/IDreamManager.aidl
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -43,5 +43,6 @@
void forceAmbientDisplayEnabled(boolean enabled);
ComponentName[] getDreamComponentsForUser(int userId);
void setDreamComponentsForUser(int userId, in ComponentName[] componentNames);
+ void setSystemDreamComponent(in ComponentName componentName);
void registerDreamOverlayService(in ComponentName componentName);
}
diff --git a/core/java/android/service/dreams/Sandman.java b/core/java/android/service/dreams/Sandman.java
index ced2a01..fae72a2 100644
--- a/core/java/android/service/dreams/Sandman.java
+++ b/core/java/android/service/dreams/Sandman.java
@@ -20,13 +20,13 @@
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
+import com.android.server.LocalServices;
+
/**
* Internal helper for launching dreams to ensure consistency between the
* <code>UiModeManagerService</code> system service and the <code>Somnambulator</code> activity.
@@ -75,32 +75,28 @@
}
private static void startDream(Context context, boolean docked) {
- try {
- IDreamManager dreamManagerService = IDreamManager.Stub.asInterface(
- ServiceManager.getService(DreamService.DREAM_SERVICE));
- if (dreamManagerService != null && !dreamManagerService.isDreaming()) {
- if (docked) {
- Slog.i(TAG, "Activating dream while docked.");
+ DreamManagerInternal dreamManagerService =
+ LocalServices.getService(DreamManagerInternal.class);
+ if (dreamManagerService != null && !dreamManagerService.isDreaming()) {
+ if (docked) {
+ Slog.i(TAG, "Activating dream while docked.");
- // Wake up.
- // The power manager will wake up the system automatically when it starts
- // receiving power from a dock but there is a race between that happening
- // and the UI mode manager starting a dream. We want the system to already
- // be awake by the time this happens. Otherwise the dream may not start.
- PowerManager powerManager =
- context.getSystemService(PowerManager.class);
- powerManager.wakeUp(SystemClock.uptimeMillis(),
- PowerManager.WAKE_REASON_PLUGGED_IN,
- "android.service.dreams:DREAM");
- } else {
- Slog.i(TAG, "Activating dream by user request.");
- }
-
- // Dream.
- dreamManagerService.dream();
+ // Wake up.
+ // The power manager will wake up the system automatically when it starts
+ // receiving power from a dock but there is a race between that happening
+ // and the UI mode manager starting a dream. We want the system to already
+ // be awake by the time this happens. Otherwise the dream may not start.
+ PowerManager powerManager =
+ context.getSystemService(PowerManager.class);
+ powerManager.wakeUp(SystemClock.uptimeMillis(),
+ PowerManager.WAKE_REASON_PLUGGED_IN,
+ "android.service.dreams:DREAM");
+ } else {
+ Slog.i(TAG, "Activating dream by user request.");
}
- } catch (RemoteException ex) {
- Slog.e(TAG, "Could not start dream when docked.", ex);
+
+ // Dream.
+ dreamManagerService.requestDream();
}
}
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 91042bfa..a9c2ad1 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -91,6 +91,22 @@
= "android.service.notification.NotificationAssistantService";
/**
+ * Activity Action: Show notification assistant detail setting page in NAS app.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ * @hide
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_NOTIFICATION_ASSISTANT_DETAIL_SETTINGS =
+ "android.service.notification.action.NOTIFICATION_ASSISTANT_DETAIL_SETTINGS";
+
+
+ /**
* Data type: int, the feedback rating score provided by user. The score can be any integer
* value depends on the experimental and feedback UX design.
*/
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 195cf82..976a3e4 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -52,18 +52,18 @@
public static final String SETTINGS_SUPPORT_LARGE_SCREEN = "settings_support_large_screen";
/**
- * Support per app's language selection
- * @hide
- */
- public static final String SETTINGS_APP_LANGUAGE_SELECTION = "settings_app_language_selection";
-
- /**
* Support locale opt-out and opt-in switch for per app's language.
* @hide
*/
public static final String SETTINGS_APP_LOCALE_OPT_IN_ENABLED =
"settings_app_locale_opt_in_enabled";
+ /**
+ * Launch the Volume panel in SystemUI.
+ * @hide
+ */
+ public static final String SETTINGS_VOLUME_PANEL_IN_SYSTEMUI =
+ "settings_volume_panel_in_systemui";
/** @hide */
public static final String SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS =
@@ -83,11 +83,6 @@
public static final String SETTINGS_HIDE_SECOND_LAYER_PAGE_NAVIGATE_UP_BUTTON_IN_TWO_PANE =
"settings_hide_second_layer_page_navigate_up_button_in_two_pane";
- /** Flag to enable/disable guest mode UX changes as mentioned in b/214031645
- * @hide
- */
- public static final String SETTINGS_GUEST_MODE_UX_CHANGES = "settings_guest_mode_ux_changes";
-
/** Support Clear Calling feature.
* @hide
*/
@@ -115,19 +110,17 @@
DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "true");
DEFAULT_FLAGS.put(SETTINGS_SUPPORT_LARGE_SCREEN, "true");
DEFAULT_FLAGS.put("settings_search_always_expand", "true");
- DEFAULT_FLAGS.put(SETTINGS_APP_LANGUAGE_SELECTION, "true");
DEFAULT_FLAGS.put(SETTINGS_APP_LOCALE_OPT_IN_ENABLED, "true");
+ DEFAULT_FLAGS.put(SETTINGS_VOLUME_PANEL_IN_SYSTEMUI, "false");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS, "true");
DEFAULT_FLAGS.put(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME, "true");
DEFAULT_FLAGS.put(SETTINGS_HIDE_SECOND_LAYER_PAGE_NAVIGATE_UP_BUTTON_IN_TWO_PANE, "true");
- DEFAULT_FLAGS.put(SETTINGS_GUEST_MODE_UX_CHANGES, "true");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_CLEAR_CALLING, "false");
}
private static final Set<String> PERSISTENT_FLAGS;
static {
PERSISTENT_FLAGS = new HashSet<>();
- PERSISTENT_FLAGS.add(SETTINGS_APP_LANGUAGE_SELECTION);
PERSISTENT_FLAGS.add(SETTINGS_APP_LOCALE_OPT_IN_ENABLED);
PERSISTENT_FLAGS.add(SETTINGS_SUPPORT_LARGE_SCREEN);
PERSISTENT_FLAGS.add(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 0ef23bb..bb26c46 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -413,11 +413,6 @@
boolean hasNavigationBar(int displayId);
/**
- * Get the position of the nav bar
- */
- int getNavBarPosition(int displayId);
-
- /**
* Lock the device immediately with the specified options (can be null).
*/
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index d63c25a..5236fe7 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -176,7 +176,9 @@
// If we have a new leash, make sure visibility is up-to-date, even though we
// didn't want to run an animation above.
- applyRequestedVisibilityToControl();
+ if (mController.getAnimationType(control.getType()) == ANIMATION_TYPE_NONE) {
+ applyRequestedVisibilityToControl();
+ }
// Remove the surface that owned by last control when it lost.
if (!requestedVisible && lastControl == null) {
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index c198098..c102ad3 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -349,6 +349,20 @@
return insets;
}
+ // TODO: Remove this once the task bar is treated as navigation bar.
+ public Insets calculateInsetsWithInternalTypes(Rect frame, @InternalInsetsType int[] types,
+ boolean ignoreVisibility) {
+ Insets insets = Insets.NONE;
+ for (int i = types.length - 1; i >= 0; i--) {
+ InsetsSource source = mSources[types[i]];
+ if (source == null) {
+ continue;
+ }
+ insets = Insets.max(source.calculateInsets(frame, ignoreVisibility), insets);
+ }
+ return insets;
+ }
+
public Insets calculateInsets(Rect frame, @InsetsType int types,
InsetsVisibilities overrideVisibilities) {
Insets insets = Insets.NONE;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ec6b4ac..e673041 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -284,7 +284,7 @@
* @hide
*/
public static final boolean LOCAL_LAYOUT =
- SystemProperties.getBoolean("persist.debug.local_layout", false);
+ SystemProperties.getBoolean("persist.debug.local_layout", true);
/**
* Set this system property to true to force the view hierarchy to render
diff --git a/core/java/android/view/WindowLayout.java b/core/java/android/view/WindowLayout.java
index 57a0330..5ed9d2f 100644
--- a/core/java/android/view/WindowLayout.java
+++ b/core/java/android/view/WindowLayout.java
@@ -118,11 +118,11 @@
}
if (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) {
if (displayFrame.width() < displayFrame.height()) {
- displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
- displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
+ displayCutoutSafeExceptMaybeBars.top = MIN_Y;
+ displayCutoutSafeExceptMaybeBars.bottom = MAX_Y;
} else {
- displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
- displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
+ displayCutoutSafeExceptMaybeBars.left = MIN_X;
+ displayCutoutSafeExceptMaybeBars.right = MAX_X;
}
}
final boolean layoutInsetDecor = (attrs.flags & FLAG_LAYOUT_INSET_DECOR) != 0;
@@ -132,23 +132,23 @@
final Insets systemBarsInsets = state.calculateInsets(
displayFrame, WindowInsets.Type.systemBars(), requestedVisibilities);
if (systemBarsInsets.left > 0) {
- displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
+ displayCutoutSafeExceptMaybeBars.left = MIN_X;
}
if (systemBarsInsets.top > 0) {
- displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
+ displayCutoutSafeExceptMaybeBars.top = MIN_Y;
}
if (systemBarsInsets.right > 0) {
- displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
+ displayCutoutSafeExceptMaybeBars.right = MAX_X;
}
if (systemBarsInsets.bottom > 0) {
- displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
+ displayCutoutSafeExceptMaybeBars.bottom = MAX_Y;
}
}
if (type == TYPE_INPUT_METHOD) {
final InsetsSource navSource = state.peekSource(ITYPE_NAVIGATION_BAR);
if (navSource != null && navSource.calculateInsets(displayFrame, true).bottom > 0) {
// The IME can always extend under the bottom cutout if the navbar is there.
- displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
+ displayCutoutSafeExceptMaybeBars.bottom = MAX_Y;
}
}
final boolean attachedInParent = attachedWindowFrame != null && !layoutInScreen;
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index fa84407..7314ad8 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -732,6 +732,10 @@
* @hide Pending API consideration. Currently only used internally by the system.
*/
protected boolean hasDividerBeforeChildAt(int childIndex) {
+ if (mShowDividers == SHOW_DIVIDER_NONE) {
+ // Short-circuit to save iteration over child views.
+ return false;
+ }
if (childIndex == getVirtualChildCount()) {
// Check whether the end divider should draw.
return (mShowDividers & SHOW_DIVIDER_END) != 0;
@@ -746,6 +750,24 @@
}
/**
+ * Determines whether or not there's a divider after a specified child index.
+ *
+ * @param childIndex Index of child to check for following divider
+ * @return true if there should be a divider after the child at childIndex
+ */
+ private boolean hasDividerAfterChildAt(int childIndex) {
+ if (mShowDividers == SHOW_DIVIDER_NONE) {
+ // Short-circuit to save iteration over child views.
+ return false;
+ }
+ if (allViewsAreGoneAfter(childIndex)) {
+ // This is the last view that's not gone, check if end divider is enabled.
+ return (mShowDividers & SHOW_DIVIDER_END) != 0;
+ }
+ return (mShowDividers & SHOW_DIVIDER_MIDDLE) != 0;
+ }
+
+ /**
* Checks whether all (virtual) child views before the given index are gone.
*/
private boolean allViewsAreGoneBefore(int childIndex) {
@@ -759,6 +781,20 @@
}
/**
+ * Checks whether all (virtual) child views after the given index are gone.
+ */
+ private boolean allViewsAreGoneAfter(int childIndex) {
+ final int count = getVirtualChildCount();
+ for (int i = childIndex + 1; i < count; i++) {
+ final View child = getVirtualChildAt(i);
+ if (child != null && child.getVisibility() != GONE) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
* Measures the children when the orientation of this LinearLayout is set
* to {@link #VERTICAL}.
*
@@ -1295,6 +1331,7 @@
if (useLargestChild &&
(widthMode == MeasureSpec.AT_MOST || widthMode == MeasureSpec.UNSPECIFIED)) {
mTotalLength = 0;
+ nonSkippedChildCount = 0;
for (int i = 0; i < count; ++i) {
final View child = getVirtualChildAt(i);
@@ -1308,6 +1345,11 @@
continue;
}
+ nonSkippedChildCount++;
+ if (hasDividerBeforeChildAt(i)) {
+ mTotalLength += mDividerWidth;
+ }
+
final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
child.getLayoutParams();
if (isExactly) {
@@ -1319,6 +1361,10 @@
lp.leftMargin + lp.rightMargin + getNextLocationOffset(child));
}
}
+
+ if (nonSkippedChildCount > 0 && hasDividerBeforeChildAt(count)) {
+ mTotalLength += mDividerWidth;
+ }
}
// Add in our padding
@@ -1347,6 +1393,7 @@
maxHeight = -1;
mTotalLength = 0;
+ nonSkippedChildCount = 0;
for (int i = 0; i < count; ++i) {
final View child = getVirtualChildAt(i);
@@ -1354,6 +1401,11 @@
continue;
}
+ nonSkippedChildCount++;
+ if (hasDividerBeforeChildAt(i)) {
+ mTotalLength += mDividerWidth;
+ }
+
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
final float childWeight = lp.weight;
if (childWeight > 0) {
@@ -1423,6 +1475,10 @@
}
}
+ if (nonSkippedChildCount > 0 && hasDividerBeforeChildAt(count)) {
+ mTotalLength += mDividerWidth;
+ }
+
// Add in our padding
mTotalLength += mPaddingLeft + mPaddingRight;
// TODO: Should we update widthSize with the new total length?
@@ -1810,7 +1866,13 @@
break;
}
- if (hasDividerBeforeChildAt(childIndex)) {
+ if (isLayoutRtl) {
+ // Because rtl rendering occurs in the reverse direction, we need to check
+ // after the child rather than before (since after=left in this context)
+ if (hasDividerAfterChildAt(childIndex)) {
+ childLeft += mDividerWidth;
+ }
+ } else if (hasDividerBeforeChildAt(childIndex)) {
childLeft += mDividerWidth;
}
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 872e65a..07dfce7 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -61,22 +61,32 @@
import com.android.internal.R;
/**
- * A Switch is a two-state toggle switch widget that can select between two
- * options. The user may drag the "thumb" back and forth to choose the selected option,
- * or simply tap to toggle as if it were a checkbox. The {@link #setText(CharSequence) text}
- * property controls the text displayed in the label for the switch, whereas the
- * {@link #setTextOff(CharSequence) off} and {@link #setTextOn(CharSequence) on} text
- * controls the text on the thumb. Similarly, the
- * {@link #setTextAppearance(android.content.Context, int) textAppearance} and the related
- * setTypeface() methods control the typeface and style of label text, whereas the
- * {@link #setSwitchTextAppearance(android.content.Context, int) switchTextAppearance} and
- * the related setSwitchTypeface() methods control that of the thumb.
+ * A Switch is a two-state toggle widget. Users can drag the switch "thumb" back
+ * and forth to select either of two options or simply tap the switch to toggle
+ * between options.
*
- * <p>{@link androidx.recyclerview.widget.RecyclerView} is a version of
- * the Switch widget which runs on devices back to API 7.</p>
+ * <p>The {@link #setText(CharSequence) text} property controls
+ * the text of the switch label. The {@link #setTextOn(CharSequence) textOn} and
+ * {@link #setTextOff(CharSequence) textOff} properties control the text of the
+ * thumb. The {@link #setTextAppearance(int) textAppearance} property and the
+ * related {@link #setTypeface(android.graphics.Typeface) setTypeface()} methods
+ * control the typeface and style of the switch label. The
+ * {@link #setSwitchTextAppearance(android.content.Context, int)
+ * switchTextAppearance} property and the related
+ * {@link #setSwitchTypeface(android.graphics.Typeface) setSwitchTypeface()}
+ * methods control the typeface and style of the thumb text.</p>
*
- * <p>See the <a href="{@docRoot}guide/topics/ui/controls/togglebutton.html">Toggle Buttons</a>
- * guide.</p>
+ * <p class="note"><b>Note:</b> The thumb text is displayed only if the
+ * <a href="{@docRoot}reference/android/widget/Switch#attr_android:showText">
+ * <code>showText</code></a> attribute is set to {@code true}. See also
+ * {@link #setShowText(boolean)} and {@link #getShowText()}.</p>
+ *
+ * <p>{@link androidx.appcompat.widget.SwitchCompat} provides backward
+ * compatibility down to Android 4.0 (API level 14).</p>
+ *
+ * <p>For more information, see the
+ * <a href="{@docRoot}guide/topics/ui/controls/togglebutton.html">
+ * Toggle Buttons</a> guide.</p>
*
* @attr ref android.R.styleable#Switch_textOn
* @attr ref android.R.styleable#Switch_textOff
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 2268bef..450bb1e 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4877,20 +4877,28 @@
}
/**
- * Set the line break style for text wrapping.
+ * Sets the line-break style for text wrapping.
*
- * The line break style to indicates the line break strategies can be used when
- * calculating the text wrapping. The line break style affects rule-based breaking. It
- * specifies the strictness of line-breaking rules.
- * There are several types for the line break style:
- * {@link LineBreakConfig#LINE_BREAK_STYLE_LOOSE},
- * {@link LineBreakConfig#LINE_BREAK_STYLE_NORMAL} and
- * {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}. The default values of the line break style
- * is {@link LineBreakConfig#LINE_BREAK_STYLE_NONE}, indicating no breaking rule is specified.
- * See <a href="https://www.w3.org/TR/css-text-3/#line-break-property">
- * the line-break property</a>
+ * <p>Line-break style specifies the line-break strategies that can be used
+ * for text wrapping. The line-break style affects rule-based line breaking
+ * by specifying the strictness of line-breaking rules.
*
- * @param lineBreakStyle the line break style for the text.
+ * <p>The following are types of line-break styles:
+ * <ul>
+ * <li>{@link LineBreakConfig#LINE_BREAK_STYLE_LOOSE}
+ * <li>{@link LineBreakConfig#LINE_BREAK_STYLE_NORMAL}
+ * <li>{@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}
+ * </ul>
+ *
+ * <p>The default line-break style is
+ * {@link LineBreakConfig#LINE_BREAK_STYLE_NONE}, which specifies that no
+ * line-breaking rules are used.
+ *
+ * <p>See the
+ * <a href="https://www.w3.org/TR/css-text-3/#line-break-property" class="external">
+ * line-break property</a> for more information.
+ *
+ * @param lineBreakStyle The line-break style for the text.
*/
public void setLineBreakStyle(@LineBreakConfig.LineBreakStyle int lineBreakStyle) {
if (mLineBreakStyle != lineBreakStyle) {
@@ -4904,17 +4912,22 @@
}
/**
- * Set the line break word style for text wrapping.
+ * Sets the line-break word style for text wrapping.
*
- * The line break word style affects dictionary-based breaking and provide phrase-based
- * breaking opportunities. The type for the line break word style is
- * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}. The default values of the line break
- * word style is {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE}, indicating no breaking rule
- * is specified.
- * See <a href="https://www.w3.org/TR/css-text-3/#word-break-property">
- * the word-break property</a>
+ * <p>The line-break word style affects dictionary-based line breaking by
+ * providing phrase-based line-breaking opportunities. Use
+ * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE} to specify
+ * phrase-based line breaking.
*
- * @param lineBreakWordStyle the line break word style for the tet
+ * <p>The default line-break word style is
+ * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE}, which specifies that
+ * no line-breaking word style is used.
+ *
+ * <p>See the
+ * <a href="https://www.w3.org/TR/css-text-3/#word-break-property" class="external">
+ * word-break property</a> for more information.
+ *
+ * @param lineBreakWordStyle The line-break word style for the text.
*/
public void setLineBreakWordStyle(@LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) {
if (mLineBreakWordStyle != lineBreakWordStyle) {
@@ -4928,18 +4941,18 @@
}
/**
- * Get the current line break style for text wrapping.
+ * Gets the current line-break style for text wrapping.
*
- * @return the current line break style to be used for text wrapping.
+ * @return The line-break style to be used for text wrapping.
*/
public @LineBreakConfig.LineBreakStyle int getLineBreakStyle() {
return mLineBreakStyle;
}
/**
- * Get the current line word break style for text wrapping.
+ * Gets the current line-break word style for text wrapping.
*
- * @return the current line break word style to be used for text wrapping.
+ * @return The line-break word style to be used for text wrapping.
*/
public @LineBreakConfig.LineBreakWordStyle int getLineBreakWordStyle() {
return mLineBreakWordStyle;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java b/core/java/android/window/BackAnimationAdaptor.aidl
similarity index 61%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
copy to core/java/android/window/BackAnimationAdaptor.aidl
index e62a63a..1082d0a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
+++ b/core/java/android/window/BackAnimationAdaptor.aidl
@@ -14,18 +14,9 @@
* limitations under the License.
*/
-package com.android.wm.shell.desktopmode;
-
-import android.os.SystemProperties;
+package android.window;
/**
- * Constants for desktop mode feature
+ * @hide
*/
-public class DesktopModeConstants {
-
- /**
- * Flag to indicate whether desktop mode is available on the device
- */
- public static final boolean IS_FEATURE_ENABLED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode", false);
-}
+parcelable BackAnimationAdaptor;
\ No newline at end of file
diff --git a/core/java/android/window/BackAnimationAdaptor.java b/core/java/android/window/BackAnimationAdaptor.java
new file mode 100644
index 0000000..cf82046
--- /dev/null
+++ b/core/java/android/window/BackAnimationAdaptor.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Object that describes how to run a remote back animation.
+ *
+ * @hide
+ */
+public class BackAnimationAdaptor implements Parcelable {
+
+ private final IBackAnimationRunner mRunner;
+ @BackNavigationInfo.BackTargetType
+ private final int mSupportType;
+
+ public BackAnimationAdaptor(IBackAnimationRunner runner, int supportType) {
+ mRunner = runner;
+ mSupportType = supportType;
+ }
+
+ public BackAnimationAdaptor(Parcel in) {
+ mRunner = IBackAnimationRunner.Stub.asInterface(in.readStrongBinder());
+ mSupportType = in.readInt();
+ }
+
+ public IBackAnimationRunner getRunner() {
+ return mRunner;
+ }
+
+ @BackNavigationInfo.BackTargetType public int getSupportType() {
+ return mSupportType;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeStrongInterface(mRunner);
+ dest.writeInt(mSupportType);
+ }
+
+ public static final @android.annotation.NonNull Creator<BackAnimationAdaptor> CREATOR =
+ new Creator<BackAnimationAdaptor>() {
+ public BackAnimationAdaptor createFromParcel(Parcel in) {
+ return new BackAnimationAdaptor(in);
+ }
+
+ public BackAnimationAdaptor[] newArray(int size) {
+ return new BackAnimationAdaptor[size];
+ }
+ };
+}
diff --git a/core/java/android/window/BackNavigationInfo.java b/core/java/android/window/BackNavigationInfo.java
index dd49014..941511e 100644
--- a/core/java/android/window/BackNavigationInfo.java
+++ b/core/java/android/window/BackNavigationInfo.java
@@ -101,6 +101,8 @@
@Nullable
private final IOnBackInvokedCallback mOnBackInvokedCallback;
+ private final boolean mIsPrepareRemoteAnimation;
+
/**
* Create a new {@link BackNavigationInfo} instance.
*
@@ -117,6 +119,9 @@
* @param onBackNavigationDone The callback to be called once the client is done with the
* back preview.
* @param onBackInvokedCallback The back callback registered by the current top level window.
+ * @param isPrepareRemoteAnimation Return whether the core is preparing a back gesture
+ * animation, if true, the caller of startBackNavigation should
+ * be expected to receive an animation start callback.
*/
private BackNavigationInfo(@BackTargetType int type,
@Nullable RemoteAnimationTarget departingAnimationTarget,
@@ -124,7 +129,8 @@
@Nullable HardwareBuffer screenshotBuffer,
@Nullable WindowConfiguration taskWindowConfiguration,
@Nullable RemoteCallback onBackNavigationDone,
- @Nullable IOnBackInvokedCallback onBackInvokedCallback) {
+ @Nullable IOnBackInvokedCallback onBackInvokedCallback,
+ boolean isPrepareRemoteAnimation) {
mType = type;
mDepartingAnimationTarget = departingAnimationTarget;
mScreenshotSurface = screenshotSurface;
@@ -132,6 +138,7 @@
mTaskWindowConfiguration = taskWindowConfiguration;
mOnBackNavigationDone = onBackNavigationDone;
mOnBackInvokedCallback = onBackInvokedCallback;
+ mIsPrepareRemoteAnimation = isPrepareRemoteAnimation;
}
private BackNavigationInfo(@NonNull Parcel in) {
@@ -142,6 +149,7 @@
mTaskWindowConfiguration = in.readTypedObject(WindowConfiguration.CREATOR);
mOnBackNavigationDone = in.readTypedObject(RemoteCallback.CREATOR);
mOnBackInvokedCallback = IOnBackInvokedCallback.Stub.asInterface(in.readStrongBinder());
+ mIsPrepareRemoteAnimation = in.readBoolean();
}
@Override
@@ -153,6 +161,7 @@
dest.writeTypedObject(mTaskWindowConfiguration, flags);
dest.writeTypedObject(mOnBackNavigationDone, flags);
dest.writeStrongInterface(mOnBackInvokedCallback);
+ dest.writeBoolean(mIsPrepareRemoteAnimation);
}
/**
@@ -221,6 +230,10 @@
return mOnBackInvokedCallback;
}
+ public boolean isPrepareRemoteAnimation() {
+ return mIsPrepareRemoteAnimation;
+ }
+
/**
* Callback to be called when the back preview is finished in order to notify the server that
* it can clean up the resources created for the animation.
@@ -306,6 +319,8 @@
@Nullable
private IOnBackInvokedCallback mOnBackInvokedCallback = null;
+ private boolean mPrepareAnimation;
+
/**
* @see BackNavigationInfo#getType()
*/
@@ -366,12 +381,20 @@
}
/**
+ * @param prepareAnimation Whether core prepare animation for shell.
+ */
+ public Builder setPrepareAnimation(boolean prepareAnimation) {
+ mPrepareAnimation = prepareAnimation;
+ return this;
+ }
+
+ /**
* Builds and returns an instance of {@link BackNavigationInfo}
*/
public BackNavigationInfo build() {
return new BackNavigationInfo(mType, mDepartingAnimationTarget, mScreenshotSurface,
mScreenshotBuffer, mTaskWindowConfiguration, mOnBackNavigationDone,
- mOnBackInvokedCallback);
+ mOnBackInvokedCallback, mPrepareAnimation);
}
}
}
diff --git a/core/java/android/window/IBackAnimationRunner.aidl b/core/java/android/window/IBackAnimationRunner.aidl
new file mode 100644
index 0000000..ca04b9d
--- /dev/null
+++ b/core/java/android/window/IBackAnimationRunner.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.view.RemoteAnimationTarget;
+import android.window.IBackNaviAnimationController;
+
+/**
+ * Interface that is used to callback from window manager to the process that runs a back gesture
+ * animation to start or cancel it.
+ *
+ * {@hide}
+ */
+oneway interface IBackAnimationRunner {
+
+ /**
+ * Called when the system needs to cancel the current animation. This can be due to the
+ * wallpaper not drawing in time, or the handler not finishing the animation within a predefined
+ * amount of time.
+ *
+ */
+ void onAnimationCancelled() = 1;
+
+ /**
+ * Called when the system is ready for the handler to start animating all the visible tasks.
+ *
+ */
+ void onAnimationStart(in IBackNaviAnimationController controller, in int type,
+ in RemoteAnimationTarget[] apps, in RemoteAnimationTarget[] wallpapers,
+ in RemoteAnimationTarget[] nonApps) = 2;
+}
diff --git a/core/java/android/window/IBackNaviAnimationController.aidl b/core/java/android/window/IBackNaviAnimationController.aidl
new file mode 100644
index 0000000..bba223e
--- /dev/null
+++ b/core/java/android/window/IBackNaviAnimationController.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.window;
+
+/**
+ * Interface to be invoked by the controlling process when a back animation has finished.
+ *
+ * @param trigger Whether the back gesture has passed the triggering threshold.
+ * {@hide}
+ */
+interface IBackNaviAnimationController {
+ void finish(in boolean triggerBack);
+}
diff --git a/core/java/android/window/ITaskFragmentOrganizerController.aidl b/core/java/android/window/ITaskFragmentOrganizerController.aidl
index 884ca77..3250dd8 100644
--- a/core/java/android/window/ITaskFragmentOrganizerController.aidl
+++ b/core/java/android/window/ITaskFragmentOrganizerController.aidl
@@ -57,6 +57,12 @@
* Notifies the server that the organizer has finished handling the given transaction. The
* server should apply the given {@link WindowContainerTransaction} for the necessary changes.
*/
- void onTransactionHandled(in ITaskFragmentOrganizer organizer, in IBinder transactionToken,
- in WindowContainerTransaction wct);
+ void onTransactionHandled(in IBinder transactionToken, in WindowContainerTransaction wct,
+ int transitionType, boolean shouldApplyIndependently);
+
+ /**
+ * Requests the server to apply the given {@link WindowContainerTransaction}.
+ */
+ void applyTransaction(in WindowContainerTransaction wct, int transitionType,
+ boolean shouldApplyIndependently);
}
diff --git a/core/java/android/window/TaskFragmentOrganizer.java b/core/java/android/window/TaskFragmentOrganizer.java
index 7b6139f..649785a 100644
--- a/core/java/android/window/TaskFragmentOrganizer.java
+++ b/core/java/android/window/TaskFragmentOrganizer.java
@@ -16,17 +16,25 @@
package android.window;
+import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_OPEN;
import static android.window.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENTED_TO_TASK;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_ERROR;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_INFO_CHANGED;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_VANISHED;
+import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT;
+import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT;
+import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
+import android.app.WindowConfiguration;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
@@ -34,6 +42,7 @@
import android.os.RemoteException;
import android.util.SparseArray;
import android.view.RemoteAnimationDefinition;
+import android.view.WindowManager;
import java.util.ArrayList;
import java.util.List;
@@ -47,11 +56,24 @@
public class TaskFragmentOrganizer extends WindowOrganizer {
/**
- * Key to the exception in {@link Bundle} in {@link ITaskFragmentOrganizer#onTaskFragmentError}.
+ * Key to the {@link Throwable} in {@link TaskFragmentTransaction.Change#getErrorBundle()}.
+ * @hide
*/
- private static final String KEY_ERROR_CALLBACK_EXCEPTION = "fragment_exception";
- private static final String KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO = "task_fragment_info";
- private static final String KEY_ERROR_CALLBACK_OP_TYPE = "operation_type";
+ public static final String KEY_ERROR_CALLBACK_THROWABLE = "fragment_throwable";
+
+ /**
+ * Key to the {@link TaskFragmentInfo} in
+ * {@link TaskFragmentTransaction.Change#getErrorBundle()}.
+ * @hide
+ */
+ public static final String KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO = "task_fragment_info";
+
+ /**
+ * Key to the {@link WindowContainerTransaction.HierarchyOp} in
+ * {@link TaskFragmentTransaction.Change#getErrorBundle()}.
+ * @hide
+ */
+ public static final String KEY_ERROR_CALLBACK_OP_TYPE = "operation_type";
/**
* Creates a {@link Bundle} with an exception, operation type and TaskFragmentInfo (if any)
@@ -61,7 +83,7 @@
public static @NonNull Bundle putErrorInfoInBundle(@NonNull Throwable exception,
@Nullable TaskFragmentInfo info, int opType) {
final Bundle errorBundle = new Bundle();
- errorBundle.putSerializable(KEY_ERROR_CALLBACK_EXCEPTION, exception);
+ errorBundle.putSerializable(KEY_ERROR_CALLBACK_THROWABLE, exception);
if (info != null) {
errorBundle.putParcelable(KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO, info);
}
@@ -155,21 +177,111 @@
* {@link #onTransactionReady(TaskFragmentTransaction)}
* @param wct {@link WindowContainerTransaction} that the server should apply for
* update of the transaction.
- * @see com.android.server.wm.WindowOrganizerController#enforceTaskPermission for permission
- * requirement.
+ * @param transitionType {@link WindowManager.TransitionType} if it needs to start a
+ * transition.
+ * @param shouldApplyIndependently If {@code true}, the {@code wct} will request a new
+ * transition, which will be queued until the sync engine is
+ * free if there is any other active sync. If {@code false},
+ * the {@code wct} will be directly applied to the active sync.
+ * @see com.android.server.wm.WindowOrganizerController#enforceTaskFragmentOrganizerPermission
+ * for permission enforcement.
* @hide
*/
public void onTransactionHandled(@NonNull IBinder transactionToken,
- @NonNull WindowContainerTransaction wct) {
+ @NonNull WindowContainerTransaction wct,
+ @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) {
wct.setTaskFragmentOrganizer(mInterface);
try {
- getController().onTransactionHandled(mInterface, transactionToken, wct);
+ getController().onTransactionHandled(transactionToken, wct, transitionType,
+ shouldApplyIndependently);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
+ * Routes to {@link ITaskFragmentOrganizerController#applyTransaction} instead of
+ * {@link IWindowOrganizerController#applyTransaction} for the different transition options.
+ *
+ * @see #applyTransaction(WindowContainerTransaction, int, boolean, boolean)
+ */
+ @Override
+ public void applyTransaction(@NonNull WindowContainerTransaction wct) {
+ // TODO(b/207070762) doing so to keep CTS compatibility. Remove in the next release.
+ applyTransaction(wct, getTransitionType(wct), false /* shouldApplyIndependently */);
+ }
+
+ /**
+ * Requests the server to apply the given {@link WindowContainerTransaction}.
+ *
+ * @param wct {@link WindowContainerTransaction} to apply.
+ * @param transitionType {@link WindowManager.TransitionType} if it needs to start a
+ * transition.
+ * @param shouldApplyIndependently If {@code true}, the {@code wct} will request a new
+ * transition, which will be queued until the sync engine is
+ * free if there is any other active sync. If {@code false},
+ * the {@code wct} will be directly applied to the active sync.
+ * @see com.android.server.wm.WindowOrganizerController#enforceTaskFragmentOrganizerPermission
+ * for permission enforcement.
+ * @hide
+ */
+ public void applyTransaction(@NonNull WindowContainerTransaction wct,
+ @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) {
+ if (wct.isEmpty()) {
+ return;
+ }
+ wct.setTaskFragmentOrganizer(mInterface);
+ try {
+ getController().applyTransaction(wct, transitionType, shouldApplyIndependently);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Gets the default {@link WindowManager.TransitionType} based on the requested
+ * {@link WindowContainerTransaction}.
+ * @hide
+ */
+ // TODO(b/207070762): let Extensions to set the transition type instead.
+ @WindowManager.TransitionType
+ public static int getTransitionType(@NonNull WindowContainerTransaction wct) {
+ if (wct.isEmpty()) {
+ return TRANSIT_NONE;
+ }
+ for (WindowContainerTransaction.Change change : wct.getChanges().values()) {
+ if ((change.getWindowSetMask() & WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0) {
+ // Treat as TRANSIT_CHANGE when there is TaskFragment resizing.
+ return TRANSIT_CHANGE;
+ }
+ }
+ boolean containsCreatingTaskFragment = false;
+ boolean containsDeleteTaskFragment = false;
+ final List<WindowContainerTransaction.HierarchyOp> ops = wct.getHierarchyOps();
+ for (int i = ops.size() - 1; i >= 0; i--) {
+ final int type = ops.get(i).getType();
+ if (type == HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT) {
+ // Treat as TRANSIT_CHANGE when there is activity reparent.
+ return TRANSIT_CHANGE;
+ }
+ if (type == HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT) {
+ containsCreatingTaskFragment = true;
+ } else if (type == HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT) {
+ containsDeleteTaskFragment = true;
+ }
+ }
+ if (containsCreatingTaskFragment) {
+ return TRANSIT_OPEN;
+ }
+ if (containsDeleteTaskFragment) {
+ return TRANSIT_CLOSE;
+ }
+
+ // Use TRANSIT_CHANGE as default.
+ return TRANSIT_CHANGE;
+ }
+
+ /**
* Called when a TaskFragment is created and organized by this organizer.
*
* @param taskFragmentInfo Info of the TaskFragment that is created.
@@ -342,6 +454,9 @@
* @hide
*/
public void onTransactionReady(@NonNull TaskFragmentTransaction transaction) {
+ // TODO(b/240519866): move to SplitController#onTransactionReady to make sure the whole
+ // transaction is handled in one sync block. Keep the implementation below to keep CTS
+ // compatibility. Remove in the next release.
final WindowContainerTransaction wct = new WindowContainerTransaction();
final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
for (TaskFragmentTransaction.Change change : changes) {
@@ -391,7 +506,7 @@
errorBundle.getParcelable(
KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO, TaskFragmentInfo.class),
errorBundle.getInt(KEY_ERROR_CALLBACK_OP_TYPE),
- errorBundle.getSerializable(KEY_ERROR_CALLBACK_EXCEPTION,
+ errorBundle.getSerializable(KEY_ERROR_CALLBACK_THROWABLE,
java.lang.Throwable.class));
break;
case TYPE_ACTIVITY_REPARENTED_TO_TASK:
@@ -408,22 +523,8 @@
}
// Notify the server, and the server should apply the WindowContainerTransaction.
- onTransactionHandled(transaction.getTransactionToken(), wct);
- }
-
- @Override
- public void applyTransaction(@NonNull WindowContainerTransaction t) {
- t.setTaskFragmentOrganizer(mInterface);
- super.applyTransaction(t);
- }
-
- // Suppress the lint because it is not a registration method.
- @SuppressWarnings("ExecutorRegistration")
- @Override
- public int applySyncTransaction(@NonNull WindowContainerTransaction t,
- @NonNull WindowContainerTransactionCallback callback) {
- t.setTaskFragmentOrganizer(mInterface);
- return super.applySyncTransaction(t, callback);
+ onTransactionHandled(transaction.getTransactionToken(), wct, getTransitionType(wct),
+ false /* shouldApplyIndependently */);
}
private final ITaskFragmentOrganizer mInterface = new ITaskFragmentOrganizer.Stub() {
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index b263b08..dc1f612 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -119,6 +119,12 @@
/** The container is going to show IME on its task after the transition. */
public static final int FLAG_WILL_IME_SHOWN = 1 << 11;
+ /** The container attaches owner profile thumbnail for cross profile animation. */
+ public static final int FLAG_CROSS_PROFILE_OWNER_THUMBNAIL = 1 << 12;
+
+ /** The container attaches work profile thumbnail for cross profile animation. */
+ public static final int FLAG_CROSS_PROFILE_WORK_THUMBNAIL = 1 << 13;
+
/** @hide */
@IntDef(prefix = { "FLAG_" }, value = {
FLAG_NONE,
@@ -508,6 +514,11 @@
return mFlags;
}
+ /** Whether the given change flags has included in this change. */
+ public boolean hasFlags(@ChangeFlags int flags) {
+ return (mFlags & flags) != 0;
+ }
+
/**
* @return the bounds of the container before the change. It may be empty if the container
* is coming into existence.
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index 567b164..ffbdf08 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -456,6 +456,17 @@
}
/**
+ * Finds and removes a task and its children using its container token. The task is removed
+ * from recents.
+ * @param containerToken ContainerToken of Task to be removed
+ */
+ @NonNull
+ public WindowContainerTransaction removeTask(@NonNull WindowContainerToken containerToken) {
+ mHierarchyOps.add(HierarchyOp.createForRemoveTask(containerToken.asBinder()));
+ return this;
+ }
+
+ /**
* Sends a pending intent in sync.
* @param sender The PendingIntent sender.
* @param intent The fillIn intent to patch over the sender's base intent.
@@ -682,7 +693,6 @@
* TaskFragment.
* @param fragmentToken client assigned unique token to create TaskFragment with specified in
* {@link TaskFragmentCreationParams#getFragmentToken()}.
- * @hide
*/
@NonNull
public WindowContainerTransaction requestFocusOnTaskFragment(@NonNull IBinder fragmentToken) {
@@ -753,10 +763,8 @@
* @hide
*/
@NonNull
- WindowContainerTransaction setTaskFragmentOrganizer(@NonNull ITaskFragmentOrganizer organizer) {
- if (mTaskFragmentOrganizer != null) {
- throw new IllegalStateException("Can't set multiple organizers for one transaction.");
- }
+ public WindowContainerTransaction setTaskFragmentOrganizer(
+ @NonNull ITaskFragmentOrganizer organizer) {
mTaskFragmentOrganizer = organizer;
return this;
}
@@ -1154,6 +1162,7 @@
public static final int HIERARCHY_OP_TYPE_REMOVE_INSETS_PROVIDER = 17;
public static final int HIERARCHY_OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT = 18;
public static final int HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP = 19;
+ public static final int HIERARCHY_OP_TYPE_REMOVE_TASK = 20;
// The following key(s) are for use with mLaunchOptions:
// When launching a task (eg. from recents), this is the taskId to be launched.
@@ -1283,6 +1292,13 @@
.build();
}
+ /** create a hierarchy op for deleting a task **/
+ public static HierarchyOp createForRemoveTask(@NonNull IBinder container) {
+ return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REMOVE_TASK)
+ .setContainer(container)
+ .build();
+ }
+
/** Only creates through {@link Builder}. */
private HierarchyOp(int type) {
mType = type;
@@ -1466,6 +1482,8 @@
case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP:
return "{setAlwaysOnTop: container=" + mContainer
+ " alwaysOnTop=" + mAlwaysOnTop + "}";
+ case HIERARCHY_OP_TYPE_REMOVE_TASK:
+ return "{RemoveTask: task=" + mContainer + "}";
default:
return "{mType=" + mType + " container=" + mContainer + " reparent=" + mReparent
+ " mToTop=" + mToTop
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index e9e437f..0e1ed7b 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1283,9 +1283,6 @@
}
if (target != null) {
- if (intent != null && isLaunchingTargetInOtherProfile()) {
- prepareIntentForCrossProfileLaunch(intent);
- }
safelyStartActivity(target);
// Rely on the ActivityManager to pop up a dialog regarding app suspension
@@ -1298,15 +1295,6 @@
return true;
}
- private void prepareIntentForCrossProfileLaunch(Intent intent) {
- intent.fixUris(UserHandle.myUserId());
- }
-
- private boolean isLaunchingTargetInOtherProfile() {
- return mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier()
- != UserHandle.myUserId();
- }
-
@VisibleForTesting
public void safelyStartActivity(TargetInfo cti) {
// We're dispatching intents that might be coming from legacy apps, so
@@ -1513,9 +1501,6 @@
findViewById(R.id.button_open).setOnClickListener(v -> {
Intent intent = otherProfileResolveInfo.getResolvedIntent();
- if (intent != null) {
- prepareIntentForCrossProfileLaunch(intent);
- }
safelyStartActivityAsUser(otherProfileResolveInfo,
inactiveAdapter.mResolverListController.getUserHandle());
finish();
diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
index ff188dc..1be1247 100644
--- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
+++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
@@ -207,7 +207,11 @@
case TYPE_HEADER_ALL_OTHERS:
TextView textView = (TextView) itemView;
if (itemType == TYPE_HEADER_SUGGESTED) {
- setTextTo(textView, R.string.language_picker_section_suggested);
+ if (mCountryMode) {
+ setTextTo(textView, R.string.language_picker_regions_section_suggested);
+ } else {
+ setTextTo(textView, R.string.language_picker_section_suggested);
+ }
} else {
if (mCountryMode) {
setTextTo(textView, R.string.region_picker_section_all);
diff --git a/core/java/com/android/internal/app/chooser/DisplayResolveInfo.java b/core/java/com/android/internal/app/chooser/DisplayResolveInfo.java
index 96cc5e1b..5f4a9cd 100644
--- a/core/java/com/android/internal/app/chooser/DisplayResolveInfo.java
+++ b/core/java/com/android/internal/app/chooser/DisplayResolveInfo.java
@@ -172,12 +172,14 @@
@Override
public boolean startAsCaller(ResolverActivity activity, Bundle options, int userId) {
+ prepareIntentForCrossProfileLaunch(mResolvedIntent, userId);
activity.startActivityAsCaller(mResolvedIntent, options, false, userId);
return true;
}
@Override
public boolean startAsUser(Activity activity, Bundle options, UserHandle user) {
+ prepareIntentForCrossProfileLaunch(mResolvedIntent, user.getIdentifier());
activity.startActivityAsUser(mResolvedIntent, options, user);
return false;
}
@@ -222,6 +224,13 @@
}
};
+ private static void prepareIntentForCrossProfileLaunch(Intent intent, int targetUserId) {
+ final int currentUserId = UserHandle.myUserId();
+ if (targetUserId != currentUserId) {
+ intent.fixUris(currentUserId);
+ }
+ }
+
private DisplayResolveInfo(Parcel in) {
mDisplayLabel = in.readCharSequence();
mExtendedInfo = in.readCharSequence();
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 7c08a7b..6c689ff 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -548,6 +548,12 @@
*/
public static final String TASK_MANAGER_SHOW_FOOTER_DOT = "task_manager_show_footer_dot";
+ /**
+ * (boolean) Whether the task manager should show a stop button if the app is allowlisted
+ * by the user.
+ */
+ public static final String TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS =
+ "show_stop_button_for_user_allowlisted_apps";
/**
* (boolean) Whether the clipboard overlay is enabled.
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 06473b5..98d4c59 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -6144,8 +6144,7 @@
}
@GuardedBy("this")
- public void noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event,
- long elapsedRealtimeMs, long uptimeMs) {
+ public void noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs) {
if (mOnBatteryInternal) {
uid = mapUid(uid);
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event);
@@ -9957,14 +9956,14 @@
}
@Override
- public void noteUserActivityLocked(@PowerManager.UserActivityEvent int event) {
+ public void noteUserActivityLocked(int type) {
if (mUserActivityCounters == null) {
initUserActivityLocked();
}
- if (event >= 0 && event < NUM_USER_ACTIVITY_TYPES) {
- mUserActivityCounters[event].stepAtomic();
+ if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
+ mUserActivityCounters[type].stepAtomic();
} else {
- Slog.w(TAG, "Unknown user activity event " + event + " was specified.",
+ Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
new Throwable());
}
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 65bec0e..44cfe1a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -264,11 +264,6 @@
void stopTracing();
/**
- * Handles a logging command from the WM shell command.
- */
- void handleWindowManagerLoggingCommand(in String[] args, in ParcelFileDescriptor outFd);
-
- /**
* If true, suppresses the ambient display from showing. If false, re-enables the ambient
* display.
*/
diff --git a/core/java/com/android/internal/widget/LocalImageResolver.java b/core/java/com/android/internal/widget/LocalImageResolver.java
index b11ea29..9ef7ce38 100644
--- a/core/java/com/android/internal/widget/LocalImageResolver.java
+++ b/core/java/com/android/internal/widget/LocalImageResolver.java
@@ -19,6 +19,8 @@
import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.ImageDecoder;
@@ -109,13 +111,13 @@
}
break;
case Icon.TYPE_RESOURCE:
- if (!(TextUtils.isEmpty(icon.getResPackage())
- || context.getPackageName().equals(icon.getResPackage()))) {
- // We can't properly resolve icons from other packages here, so fall back.
+ Resources res = resolveResourcesForIcon(context, icon);
+ if (res == null) {
+ // We couldn't resolve resources properly, fall back to icon loading.
return icon.loadDrawable(context);
}
- Drawable result = resolveImage(icon.getResId(), context, maxWidth, maxHeight);
+ Drawable result = resolveImage(res, icon.getResId(), maxWidth, maxHeight);
if (result != null) {
return tintDrawable(icon, result);
}
@@ -159,6 +161,13 @@
}
@Nullable
+ private static Drawable resolveImage(Resources res, @DrawableRes int resId, int maxWidth,
+ int maxHeight) {
+ final ImageDecoder.Source source = ImageDecoder.createSource(res, resId);
+ return resolveImage(source, maxWidth, maxHeight);
+ }
+
+ @Nullable
private static Drawable resolveBitmapImage(Icon icon, Context context, int maxWidth,
int maxHeight) {
@@ -259,4 +268,52 @@
}
return icon.getUri();
}
+
+ /**
+ * Resolves the correct resources package for a given Icon - it may come from another
+ * package.
+ *
+ * @see Icon#loadDrawableInner(Context)
+ * @hide
+ *
+ * @return resources instance if the operation succeeded, null otherwise
+ */
+ @Nullable
+ @VisibleForTesting
+ public static Resources resolveResourcesForIcon(Context context, Icon icon) {
+ if (icon.getType() != Icon.TYPE_RESOURCE) {
+ return null;
+ }
+
+ // Icons cache resolved resources, use cache if available.
+ Resources res = icon.getResources();
+ if (res != null) {
+ return res;
+ }
+
+ String resPackage = icon.getResPackage();
+ // No package means we try to use current context.
+ if (TextUtils.isEmpty(resPackage) || context.getPackageName().equals(resPackage)) {
+ return context.getResources();
+ }
+
+ if ("android".equals(resPackage)) {
+ return Resources.getSystem();
+ }
+
+ final PackageManager pm = context.getPackageManager();
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(resPackage,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.GET_SHARED_LIBRARY_FILES);
+ if (ai != null) {
+ return pm.getResourcesForApplication(ai);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, String.format("Unable to resolve package %s for icon %s", resPackage, icon));
+ return null;
+ }
+
+ return null;
+ }
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index a1be884..aa66171 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -401,6 +401,7 @@
// (e.g. gDefaultServiceManager)
"libbinder",
"libhidlbase", // libhwbinder is in here
+ "libvintf",
],
},
},
diff --git a/core/proto/android/app/notificationmanager.proto b/core/proto/android/app/notificationmanager.proto
index b88315e..3342c79 100644
--- a/core/proto/android/app/notificationmanager.proto
+++ b/core/proto/android/app/notificationmanager.proto
@@ -45,6 +45,8 @@
MEDIA = 7;
// System (catch-all for non-never suppressible sounds) are prioritized.
SYSTEM = 8;
+ // Priority conversations are prioritized
+ CONVERSATIONS = 9;
}
repeated Category priority_categories = 1;
diff --git a/core/proto/android/server/vibrator/vibratormanagerservice.proto b/core/proto/android/server/vibrator/vibratormanagerservice.proto
index 25a1f68..c211a5e 100644
--- a/core/proto/android/server/vibrator/vibratormanagerservice.proto
+++ b/core/proto/android/server/vibrator/vibratormanagerservice.proto
@@ -127,6 +127,7 @@
IGNORED_FOR_RINGER_MODE = 23;
IGNORED_FOR_SETTINGS = 24;
IGNORED_SUPERSEDED = 25;
+ IGNORED_FROM_VIRTUAL_DEVICE = 26;
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ce372e7..b91bd18 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -920,7 +920,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.SEND_SMS"
@@ -934,7 +934,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.RECEIVE_SMS"
@@ -948,7 +948,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.READ_SMS"
@@ -962,7 +962,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.RECEIVE_WAP_PUSH"
@@ -976,7 +976,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.RECEIVE_MMS"
@@ -1011,7 +1011,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
@hide Pending API council approval -->
@@ -1056,7 +1056,7 @@
targetSdkVersion}</a> is 4 or higher.
<p> This is a soft restricted permission which cannot be held by an app it its
- full form until the installer on record whitelists the permission.
+ full form until the installer on record allowlists the permission.
Specifically, if the permission is allowlisted the holder app can access
external storage and the visual and aural media collections while if the
permission is not allowlisted the holder app can only access to the visual
@@ -1236,7 +1236,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
@@ -1298,7 +1298,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.READ_CALL_LOG"
@@ -1322,7 +1322,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.WRITE_CALL_LOG"
@@ -1338,7 +1338,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
@deprecated Applications should use {@link android.telecom.CallRedirectionService} instead
@@ -4753,7 +4753,7 @@
android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to allowlist restricted permissions
- on any of the whitelists.
+ on any of the allowlists.
@hide -->
<permission android:name="android.permission.WHITELIST_RESTRICTED_PERMISSIONS"
android:protectionLevel="signature|installer" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 37435c1..9503948 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Vingerafdrukhandeling is gekanselleer."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Vingerafdrukhandeling is deur gebruiker gekanselleer."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Te veel pogings. Probeer later weer."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Te veel pogings. Vingerafdruksensor is gedeaktiveer."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Probeer weer."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Geen vingerafdrukke is geregistreer nie."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Hierdie toetstel het nie \'n vingerafdruksensor nie."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Berei tans <xliff:g id="APPNAME">%1$s</xliff:g> voor."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Begin programme."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Voltooi herlaai."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Gaan voort met opstelling?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Jy het die aan/af-skakelaar gedruk – dit skakel gewoonlik die skerm af.\n\nProbeer liggies tik terwyl jy jou vingerafdruk opstel."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Skakel skerm af"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Doen opstelling"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tik om skerm af te skakel"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Skakel skerm af"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Gaan voort met vingerafdrukverifiëring?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Jy het die aan/af-skakelaar gedruk – dit skakel gewoonlik die skerm af.\n\nProbeer liggies tik om jou vingerafdruk te verifieer."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Skakel skerm af"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Tik om op te stel"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Kies om op te stel"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Jy sal dalk die toestel moet herformateer. Tik om uit te skiet."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Om foto\'s en media oor te dra"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Om foto\'s, video\'s, musiek en meer te berg"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Blaai deur medialêers"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Kwessie met <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> werk nie"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Tik om reg te stel"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> is korrup. Kies om reg te stel."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Jy sal dalk die toestel moet herformateer. Tik om uit te skiet."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Niegesteunde <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> is bespeur"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> werk nie"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Hierdie toestel steun nie hierdie <xliff:g id="NAME">%s</xliff:g> nie. Tik om in \'n gesteunde formaat op te stel."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Tik om op te stel ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Kies om <xliff:g id="NAME">%s</xliff:g> in \'n gesteunde formaat op te stel."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Jy sal dalk die toestel moet herformateer"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> is onverwags verwyder"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Streekvoorkeur"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Voer taalnaam in"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Voorgestel"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Voorgestel"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Alle tale"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Allle streke"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Soek"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Gee <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> toegang tot alle toestelloglêers?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Gee eenmalige toegang"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Moenie toelaat nie"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Toestelloglêers teken aan wat op jou toestel gebeur. Programme kan hierdie loglêers gebruik om kwessies op te spoor en reg te stel.\n\nSommige loglêers bevat dalk sensitiewe inligting en daarom moet jy toegang tot alle toestelloglêers net gee aan programme wat jy vertrou. \n\nAs jy nie vir hierdie program toegang tot alle toestelloglêers gee nie, het dit steeds toegang tot sy eie loglêers. Jou toestelvervaardiger het dalk steeds toegang tot sommige loglêers of inligting op jou toestel. Kom meer te wete"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Toestelloglêers teken aan wat op jou toestel gebeur. Programme kan hierdie loglêers gebruik om kwessies op te spoor en reg te stel.\n\nSommige loglêers bevat dalk sensitiewe inligting en daarom moet jy toegang tot alle toestelloglêers net gee aan programme wat jy vertrou. \n\nAs jy nie vir hierdie program toegang tot alle toestelloglêers gee nie, het die program steeds toegang tot eie loglêers. Jou toestelvervaardiger het dalk steeds toegang tot sommige loglêers of inligting op jou toestel."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Moenie weer wys nie"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> wil <xliff:g id="APP_2">%2$s</xliff:g>-skyfies wys"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Wysig"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Gaan aktiewe programme na"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Kan nie toegang tot die foon se kamera op jou <xliff:g id="DEVICE">%1$s</xliff:g> kry nie"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Kan nie toegang tot die tablet se kamera op jou <xliff:g id="DEVICE">%1$s</xliff:g> kry nie"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Jy kan nie toegang hiertoe kry terwyl daar gestroom word nie. Probeer eerder op jou foon."</string>
<string name="system_locale_title" msgid="711882686834677268">"Stelselverstek"</string>
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index d777334..a219085 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -331,7 +331,7 @@
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"መስተጋበር የሚፈጥሩት የመስኮት ይዘት ይመርምሩ።"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"በመንካት ያስሱን ያብሩ"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"መታ የተደረጉ ንጥሎች ጮክ ተብለው ይነገሩና የጣት ምልክቶችን በመጠቀም ማያ ገጹ ሊታሰስ ይችላል።"</string>
- <string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"የሚተይቡት ጽሑፍ ይመልከቱ"</string>
+ <string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"የሚተይቡት ጽሁፍ ይመልከቱ"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"እንደ የክሬዲት ካርድ ቁጥሮች እና የይለፍ ቃላት ያሉ የግል ውሂብ ያካትታል።"</string>
<string name="capability_title_canControlMagnification" msgid="7701572187333415795">"የመቆጣጠሪያ ማሳያ እንዲጎላ አደራረግ"</string>
<string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"የማሳያውን የማጉያ ደረጃ እና አቀማመጥ ይቆጣጠሩ።"</string>
@@ -372,9 +372,9 @@
<string name="permlab_sendSms" msgid="7757368721742014252">"የኤስኤምኤስ መልዕክቶችን ይላኩና ይመልከቱ"</string>
<string name="permdesc_sendSms" msgid="6757089798435130769">"መተግበሪያው የኤስ.ኤም.ኤስ. መልዕክቶችን እንዲልክ ይፈቅድለታል። ይህ ያልተጠበቁ ወጪዎችን ሊያስከትል ይችላል። ተንኮል አዘል መተግበሪያዎች ያላንተ ማረጋገጫ መልዕክቶችን በመላክ ገንዘብ ሊያስወጡህ ይችላሉ።"</string>
<string name="permlab_readSms" msgid="5164176626258800297">"የጽሑፍ መልዕክቶችዎን ያንብቡ (ኤስ.ኤም.ኤስ. ወይም ኤም.ኤም.ኤስ.)"</string>
- <string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"ይህ መተግበሪያ በእርስዎ ጡባዊ ላይ የተከማቹ ሁሉንም አጭር የስልክ መልዕክት (ጽሑፍ) መልእክቶን ማንበብ ይችላል።"</string>
- <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"ይህ መተግበሪያ በእርስዎ Android TV መሣሪያ ላይ ያሉትን ሁሉንም ኤስኤምኤስ (ጽሑፍ) መልዕክቶችን ማንበብ ይችላል።"</string>
- <string name="permdesc_readSms" product="default" msgid="774753371111699782">"ይህ መተግበሪያ በእርስዎ ስልክ ላይ የተከማቹ ሁሉንም አጭር የስልክ መልዕክት (ጽሑፍ) መልእክቶን ማንበብ ይችላል።"</string>
+ <string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"ይህ መተግበሪያ በእርስዎ ጡባዊ ላይ የተከማቹ ሁሉንም አጭር የስልክ መልዕክት (ጽሁፍ) መልእክቶን ማንበብ ይችላል።"</string>
+ <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"ይህ መተግበሪያ በእርስዎ Android TV መሣሪያ ላይ ያሉትን ሁሉንም ኤስኤምኤስ (ጽሁፍ) መልዕክቶችን ማንበብ ይችላል።"</string>
+ <string name="permdesc_readSms" product="default" msgid="774753371111699782">"ይህ መተግበሪያ በእርስዎ ስልክ ላይ የተከማቹ ሁሉንም አጭር የስልክ መልዕክት (ጽሁፍ) መልእክቶን ማንበብ ይችላል።"</string>
<string name="permlab_receiveWapPush" msgid="4223747702856929056">"የፅሁፍ መልዕክቶችን ተቀበል (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="1638677888301778457">"መተግበሪያው የWAP መልዕክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ፈቃድ የተላኩልዎን መልዕክቶች ለእርስዎ ሳያሳይዎ የመቆጣጠር ወይም የመሰረዝ ብቃትን ያጠቃልላል።"</string>
<string name="permlab_getTasks" msgid="7460048811831750262">"አሂድ መተግበሪያዎችን ሰርስረው ያውጡ"</string>
@@ -555,7 +555,7 @@
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"የማያ ገጽዎን መቆለፊያ ያሰናክሉ"</string>
<string name="permdesc_disableKeyguard" msgid="3223710003098573038">"መተግበሪያው መቆለፊያውና ማንኛውም የተጎዳኘ የይለፍ ቃል ደህንነት እንዲያሰናክል ይፈቅድለታል። ለምሳሌ ስልኩ ገቢ የስልክ ጥሪ በሚቀበልበት ጊዜ መቆለፊያውን ያሰናክልና ከዚያም ጥሪው ሲጠናቀቅ መቆለፊያውን በድጋሚ ያነቃዋል።"</string>
<string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"የማያ ገጽ መቆለፊያ ውስብስብነትን ጠይቅ"</string>
- <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"መተግበሪያው የማያ ገጽ መቆለፊያው ውስብስብነት ደረጃ (ከፍተኛ፣ መካከለኛ፣ ዝቅተኛ ወይም ምንም) እንዲያውቅ ያስችለዋል፣ ይህም ሊሆኑ የሚችለው የማያ ገጽ መቆለፊያው ርዝመት እና ዓይነት ክልል ያመለክታል። መተግበሪያው እንዲሁም ለተጠቃሚዎች የማያ ገጽ መቆለፊያውን ወደተወሰነ ደረጃ እንዲያዘምኑት ሊጠቁማቸው ይችላል። የማያ ገጽ መቆለፊያው በስነጣ አልባ ጽሑፍ እንደማይከማች ልብ ይበሉ፣ በዚህም መተግበሪያው ትክክለኛውን የይለፍ ቃል አያውቅም።"</string>
+ <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"መተግበሪያው የማያ ገጽ መቆለፊያው ውስብስብነት ደረጃ (ከፍተኛ፣ መካከለኛ፣ ዝቅተኛ ወይም ምንም) እንዲያውቅ ያስችለዋል፣ ይህም ሊሆኑ የሚችለው የማያ ገጽ መቆለፊያው ርዝመት እና ዓይነት ክልል ያመለክታል። መተግበሪያው እንዲሁም ለተጠቃሚዎች የማያ ገጽ መቆለፊያውን ወደተወሰነ ደረጃ እንዲያዘምኑት ሊጠቁማቸው ይችላል። የማያ ገጽ መቆለፊያው በስነጣ አልባ ጽሁፍ እንደማይከማች ልብ ይበሉ፣ በዚህም መተግበሪያው ትክክለኛውን የይለፍ ቃል አያውቅም።"</string>
<string name="permlab_postNotification" msgid="4875401198597803658">"ማሳወቂያዎች አሳይ"</string>
<string name="permdesc_postNotification" msgid="5974977162462877075">"መተግበሪያው ማሳወቂያዎችን እንዲያሳይ ያስችለዋል"</string>
<string name="permlab_useBiometric" msgid="6314741124749633786">"ባዮሜትራዊ ሃርድዌርን መጠቀም"</string>
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"የጣት አሻራ ስርዓተ ክወና ተትቷል።"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"የጣት አሻራ ክወና በተጠቃሚ ተሰርዟል።"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"ከልክ በላይ ብዙ ሙከራዎች። በኋላ ላይ እንደገና ይሞክሩ።"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"በጣም ብዙ ሙከራዎች። የጣት አሻራ ዳሳሽ ተሰናክሏል።"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"እንደገና ይሞክሩ።"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ምንም የጣት አሻራዎች አልተመዘገቡም።"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ይህ መሣሪያ የጣት አሻራ ዳሳሽ የለውም።"</string>
@@ -1058,10 +1059,10 @@
<string name="save_password_remember" msgid="6490888932657708341">"አስታውስ"</string>
<string name="save_password_never" msgid="6776808375903410659">"በፍፁም"</string>
<string name="open_permission_deny" msgid="5136793905306987251">"ይህን ገጽ ለመክፈት ፈቃድ የለህም።"</string>
- <string name="text_copied" msgid="2531420577879738860">"ፅሁፍ ወደ ቅንጥብ ሰሌዳ ተገልብጧል።"</string>
+ <string name="text_copied" msgid="2531420577879738860">"ጽሁፍ ወደ ቅንጥብ ሰሌዳ ተገልብጧል።"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ከ <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> ተለጥፏል"</string>
<string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ከእርስዎ ቅንጥብ ሰሌዳ ተለጥፏል"</string>
- <string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> እርስዎ የቀዱትን ጽሑፍ ለጥፏል"</string>
+ <string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> እርስዎ የቀዱትን ጽሁፍ ለጥፏል"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> እርስዎ የቀዱትን ምስል ለጥፏል"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> እርስዎ የቀዱትን ይዘት ለጥፏል"</string>
<string name="more_item_label" msgid="7419249600215749115">"ተጨማሪ"</string>
@@ -1142,7 +1143,7 @@
<string name="replace" msgid="7842675434546657444">"ተካ..."</string>
<string name="delete" msgid="1514113991712129054">"ሰርዝ"</string>
<string name="copyUrl" msgid="6229645005987260230">"የURL ቅጂ"</string>
- <string name="selectTextMode" msgid="3225108910999318778">"ፅሁፍ ምረጥ"</string>
+ <string name="selectTextMode" msgid="3225108910999318778">"ጽሁፍ ምረጥ"</string>
<string name="undo" msgid="3175318090002654673">"ቀልብስ"</string>
<string name="redo" msgid="7231448494008532233">"ድገም"</string>
<string name="autofill" msgid="511224882647795296">"ራስ-ሙላ"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>ን ማዘጋጀት።"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"መተግበሪያዎችን በማስጀመር ላይ፡፡"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"አጨራረስ ማስነሻ፡፡"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"ማዋቀር ይቀጥሉ?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"የማብሪያ/ማጥፊያ ቁልፉን ተጭነዋል — ይህ ብዙውን ጊዜ ማያ ገጹን ያጠፋል።\n\nየጣት አሻራዎን በሚያዋቅሩበት ጊዜ በትንሹ መታ ለማድረግ ይሞክሩ።"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"ማያ ገጽን አጥፋ"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"ማዋቀር ቀጥል"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ማያ ገጽን ለማጥፋት መታ ያድርጉ"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ማያ ገጽን አጥፋ"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"የጣት አሻራዎን ማረጋገጥ ይቀጥሉ?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"የማብሪያ/ማጥፊያ ቁልፉን ተጭነዋል - ይህ ብዙውን ጊዜ ማያ ገጹን ያጠፋል። \n\n የጣት አሻራዎን ለማረጋገጥ በትንሹ መታ ለማድረግ ይሞክሩ።"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ማያ ገጽን አጥፋ"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"ለማዋቀር መታ ያድርጉ"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"ለማቀናበር ይምረጡ"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"መሣሪያውን ዳግም ቅርጸት መሥራት ሳያስፈልገዎት አይቀርም። ለማስወጣት መታ ያድርጉ።"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ፎቶዎችን እና ማህደረመረጃን ለማስተላለፍ"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ፎቶዎችን፣ ቪድዮችን፣ ሙዚቃን እና ሌሎችንም ለማከማቸት"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"የሚዲያ ፋይሎችን ያስሱ"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"ከ<xliff:g id="NAME">%s</xliff:g> ጋር ችግር"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> እየሠራ አይደለም"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"ለማስተካከል መታ ያድርጉ"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> የተበላሸ ነው። ለማስተካከል ይምረጡ።"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"መሣሪያውን ዳግም ቅርጸት መሥራት ሳያስፈልገዎት አይቀርም። ለማስወጣት መታ ያድርጉ።"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"ያልተደገፈ <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> ተገኝቷል"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> እየሠራ አይደለም"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ይህ መሣሪያ ይህን <xliff:g id="NAME">%s</xliff:g> አይደግፍም። በሚደገፍ ቅርጸት ለማዘጋጀት መታ ያድርጉ።"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"ለማዋቀር መታ ያድርጉ።"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"<xliff:g id="NAME">%s</xliff:g>ን በሚደገፍ ቅርጸት ለማዋቀር ይምረጡ።"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"መሣሪያውን ዳግም ቅርጸት መሥራት ሳያስፈልገዎት አይቀርም"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ሳይታሰብ ተወግዷል"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"የክልል ምርጫ"</string>
<string name="search_language_hint" msgid="7004225294308793583">"የቋንቋ ስም ይተይቡ"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"የተጠቆሙ"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"በአስተያየት የተጠቆሙ"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"ሁሉም ቋንቋዎች"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"ሁሉም ክልሎች"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"ፈልግ"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ሁሉንም የመሣሪያ ምዝግብ ማስታወሻዎች እንዲደርስ ይፈቀድለት?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"የአንድ ጊዜ መዳረሻን ፍቀድ"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"አትፍቀድ"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"የመሣሪያ ምዝግብ ማስታወሻዎች በመሣሪያዎ ላይ ምን እንደሚከሰት ይመዘግባሉ። መተግበሪያዎች ችግሮችን ለማግኘት እና ለማስተካከል እነዚህን ምዝግብ ማስታወሻዎች መጠቀም ይችላሉ።\n\nአንዳንድ ምዝግብ ማስታወሻዎች ሚስጥራዊነት ያለው መረጃ ሊይዙ ይችላሉ፣ ስለዚህ የሚያምኗቸውን መተግበሪያዎች ብቻ ሁሉንም የመሣሪያ ምዝግብ ማስታወሻዎች እንዲደርሱ ይፍቀዱላቸው። \n\nይህ መተግበሪያ ሁሉንም የመሣሪያ ምዝግብ ማስታወሻዎች እንዲደርስ ካልፈቀዱለት አሁንም የራሱን ምዝግብ ማስታወሻዎች መድረስ ይችላል። የእርስዎ መሣሪያ አምራች አሁንም አንዳንድ ምዝግብ ማስታወሻዎችን ወይም መረጃን በመሣሪያዎ ላይ ሊደርስ ይችላል። የበለጠ ለመረዳት"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"የመሣሪያ ምዝግብ ማስታወሻዎች በመሣሪያዎ ላይ ምን እንደሚከሰት ይመዘግባሉ። መተግበሪያዎች ችግሮችን ለማግኘት እና ለማስተካከል እነዚህን ምዝግብ ማስታወሻዎች መጠቀም ይችላሉ።\n\nአንዳንድ ምዝግብ ማስታወሻዎች ሚስጥራዊነት ያለው መረጃ ሊይዙ ይችላሉ፣ ስለዚህ የሚያምኗቸውን መተግበሪያዎች ብቻ ሁሉንም የመሣሪያ ምዝግብ ማስታወሻዎች እንዲደርሱ ይፍቀዱላቸው። \n\nይህ መተግበሪያ ሁሉንም የመሣሪያ ምዝግብ ማስታወሻዎች እንዲደርስ ካልፈቀዱለት አሁንም የራሱን ምዝግብ ማስታወሻዎች መድረስ ይችላል። የእርስዎ መሣሪያ አምራች አሁንም አንዳንድ ምዝግብ ማስታወሻዎችን ወይም መረጃዎችን በመሣሪያዎ ላይ ሊደርስ ይችላል።"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"ዳግም አታሳይ"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> የ<xliff:g id="APP_2">%2$s</xliff:g> ቁራጮችን ማሳየት ይፈልጋል"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"አርትዕ"</string>
@@ -2131,7 +2132,7 @@
<string name="accessibility_system_action_dpad_left_label" msgid="6557647179116479152">"ከDpad በስተግራ"</string>
<string name="accessibility_system_action_dpad_right_label" msgid="9180196950365804081">"ከDpad በስተቀኝ"</string>
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"የDpad ማዕከል"</string>
- <string name="accessibility_freeform_caption" msgid="8377519323496290122">"የ<xliff:g id="APP_NAME">%1$s</xliff:g> የሥዕል ገላጭ ጽሑፍ አሞሌ።"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"የ<xliff:g id="APP_NAME">%1$s</xliff:g> የሥዕል ገላጭ ጽሁፍ አሞሌ።"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ወደ የRESTRICTED ባልዲ ተከትቷል"</string>
<string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>፦"</string>
<string name="conversation_single_line_image_placeholder" msgid="6983271082911936900">"አንድ ምስል ልከዋል"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ንቁ መተግበሪያዎችን ይፈትሹ"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"የስልኩን ካሜራ ከእርስዎ <xliff:g id="DEVICE">%1$s</xliff:g> መድረስ አይቻልም"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"ጡባዊውን ካሜራ ከእርስዎ <xliff:g id="DEVICE">%1$s</xliff:g> መድረስ አይቻልም"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"ዥረት በመልቀቅ ላይ ሳለ ይህ ሊደረስበት አይችልም። በምትኩ በስልክዎ ላይ ይሞክሩ።"</string>
<string name="system_locale_title" msgid="711882686834677268">"የሥርዓት ነባሪ"</string>
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 4b04132..01fc4bd 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -612,7 +612,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"تم إلغاء تشغيل بصمة الإصبع."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"تم إلغاء تشغيل بصمة الإصبع بواسطة المستخدم."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"تم إجراء عدد كبير من المحاولات. أعد المحاولة لاحقًا."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"تم إجراء عدد كبير جدًا من المحاولات. لذا تم إيقاف جهاز استشعار بصمات الإصبع."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"أعد المحاولة."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ليست هناك بصمات إصبع مسجَّلة."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"لا يحتوي هذا الجهاز على مستشعِر بصمات إصبع."</string>
@@ -1253,10 +1254,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"جارٍ تحضير <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"بدء التطبيقات."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"جارٍ إعادة التشغيل."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"هل تريد مواصلة عملية الإعداد؟"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ضغطت على زر التشغيل، يؤدي هذا عادةً إلى إيقاف الشاشة.\n\nجرِّب النقر بخفة أثناء إعداد بصمتك."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"إيقاف الشاشة"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"مواصلة عملية الإعداد"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"النقر لإيقاف الشاشة"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"إيقاف الشاشة"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"هل تريد مواصلة تأكيد بصمة إصبعك؟"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"ضغطت على زر التشغيل، يؤدي هذا عادةً إلى إيقاف الشاشة.\n\nجرِّب النقر بخفة لتأكيد بصمة إصبعك."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"إيقاف الشاشة"</string>
@@ -1409,16 +1409,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"انقر للإعداد."</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"اختيار الوسائط لإعدادها"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"قد تحتاج إلى إعادة تنسيق الجهاز. انقر على إخراج."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"لنقل الصور والوسائط"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"لتخزين الصور والفيديوهات والموسيقى وغير ذلك."</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"تصفّح ملفات الوسائط"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"هناك مشكلة في <xliff:g id="NAME">%s</xliff:g>."</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> لا يعمل."</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"انقر للإصلاح"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> تالف، ويمكنك اختيار إصلاحه."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"قد تحتاج إلى إعادة تنسيق الجهاز. انقر على إخراج."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> غير متوافق"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"تم رصد <xliff:g id="NAME">%s</xliff:g>."</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> لا يعمل."</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"هذا الجهاز غير متوافق مع <xliff:g id="NAME">%s</xliff:g> هذا. انقر للإعداد بتنسيق متوافق."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"انقر لبدء عملية إعداد الوسائط الخارجية."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"عليك الاختيار لإعداد \"<xliff:g id="NAME">%s</xliff:g>\" بتنسيق متوافق."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"قد تحتاج إلى إعادة تنسيق الجهاز."</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"تمت إزالة <xliff:g id="NAME">%s</xliff:g> بشكل غير متوقع"</string>
@@ -1428,7 +1428,7 @@
<string name="ext_media_unmounting_notification_title" msgid="4147986383917892162">"جارٍ إخراج <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmounting_notification_message" msgid="5717036261538754203">"عدم الإزالة"</string>
<string name="ext_media_init_action" msgid="2312974060585056709">"إعداد"</string>
- <string name="ext_media_unmount_action" msgid="966992232088442745">"إلغاء"</string>
+ <string name="ext_media_unmount_action" msgid="966992232088442745">"إخراج"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"استكشاف"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"تبديل جهاز إخراج الصوت"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> مفقود"</string>
@@ -1931,6 +1931,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"تفضيل المنطقة"</string>
<string name="search_language_hint" msgid="7004225294308793583">"اكتب اسم اللغة"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"اللغات المقترَحة"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"الاقتراحات"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"جميع اللغات"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"كل المناطق"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"البحث"</string>
@@ -2053,7 +2054,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"هل تريد السماح لتطبيق <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> بالوصول إلى جميع سجلّات الجهاز؟"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"السماح بالوصول إلى السجلّ لمرة واحدة"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"عدم السماح"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"ترصد سجلّات الجهاز ما يحدث على جهازك. يمكن أن تستخدم التطبيقات هذه السجلّات لتحديد المشاكل وحلها.\n\nقد تحتوي بعض السجلّات على معلومات حساسة، ولذلك يجب عدم السماح بالوصول إلى جميع سجلّات الجهاز إلا للتطبيقات التي تثق بها. \n\nإذا لم تسمح بوصول هذا التطبيق إلى جميع سجلّات الجهاز، يظل بإمكان التطبيق الوصول إلى سجلّاته. ويظل بإمكان الشركة المصنّعة لجهازك الوصول إلى بعض السجلّات أو المعلومات المتوفّرة على جهازك. مزيد من المعلومات"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"ترصد سجلّات الجهاز ما يحدث على جهازك. يمكن أن تستخدم التطبيقات هذه السجلّات لتحديد المشاكل وحلها.\n\nقد تحتوي بعض السجلّات على معلومات حساسة، ولذلك يجب عدم السماح بالوصول إلى جميع سجلّات الجهاز إلا للتطبيقات التي تثق بها. \n\nإذا لم تسمح بوصول هذا التطبيق إلى جميع سجلّات الجهاز، يظل بإمكان التطبيق الوصول إلى سجلّاته. ويظل بإمكان الشركة المصنِّعة لجهازك الوصول إلى بعض السجلّات أو المعلومات المتوفّرة على جهازك."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"عدم الإظهار مرة أخرى"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"يريد تطبيق <xliff:g id="APP_0">%1$s</xliff:g> عرض شرائح تطبيق <xliff:g id="APP_2">%2$s</xliff:g>."</string>
<string name="screenshot_edit" msgid="7408934887203689207">"تعديل"</string>
@@ -2294,5 +2295,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"التحقّق من التطبيقات النشطة"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"يتعذّر الوصول إلى كاميرا الهاتف من على جهاز <xliff:g id="DEVICE">%1$s</xliff:g>."</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"يتعذّر الوصول إلى كاميرا الجهاز اللوحي من على جهاز <xliff:g id="DEVICE">%1$s</xliff:g>."</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"لا يمكن الوصول إلى هذا المحتوى أثناء البث. بدلاً من ذلك، جرِّب استخدام هاتفك."</string>
<string name="system_locale_title" msgid="711882686834677268">"الإعداد التلقائي للنظام"</string>
</resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 957dc54..7fed29f 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ফিংগাৰপ্ৰিণ্ট কাৰ্য বাতিল কৰা হ’ল।"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ব্যৱহাৰকাৰীয়ে ফিংগাৰপ্ৰিণ্ট ক্ৰিয়া বাতিল কৰিছে।"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"অত্যধিক ভুল প্ৰয়াস। কিছুসময়ৰ পাছত আকৌ চেষ্টা কৰক।"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"অত্যধিক প্ৰয়াস। ফিংগাৰপ্ৰিণ্ট ছেন্সৰ অক্ষম কৰা হ’ল।"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"আকৌ চেষ্টা কৰক।"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"কোনো ফিংগাৰপ্ৰিণ্ট যোগ কৰা নহ\'ল।"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"এই ডিভাইচটোত ফিংগাৰপ্ৰিণ্ট ছেন্সৰ নাই।"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>সাজু কৰি থকা হৈছে।"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"আৰম্ভ হৈ থকা এপসমূহ।"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"বুট কাৰ্য সমাপ্ত কৰিছে।"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"ছেট আপ অব্যাহত ৰাখিবনে?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"আপুনি পাৱাৰ বুটামটো টিপিছে — এইটোৱে সাধাৰণতে স্ক্ৰীনখন অফ কৰে।\n\nআপোনাৰ ফিংগাৰপ্ৰিণ্টটো ছেট আপ কৰাৰ সময়ত লাহেকৈ টিপি চাওক।"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"স্ক্ৰীন অফ কৰক"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"ছেট আপ অব্যাহত ৰাখক"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"স্ক্ৰীন অফ কৰিবলৈ টিপক"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"স্ক্ৰীন অফ কৰক"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"ফিংগাৰপ্ৰিণ্ট সত্যাপন কৰা জাৰি ৰাখিবনে?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"আপুনি পাৱাৰ বুটামটো টিপিছে — এইটোৱে সাধাৰণতে স্ক্ৰীনখন অফ কৰে।\n\nআপোনাৰ ফিংগাৰপ্ৰিণ্টটো সত্যাপন কৰিবলৈ লাহেকৈ টিপি চাওক।"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"স্ক্ৰীন অফ কৰক"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"ছেট আপ কৰিবলৈ টিপক"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"ছেট আপ কৰিবলৈ বাছনি কৰক"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"আপুনি ডিভাইচটো পুনৰ ফৰ্মেট কৰিবলগীয়া হ’ব পাৰে। বাহিৰলৈ উলিয়াবলৈ টিপক।"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ফট\' আৰু মিডিয়া স্থানান্তৰণৰ বাবে"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ফট’ ভিডিঅ’, সংগীত আৰু বহুতো ষ্ট’ৰ কৰাৰ বাবে"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"মিডিয়া ফাইল ব্ৰাউজ কৰক"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g>ত কিবা সমস্যা আছে"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g>এ কাম কৰা নাই"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"সমাধান কৰিবলৈ টিপক"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> ব্যৱহাৰযোগ্য হৈ থকা নাই। ঠিক কৰিবলৈ বাছনি কৰক।"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"আপুনি ডিভাইচটো পুনৰ ফৰ্মেট কৰিবলগীয়া হ’ব পাৰে। বাহিৰলৈ উলিয়াবলৈ টিপক।"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g>ক ব্যৱহাৰ কৰিব নোৱাৰি"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> চিনাক্ত কৰা হৈছে"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g>এ কাম কৰা নাই"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"এই ডিভাইচটোৱে <xliff:g id="NAME">%s</xliff:g>ক ব্যৱহাৰ কৰিব নোৱাৰে। ব্যৱহাৰ কৰিব পৰা ফৰ্মেটত ছেট আপ কৰিবলৈ টিপক।"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"ছেট আপ কৰিবলৈ টিপক।"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"এটা সমৰ্থিত ফৰ্মেটত <xliff:g id="NAME">%s</xliff:g> ছেট আপ কৰিবলৈ বাছনি কৰক।"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"আপুনি ডিভাইচটো পুনৰ ফৰ্মেট কৰিবলগীয়া হ’ব পাৰে"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> অপ্ৰত্য়াশিতভাৱে আঁতৰোৱা হ’ল"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"অঞ্চলৰ অগ্ৰাধিকাৰ"</string>
<string name="search_language_hint" msgid="7004225294308793583">"ভাষাৰ নাম লিখক"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"প্ৰস্তাৱিত"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"পৰামৰ্শিত"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"সকলো ভাষা"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"আটাইবোৰ অঞ্চল"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"সন্ধান কৰক"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>ক আটাইবোৰ ডিভাইচৰ লগ এক্সেছ কৰাৰ অনুমতি প্ৰদান কৰিবনে?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"কেৱল এবাৰ এক্সেছ কৰাৰ অনুমতি দিয়ক"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"অনুমতি নিদিব"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"আপোনাৰ ডিভাইচত কি কি ঘটে সেয়া ডিভাইচ লগে ৰেকৰ্ড কৰে। এপ্সমূহে সমস্যা বিচাৰিবলৈ আৰু সমাধান কৰিবলৈ এই লগসমূহ ব্যৱহাৰ কৰিব পাৰে।\n\nকিছুমান লগত সংবেদনশীল তথ্য থাকিব পাৰে, গতিকে কেৱল আপুনি বিশ্বাস কৰা এপকহে আটাইবোৰ ডিভাইচ লগ এক্সেছ কৰাৰ অনুমতি দিয়ক। \n\nআপুনি যদি এই এপ্টোক আটাইবোৰ ডিভাইচ লগ এক্সেছ কৰাৰ অনুমতি নিদিয়ে, তথাপিও ই নিজৰ লগসমূহ এক্সেছ কৰিব পাৰিব। আপোনাৰ ডিভাইচৰ নিৰ্মাতাই তথাপিও হয়তো আপোনাৰ ডিভাইচটোত থকা কিছু লগ অথবা তথ্য এক্সেছ কৰিব পাৰিব। অধিক জানক"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"আপোনাৰ ডিভাইচত কি কি ঘটে সেয়া ডিভাইচ লগে ৰেকৰ্ড কৰে। এপ্সমূহে সমস্যা বিচাৰিবলৈ আৰু সমাধান কৰিবলৈ এই লগসমূহ ব্যৱহাৰ কৰিব পাৰে।\n\nকিছুমান লগত সংবেদনশীল তথ্য থাকিব পাৰে, গতিকে কেৱল আপুনি বিশ্বাস কৰা এপকহে আটাইবোৰ ডিভাইচ লগ এক্সেছ কৰাৰ অনুমতি দিয়ক। \n\nআপুনি যদি এই এপ্টোক আটাইবোৰ ডিভাইচ লগ এক্সেছ কৰাৰ অনুমতি নিদিয়ে, তথাপিও ই নিজৰ লগসমূহ এক্সেছ কৰিব পাৰিব। আপোনাৰ ডিভাইচৰ নিৰ্মাতাই তথাপিও হয়তো আপোনাৰ ডিভাইচটোত থকা কিছু লগ অথবা তথ্য এক্সেছ কৰিব পাৰিব।"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"পুনৰ নেদেখুৱাব"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g>এ <xliff:g id="APP_2">%2$s</xliff:g>ৰ অংশ দেখুওৱাব খুজিছে"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"সম্পাদনা কৰক"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"সক্ৰিয় এপ্সমূহ পৰীক্ষা কৰক"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"আপোনাৰ <xliff:g id="DEVICE">%1$s</xliff:g>ৰ পৰা ফ’নটোৰ কেমেৰা এক্সেছ কৰিব নোৱাৰি"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"আপোনাৰ <xliff:g id="DEVICE">%1$s</xliff:g>ৰ পৰা টেবলেটটোৰ কেমেৰা এক্সেছ কৰিব নোৱাৰি"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"ষ্ট্ৰীম কৰি থকাৰ সময়ত এইটো এক্সেছ কৰিব নোৱাৰি। তাৰ পৰিৱৰ্তে আপোনাৰ ফ’নত চেষ্টা কৰি চাওক।"</string>
<string name="system_locale_title" msgid="711882686834677268">"ছিষ্টেম ডিফ’ল্ট"</string>
</resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index e139f4a9..da989ae 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Barmaq izi əməliyyatı ləğv edildi."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Barmaq izi əməliyyatı istifadəçi tərəfindən ləğv edildi."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Cəhdlər çox oldu. Sonraya saxlayın."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Həddindən çox cəhd. Barmaq izi sensoru deaktiv edilib."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Yenidən cəhd edin."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Barmaq izi qeydə alınmayıb."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Bu cihazda barmaq izi sensoru yoxdur."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> proqramının hazırlanması."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Tətbiqlər başladılır."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Yükləmə başa çatır."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Ayarlamağa davam edilsin?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Qidalanma düyməsini basdınız — adətən bu, ekranı söndürür.\n\nBarmaq izini ayarlayarkən yüngülcə toxunmağa çalışın."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Ekranı söndürün"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Ayarlamağa davam edin"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Ekranı söndürmək üçün toxunun"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Ekranı söndürün"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Barmaq izini doğrulamağa davam edilsin?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Qidalanma düyməsini basdınız — adətən bu, ekranı söndürür.\n\nBarmaq izini doğrulamaq üçün yüngülcə toxunmağa çalışın."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Ekranı söndürün"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Quraşdırmaq üçün klikləyin"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Ayarlamaq üçün seçin"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Cihazı yenidən formatlamaq tələb oluna bilər. Çıxarmaq üçün toxunun."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Fotoların və medianın köçürülməsi üçün"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Fotoları, videoları, musiqiləri və s. saxlamaq üçün"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Media fayllarına nəzər salın"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> ilə bağlı problem"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> işləmir"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Həll etmək üçün klikləyin"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> zədələnib. Düzəltmək üçün seçin."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Cihazı yenidən formatlamaq tələb oluna bilər. Çıxarmaq üçün toxunun."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Dəstəklənməyən <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> aşkarlandı"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> işləmir"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"<xliff:g id="NAME">%s</xliff:g> bu cihaz tərəfindən dəstəklənmir. Dəstəklənən formatda ayarlamaq üçün tıklayın."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Ayarlamaq üçün toxunun."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"<xliff:g id="NAME">%s</xliff:g> elementinin dəstəklənən formatda ayarlanmasını seçin."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Cihazı yenidən formatlamaq tələb oluna bilər"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> gözlənilmədən çıxarıldı"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Region seçimi"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Dil adını daxil edin"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Təklif edilmiş"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Təklif edilib"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Bütün dillər"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Bütün bölgələr"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Axtarın"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> tətbiqinin bütün cihaz qeydlərinə girişinə icazə verilsin?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Birdəfəlik girişə icazə verin"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"İcazə verməyin"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Cihaz qeydləri cihazınızda baş verənləri qeyd edir. Tətbiqlər problemləri tapmaq və həll etmək üçün bu qeydlərdən istifadə edə bilər.\n\nBəzi qeydlərdə həssas məlumatlar ola bilər, ona görə də yalnız etibar etdiyiniz tətbiqlərin bütün cihaz qeydlərinə giriş etməsinə icazə verin. \n\nBu tətbiqin bütün cihaz qeydlərinə girişinə icazə verməsəniz, o, hələ də öz qeydlərinə giriş edə bilər. Cihaz istehsalçınız hələ də cihazınızda bəzi qeydlərə və ya məlumatlara giriş edə bilər. Ətraflı məlumat"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Cihaz qeydləri cihazınızda baş verənləri qeyd edir. Tətbiqlər problemləri tapmaq və həll etmək üçün bu qeydlərdən istifadə edə bilər.\n\nBəzi qeydlərdə həssas məlumatlar ola bilər, ona görə də yalnız etibar etdiyiniz tətbiqlərin bütün cihaz qeydlərinə giriş etməsinə icazə verin. \n\nBu tətbiqin bütün cihaz qeydlərinə girişinə icazə verməsəniz, o, hələ də öz qeydlərinə giriş edə bilər. Cihaz istehsalçınız hələ də cihazınızda bəzi qeydlərə və ya məlumatlara giriş edə bilər."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Daha göstərməyin"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> <xliff:g id="APP_2">%2$s</xliff:g> tətbiqindən bölmələr göstərmək istəyir"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Redaktə edin"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Aktiv tətbiqləri yoxlayın"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan telefonun kamerasına giriş etmək olmur"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan planşetin kamerasına giriş etmək olmur"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Yayım zamanı buna giriş mümkün deyil. Telefonunuzda sınayın."</string>
<string name="system_locale_title" msgid="711882686834677268">"Sistem defoltu"</string>
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 86e8735..23397b0 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -609,7 +609,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Radnja sa otiskom prsta je otkazana."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Korisnik je otkazao radnju sa otiskom prsta."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Previše pokušaja. Probajte ponovo kasnije."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Previše pokušaja. Senzor za otisak prsta je onemogućen."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Probajte ponovo."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nije registrovan nijedan otisak prsta."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ovaj uređaj nema senzor za otisak prsta."</string>
@@ -1250,10 +1251,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Priprema se <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Pokretanje aplikacija."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Završavanje pokretanja."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Želite li da nastavite sa podešavanjem?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Pritisnuli ste dugme za uključivanje – time obično isključujete ekran.\n\nProbajte lagano da dodirnete dok podešavate otisak prsta."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Isključi ekran"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Nastavi podešavanje"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Dodirnite da biste isključili ekran"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Isključi ekran"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Nastavljate verifikaciju otiska prsta?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Pritisnuli ste dugme za uključivanje – time obično isključujete ekran.\n\nProbajte lagano da dodirnete da biste verifikovali otisak prsta."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Isključi ekran"</string>
@@ -1406,16 +1406,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Dodirnite da biste podesili"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Izaberite da biste podesili"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Možda morate da reformatirate uređaj. Dodirnite da biste izbacili."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Za prenos slika i medija"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Za čuvanje slika, video snimaka, muzike i drugog sadržaja"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Pregledajte medijske fajlove"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problem sa: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ne radi"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Dodirnite da biste ispravili"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Medij <xliff:g id="NAME">%s</xliff:g> je oštećen. Izaberite da ga popravite."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Možda morate da reformatirate uređaj. Dodirnite da biste izbacili."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Uređaj <xliff:g id="NAME">%s</xliff:g> nije podržan"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Otkriveno: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ne radi"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Ovaj uređaj ne podržava ovaj uređaj <xliff:g id="NAME">%s</xliff:g>. Dodirnite da biste podesili podržani format."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Dodirnite da biste podesili."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Izaberite da biste podesili uređaj <xliff:g id="NAME">%s</xliff:g> u podržanom formatu."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Možda morate da reformatirate uređaj"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Uređaj <xliff:g id="NAME">%s</xliff:g> je neočekivano uklonjen"</string>
@@ -1928,6 +1928,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Podešavanje regiona"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Unesite naziv jezika"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Predloženi"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Predloženo"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Svi jezici"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Svi regioni"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Pretraži"</string>
@@ -2050,7 +2051,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Želite da dozvolite aplikaciji <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> da pristupa svim evidencijama uređaja?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Dozvoli jednokratan pristup"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Ne dozvoli"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Evidencije uređaja registruju šta se dešava na uređaju. Aplikacije mogu da koriste te evidencije da bi pronašle i rešile probleme.\n\nNeke evidencije mogu da sadrže osetljive informacije, pa pristup svim evidencijama uređaja treba da dozvoljavate samo aplikacijama u koje imate poverenja. \n\nAko ne dozvolite ovoj aplikaciji da pristupa svim evidencijama uređaja, ona i dalje može da pristupa sopstvenim evidencijama. Proizvođač uređaja će možda i dalje moći da pristupa nekim evidencijama ili informacijama na uređaju. Saznajte više"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Evidencije uređaja registruju šta se dešava na uređaju. Aplikacije mogu da koriste te evidencije da bi pronašle i rešile probleme.\n\nNeke evidencije mogu da sadrže osetljive informacije, pa pristup svim evidencijama uređaja treba da dozvoljavate samo aplikacijama u koje imate poverenja. \n\nAko ne dozvolite ovoj aplikaciji da pristupa svim evidencijama uređaja, ona i dalje može da pristupa sopstvenim evidencijama. Proizvođač uređaja će možda i dalje moći da pristupa nekim evidencijama ili informacijama na uređaju."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ne prikazuj ponovo"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Aplikacija <xliff:g id="APP_0">%1$s</xliff:g> želi da prikazuje isečke iz aplikacije <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Izmeni"</string>
@@ -2291,5 +2292,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Proverite aktivne aplikacije"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Ne može da se pristupi kameri telefona sa <xliff:g id="DEVICE">%1$s</xliff:g> uređaja"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Ne može da se pristupi kameri tableta sa <xliff:g id="DEVICE">%1$s</xliff:g> uređaja"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Ovom ne možete da pristupate tokom strimovanja. Probajte na telefonu."</string>
<string name="system_locale_title" msgid="711882686834677268">"Podrazumevani sistemski"</string>
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index a24aee7..0079624 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -610,7 +610,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Аперацыя з адбіткамі пальцаў скасавана."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Аўтэнтыфікацыя па адбітках пальцаў скасавана карыстальнікам."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Занадта шмат спроб. Паспрабуйце яшчэ раз пазней."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Занадта шмат спроб. Сканер адбіткаў пальцаў выключаны."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Паўтарыце спробу."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Адбіткі пальцаў не зарэгістраваны."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"На гэтай прыладзе няма сканера адбіткаў пальцаў."</string>
@@ -1251,10 +1252,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Падрыхтоўка <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Запуск прыкладанняў."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Завяршэнне загрузкі."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Працягнуць наладжванне?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Вы націснулі кнопку сілкавання. Звычайна ў выніку гэтага дзеяння выключаецца экран.\n\nПадчас наладжвання адбітка пальца злёгку дакраніцеся да кнопкі."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Выключыць экран"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Працягнуць наладку"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Націсніце, каб выключыць экран"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Выключыць экран"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Працягнуць спраўджанне адбітка пальца?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Вы націснулі кнопку сілкавання. Звычайна ў выніку гэтага дзеяння выключаецца экран.\n\nКаб спраўдзіць адбітак пальца, злёгку дакраніцеся да кнопкі."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Выключыць экран"</string>
@@ -1407,16 +1407,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Дакраніцеся, каб наладзіць"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Выберыце, каб наладзіць"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Магчыма, вам спатрэбіцца перафармаціраваць прыладу. Націсніце, каб выняць."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Для перадачы фатаграфій і медыяфайлаў"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Для захоўвання фота, відэа, музыкі і іншага змесціва"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Пошук медыяфайлаў"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Праблема з носьбітам (<xliff:g id="NAME">%s</xliff:g>)"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> не працуе"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Націсніце, каб выправіць"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Носьбіт <xliff:g id="NAME">%s</xliff:g> пашкоджаны. Выберыце, каб выправіць."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Магчыма, вам спатрэбіцца перафармаціраваць прыладу. Націсніце, каб выняць."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> не падтрымліваецца"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Выяўлены носьбіт \"<xliff:g id="NAME">%s</xliff:g>\""</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> не працуе"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Гэта прылада не падтрымлівае носьбіт <xliff:g id="NAME">%s</xliff:g>. Дакраніцеся, каб наладзіць яго ў фармаце, які падтрымліваецца."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Дакраніцеся, каб наладзіць ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Выберыце, каб задаць для носьбіта \"<xliff:g id="NAME">%s</xliff:g>\" фармат, які падтрымліваецца."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Магчыма, вам спатрэбіцца перафармаціраваць прыладу"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Носьбіт <xliff:g id="NAME">%s</xliff:g> нечакана выняты"</string>
@@ -1929,6 +1929,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Параметры рэгіёна"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Увядзіце назву мовы"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Прапанаваныя"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Прапанавана"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Усе мовы"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Усе рэгіёны"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Шукаць"</string>
@@ -2051,7 +2052,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Дазволіць праграме \"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>\" мець доступ да ўсіх журналаў прылады?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Дазволіць аднаразовы доступ"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Не дазваляць"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Журналы прылад запісваюць усё, што адбываецца на вашай прыладзе. Праграмы выкарыстоўваюць гэтыя журналы для пошуку і выпраўлення памылак.\n\nУ некаторых журналах можа ўтрымлівацца канфідэнцыяльная інфармацыя, таму давайце доступ да ўсіх журналаў прылады толькі тым праграмам, якім вы давяраеце. \n\nКалі вы не дасце гэтай праграме доступу да ўсіх журналаў прылад, у яе ўсё роўна застанецца доступ да ўласных журналаў. Для вытворцы вашай прылады будуць даступнымі некаторыя журналы і інфармацыя на вашай прыладзе. Даведацца больш"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Журналы прылад запісваюць усё, што адбываецца на вашай прыладзе. Праграмы выкарыстоўваюць гэтыя журналы для пошуку і выпраўлення памылак.\n\nУ некаторых журналах можа ўтрымлівацца канфідэнцыяльная інфармацыя, таму давайце доступ да ўсіх журналаў прылады толькі тым праграмам, якім вы давяраеце. \n\nКалі вы не дасце гэтай праграме доступу да ўсіх журналаў прылад, у яе ўсё роўна застанецца доступ да ўласных журналаў. Для вытворцы вашай прылады будуць даступнымі некаторыя журналы і інфармацыя на вашай прыладзе."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Больш не паказваць"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Праграма <xliff:g id="APP_0">%1$s</xliff:g> запытвае дазвол на паказ зрэзаў праграмы <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Рэдагаваць"</string>
@@ -2292,5 +2293,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Праверце актыўныя праграмы"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Не ўдалося атрымаць доступ да камеры тэлефона з прылады \"<xliff:g id="DEVICE">%1$s</xliff:g>\""</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Не ўдалося атрымаць доступ да камеры планшэта з прылады \"<xliff:g id="DEVICE">%1$s</xliff:g>\""</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Не ўдаецца атрымаць доступ у час перадачы плынню. Паспрабуйце скарыстаць тэлефон."</string>
<string name="system_locale_title" msgid="711882686834677268">"Стандартная сістэмная налада"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 86443d7..b5d9125 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Операцията за отпечатък е анулирана."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Операцията за удостоверяване чрез отпечатък бе анулирана от потребителя."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Твърде много опити. Пробвайте отново по-късно."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Твърде много опити. Сензорът за отпечатъци е деактивиран."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Опитайте отново."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Няма регистрирани отпечатъци."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Това устройство няма сензор за отпечатъци."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> се подготвя."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Приложенията се стартират."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Зареждането завършва."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Искате ли да продължите с настройването?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Натиснахте бутона за включване/изключване – това обикновено изключва екрана.\n\nОпитайте да докоснете леко, докато настройвате отпечатъка си."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Изключване на екрана"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Напред с настройв."</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Докоснете за изключване на екрана"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Изключване на екрана"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Напред с потвърждаването на отпечатъка?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Натиснахте бутона за включване/изключване – това обикновено изключва екрана.\n\nОпитайте да докоснете леко, за да потвърдите отпечатъка си."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Изключване на екрана"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Докоснете, за да настроите"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Изберете, за да настроите"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Може да е необходимо да форматирате отново устройството. Докоснете, за да извадите."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"За прехвърляне на снимки и мултимедия"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"За съхраняване на снимки, видеоклипове, музика и др."</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Преглед на мултимедийните файлове"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Проблем с хранилището (<xliff:g id="NAME">%s</xliff:g>)"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> не работи"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Докоснете за коригиране"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Носителят (<xliff:g id="NAME">%s</xliff:g>) е повреден. Изберете, за да отстраните проблема."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Може да е необходимо да форматирате отново устройството. Докоснете, за да извадите."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g>: Не се поддържа"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Разпознато хранилище (<xliff:g id="NAME">%s</xliff:g>)"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> не работи"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Устройството не поддържа този носител (<xliff:g id="NAME">%s</xliff:g>). Докоснете, за да настроите в поддържан формат."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Докоснете, за да настроите."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Изберете, за да настроите <xliff:g id="NAME">%s</xliff:g> в поддържан формат."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Може да е необходимо да форматирате отново устройството"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>: Неочаквано премахване"</string>
@@ -1704,8 +1704,8 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Използване на пряк път"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Инвертиране на цветовете"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Коригиране на цветовете"</string>
- <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим за работа с една ръка"</string>
- <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Допълнително затъмняване"</string>
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Работа с една ръка"</string>
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Доп. затъмн."</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е включена."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е изключена."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"За да използвате <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, натиснете двата бутона за силата на звука и ги задръжте за 3 секунди"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Предпочитание за региона"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Въведете име на език"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Предложени"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Предложени"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Всички езици"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Всички региони"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Търсене"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Да се разреши ли на <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> достъп до всички регистрационни файлове за устройството?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Разрешаване на еднократен достъп"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Забраняване"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"В регистрационните файлове за устройството се записва какво се извършва на него. Приложенията могат да използват тези регистрационни файлове, за да откриват и отстраняват проблеми.\n\nНякои регистрационни файлове за устройството може да съдържат поверителна информация, затова разрешавайте достъп до всички тях само на приложения, на които имате доверие. \n\nАко не разрешите на това приложение достъп до всички регистрационни файлове за устройството, то пак може да осъществява достъп до собствените си регистрационни файлове. Производителят на устройството пак може да има достъп до някои регистрационни файлове или информация на устройството ви. Научете повече"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"В регистрационните файлове за устройството се записва какво се извършва на него. Приложенията могат да използват тези регистрационни файлове, за да откриват и отстраняват проблеми.\n\nНякои регистрационни файлове за устройството може да съдържат поверителна информация, затова разрешавайте достъп до всички тях само на приложения, на които имате доверие. \n\nАко не разрешите на това приложение достъп до всички регистрационни файлове за устройството, то пак може да осъществява достъп до собствените си регистрационни файлове. Производителят на устройството пак може да има достъп до някои регистрационни файлове или информация на устройството ви."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Да не се показва пак"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> иска да показва части от <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Редактиране"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Проверете активните приложения"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Няма достъп до камерата на телефона от вашия <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Няма достъп до камерата на таблета от вашия <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"До това съдържание не може да се осъществи достъп при поточно предаване. Вместо това опитайте от телефона си."</string>
<string name="system_locale_title" msgid="711882686834677268">"Стандартно за системата"</string>
</resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index c0e2a06..57b0a23 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"আঙ্গুলের ছাপ অপারেশন বাতিল করা হয়েছে৷"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ব্যবহারকারী আঙ্গুলের ছাপের অপারেশনটি বাতিল করেছেন।"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"অনেকবার প্রচেষ্টা করা হয়েছে৷ পরে আবার চেষ্টা করুন৷"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"বহুবার চেষ্টা করেছেন। আঙ্গুলের ছাপ নেওয়ার সেন্সর অক্ষম করা হয়েছে।"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"আবার চেষ্টা করুন৷"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"কোনও আঙ্গুলের ছাপ নথিভুক্ত করা হয়নি।"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"এই ডিভাইসে আঙ্গুলের ছাপ নেওয়ার সেন্সর নেই।"</string>
@@ -1072,7 +1073,7 @@
<string name="menu_shift_shortcut_label" msgid="5443936876111232346">"Shift+"</string>
<string name="menu_sym_shortcut_label" msgid="4037566049061218776">"Sym+"</string>
<string name="menu_function_shortcut_label" msgid="2367112760987662566">"Function+"</string>
- <string name="menu_space_shortcut_label" msgid="5949311515646872071">"স্পেস"</string>
+ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"space"</string>
<string name="menu_enter_shortcut_label" msgid="6709499510082897320">"enter"</string>
<string name="menu_delete_shortcut_label" msgid="4365787714477739080">"মুছুন"</string>
<string name="search_go" msgid="2141477624421347086">"সার্চ"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> প্রস্তুত করা হচ্ছে৷"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"অ্যাপ্লিকেশানগুলি শুরু করা হচ্ছে৷"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"চালু করা সম্পূর্ণ হচ্ছে৷"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"সেট-আপ করা চালিয়ে যাবেন?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"আপনি \'পাওয়ার\' বোতাম প্রেস করেছেন — এর ফলে সাধারণত স্ক্রিন বন্ধ হয়ে যায়।\n\nআঙ্গুলের ছাপ সেট-আপ করার সময় হালকাভাবে ট্যাপ করে দেখুন।"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"স্ক্রিন বন্ধ করুন"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"সেট-আপ চালিয়ে যান"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"স্ক্রিন বন্ধ করতে ট্যাপ করুন"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"স্ক্রিন বন্ধ করুন"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"আঙ্গুলের ছাপ যাচাই করা চালিয়ে যাবেন?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"আপনি \'পাওয়ার\' বোতাম প্রেস করেছেন — এর ফলে সাধারণত স্ক্রিন বন্ধ হয়ে যায়।\n\nআঙ্গুলের ছাপ যাচাই করতে হালকাভাবে ট্যাপ করে দেখুন।"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"স্ক্রিন বন্ধ করুন"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"সেট-আপ করতে ট্যাপ করুন"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"সেটআপ করতে বেছে নিন"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"আপনাকে ডিভাইসটি আবার ফর্ম্যাট করতে হতে পারে। বের করে নিতে ট্যাপ করুন।"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ফটো এবং মিডিয়া ট্রান্সফার"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ফটো, ভিডিও, মিউজিক ও আরও অনেক কিছু সেভ করার জন্য"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"মিডিয়া ফাইল ব্রাউজ করুন"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> নিয়ে সমস্যা আছে"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> কাজ করছে না"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"ঠিক করতে ট্যাপ করুন"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> ত্রুটিপূর্ণ। মেরামত করতে বেছে নিন।"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"আপনাকে ডিভাইসটি আবার ফর্ম্যাট করতে হতে পারে। বের করে নিতে ট্যাপ করুন।"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> অসমর্থিত"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> শনাক্ত করা হয়েছে"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> কাজ করছে না"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"এই ডিভাইসটি <xliff:g id="NAME">%s</xliff:g> সমর্থন করে না। কোনো সমর্থিত ফর্ম্যাটে সেট-আপ করতে আলতো চাপুন।"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"সেট-আপ করতে ট্যাপ করুন ।"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"<xliff:g id="NAME">%s</xliff:g> সঠিক ফর্ম্যাটে সেটআপ করতে বেছে নিন।"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"আপনাকে ডিভাইসটি আবার ফর্ম্যাট করতে হতে পারে"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> অপ্রত্যাশিতভাবে মুছে ফেলা হয়েছে"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"পছন্দের অঞ্চল"</string>
<string name="search_language_hint" msgid="7004225294308793583">"ভাষার নাম লিখুন"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"প্রস্তাবিত"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"সাজেস্ট করা অঞ্চল"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"সকল ভাষা"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"সমস্ত অঞ্চল"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"সার্চ"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> অ্যাপকে ডিভাইসের সব লগ অ্যাক্সেসের অনুমতি দিতে চান?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"এককালীন অ্যাক্সেসের অনুমতি দিন"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"অনুমতি দেবেন না"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"ডিভাইস লগে আপনার ডিভাইসে করা অ্যাক্টিভিটি রেকর্ড করা হয়। বিভিন্ন সমস্যা খুঁজে তা সমাধান করতে, অ্যাপ এইসব লগ ব্যবহার করতে পারে।\n\nকিছু লগে সংবেদনশীল তথ্য থাকতে পারে, তাই বিশ্বাস করেন শুধুমাত্র এমন অ্যাপকেই সব ডিভাইসের লগ অ্যাক্সেসের অনুমতি দিন। \n\nআপনি এই অ্যাপকে ডিভাইসের সব লগ অ্যাক্সেস করার অনুমতি না দিলেও, এটি নিজে লগ অ্যাক্সেস করতে পারবে। ডিভাইস প্রস্তুতকারকও আপনার ডিভাইসের কিছু লগ বা তথ্য হয়ত অ্যাক্সেস করতে পারবে। আরও জানুন"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"ডিভাইস লগে আপনার ডিভাইসে করা অ্যাক্টিভিটি রেকর্ড করা হয়। অ্যাপ সমস্যা খুঁজে তা সমাধান করতে এইসব লগ ব্যবহার করতে পারে।\n\nকিছু লগে সংবেদনশীল তথ্য থাকতে পারে, তাই বিশ্বাস করেন শুধুমাত্র এমন অ্যাপকেই সব ডিভাইসের লগ অ্যাক্সেসের অনুমতি দিন। \n\nআপনি এই অ্যাপকে ডিভাইসের সব লগ অ্যাক্সেস করার অনুমতি না দিলেও, এটি নিজের লগ অ্যাক্সেস করতে পারবে। ডিভাইস প্রস্তুতকারকও আপনার ডিভাইসের কিছু লগ বা তথ্য হয়ত অ্যাক্সেস করতে পারবে।"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"আর দেখতে চাই না"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> অ্যাপটি <xliff:g id="APP_2">%2$s</xliff:g> এর অংশ দেখাতে চায়"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"এডিট করুন"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"অ্যাক্টিভ অ্যাপ চেক করুন"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"আপনার <xliff:g id="DEVICE">%1$s</xliff:g> থেকে ফোনের ক্যামেরা অ্যাক্সেস করা যাচ্ছে না"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"আপনার <xliff:g id="DEVICE">%1$s</xliff:g> থেকে ট্যাবলেটের ক্যামেরা অ্যাক্সেস করা যাচ্ছে না"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"স্ট্রিমিংয়ের সময় এটি অ্যাক্সেস করা যাবে না। পরিবর্তে আপনার ফোনে ব্যবহার করে দেখুন।"</string>
<string name="system_locale_title" msgid="711882686834677268">"সিস্টেম ডিফল্ট"</string>
</resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 085c706..39b7e62 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -609,7 +609,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Radnja s otiskom prsta je otkazana."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Korisnik je otkazao radnju s otiskom prsta."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Previše pokušaja. Senzor za otisak prsta je onemogućen."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Pokušajte ponovo."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nije prijavljen nijedan otisak prsta."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ovaj uređaj nema senzor za otisak prsta."</string>
@@ -1250,10 +1251,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Pripremanje aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Pokretanje aplikacija."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Pokretanje pri kraju."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Nastaviti postavljanje?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Pritisnuli ste dugme za uključivanje. Tako se obično isključuje ekran.\n\nPokušajte ga lagano dodirnuti dok postavljate otisak prsta."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Isključi ekran"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Nastavi postavljanje"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Dodirnite da isključite ekran"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Isključi ekran"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Nastaviti s potvrđivanjem otiska prsta?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Pritisnuli ste dugme za uključivanje. Tako se obično isključuje ekran.\n\nPokušajte ga lagano dodirnuti da potvrdite otisak prsta."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Isključi ekran"</string>
@@ -1406,16 +1406,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Dodirnite za postavke"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Odaberite da postavite"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Možda ćete morati ponovo formatirati uređaj. Dodirnite da izbacite."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Za prebacivanje slika i medijskih fajlova"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Za pohranjivanje fotografija, videozapisa, muzike i još mnogo toga"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Pregledajte medijske fajlove"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problem s medijem <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ne funkcionira"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Dodirnite da popravite"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Uređaj <xliff:g id="NAME">%s</xliff:g> je oštećen. Odaberite za popravak."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Možda ćete morati ponovo formatirati uređaj. Dodirnite da izbacite."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Uređaj <xliff:g id="NAME">%s</xliff:g> nije podržan"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Otkriven je medij <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ne funkcionira"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Ovaj uređaj ne podržava uređaj <xliff:g id="NAME">%s</xliff:g>. Dodirnite da biste ga postavili u podržanom formatu."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Dodirnite da postavite ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Odaberite da postavite medij (<xliff:g id="NAME">%s</xliff:g>) u podržanom formatu."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Možda ćete morati ponovo formatirati uređaj"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Neočekivano uklonjen uređaj <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1429,7 +1429,7 @@
<string name="ext_media_browse_action" msgid="344865351947079139">"Istraži"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Prebacite izlaz"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> nedostaje"</string>
- <string name="ext_media_missing_message" msgid="4408988706227922909">"Ponovo ubacite uređaj"</string>
+ <string name="ext_media_missing_message" msgid="4408988706227922909">"Ponovo umetnite uređaj"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"Premješta se <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"Premještanje podataka"</string>
<string name="ext_media_move_success_title" msgid="4901763082647316767">"Prijenos sadržaja je završen"</string>
@@ -1928,6 +1928,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Izbor regije"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Upišite ime jezika"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Predloženo"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Predloženo"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Svi jezici"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Sve regije"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Pretraga"</string>
@@ -2050,7 +2051,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Dozvoliti aplikaciji <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> da pristupa svim zapisnicima uređaja?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Dozvoli jednokratan pristup"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Nemoj dozvoliti"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Zapisnici uređaja bilježe šta se dešava na uređaju. Aplikacije mogu koristiti te zapisnike da pronađu i riješe probleme.\n\nNeki zapisnici mogu sadržavati osjetljive podatke. Stoga pristup svim zapisnicima uređaja dozvolite samo aplikacijama kojima vjerujete. \n\nAko ne dozvolite ovoj aplikaciji da pristupa svim zapisnicima uređaja, ona i dalje može pristupati svojim zapisnicima. Proizvođač uređaja će možda i dalje biti u stanju pristupiti nekim zapisnicima ili podacima na uređaju. Saznajte više"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Zapisnici uređaja bilježe šta se dešava na uređaju. Aplikacije mogu koristiti te zapisnike da pronađu i isprave probleme.\n\nNeki zapisnici mogu sadržavati osjetljive podatke, zato pristup svim zapisnicima uređaja dozvolite samo aplikacijama kojima vjerujete. \n\nAko ne dozvolite ovoj aplikaciji da pristupa svim zapisnicima uređaja, ona i dalje može pristupati svojim zapisnicima. Proizvođač uređaja će možda i dalje biti u stanju pristupiti nekim zapisnicima ili podacima na uređaju."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ne prikazuj ponovo"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Aplikacija <xliff:g id="APP_0">%1$s</xliff:g> želi prikazati isječke aplikacije <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Uredi"</string>
@@ -2291,5 +2292,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Provjerite aktivne aplikacije"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nije moguće pristupiti kameri telefona s uređaja <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Nije moguće pristupiti kameri tableta s uređaja <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Ovom ne možete pristupiti tokom prijenosa. Umjesto toga pokušajte na telefonu."</string>
<string name="system_locale_title" msgid="711882686834677268">"Sistemski zadano"</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 1ce2192..daf1203 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"S\'ha cancel·lat l\'operació d\'empremta digital."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"L\'usuari ha cancel·lat l\'operació d\'empremta digital."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"S\'han produït massa intents. Torna-ho a provar més tard."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"S\'han fet massa intents. S\'ha desactivat el sensor d\'empremtes digitals."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Torna-ho a provar."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No s\'ha registrat cap empremta digital."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Aquest dispositiu no té sensor d\'empremtes digitals."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"S\'està preparant <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"S\'estan iniciant les aplicacions."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"S\'està finalitzant l\'actualització."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Vols continuar amb la configuració?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Has premut el botó d\'engegada, fet que sol apagar la pantalla.\n\nProva de tocar-lo lleugerament en configurar l\'empremta digital."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Apaga la pantalla"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Continua configurant"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toca per apagar la pantalla"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Apaga la pantalla"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Vols continuar verificant l\'empremta?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Has premut el botó d\'engegada, fet que sol apagar la pantalla.\n\nProva de tocar-lo lleugerament per verificar l\'empremta digital."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Apaga la pantalla"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Toca per configurar"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Selecciona per configurar"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"És possible que hagis de reformatar el dispositiu. Toca per expulsar."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Per transferir fotos i fitxers multimèdia"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Per desar fotos, vídeos, música i més"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Cerca fitxers multimèdia"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problema amb el suport (<xliff:g id="NAME">%s</xliff:g>)"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> no funciona"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Toca per solucionar el problema"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"La unitat següent està malmesa: <xliff:g id="NAME">%s</xliff:g>. Selecciona-la per solucionar-ho."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"És possible que hagis de reformatar el dispositiu. Toca per expulsar."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> no és compatible"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"S\'ha detectat <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> no funciona"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"El dispositiu no admet <xliff:g id="NAME">%s</xliff:g>. Toca per configurar-la en un format compatible."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Toca per configurar."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Selecciona per configurar <xliff:g id="NAME">%s</xliff:g> en un format compatible."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"És possible que hagis de reformatar el dispositiu"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"S\'ha extret <xliff:g id="NAME">%s</xliff:g> de manera inesperada"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Preferència de regió"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Escriu el nom de l\'idioma"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Suggerits"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Recomanades"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Tots els idiomes"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Totes les regions"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Cerca"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Vols permetre que <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> accedeixi a tots els registres del dispositiu?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Permet l\'accés únic"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"No permetis"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Els registres del dispositiu inclouen informació sobre tot allò que passa al teu dispositiu. Les aplicacions poden utilitzar aquests registres per detectar i corregir problemes.\n\nÉs possible que alguns registres continguin informació sensible; per això només has de donar-hi accés a les aplicacions de confiança. \n\nEncara que no permetis que aquesta aplicació accedeixi a tots els registres del dispositiu, podrà accedir als seus propis registres. És possible que el fabricant del dispositiu també tingui accés a alguns registres o a informació del teu dispositiu. Més informació"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Els registres del dispositiu inclouen informació sobre tot allò que passa al teu dispositiu. Les aplicacions poden utilitzar aquests registres per detectar i corregir problemes.\n\nÉs possible que alguns registres continguin informació sensible; per això només has de donar-hi accés a les aplicacions de confiança. \n\nEncara que no permetis que aquesta aplicació pugui accedir a tots els registres del dispositiu, podrà accedir als seus propis registres. És possible que el fabricant del dispositiu també tingui accés a alguns registres o a informació del teu dispositiu."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"No tornis a mostrar"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> vol mostrar porcions de l\'aplicació <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Edita"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Consulta les aplicacions actives"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"No es pot accedir a la càmera del telèfon des del teu <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"No es pot accedir a la càmera de la tauleta des del teu <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"No s\'hi pot accedir mentre s\'està reproduint en continu. Prova-ho al telèfon."</string>
<string name="system_locale_title" msgid="711882686834677268">"Valor predeterminat del sistema"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 1a37357..9e96104 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -610,7 +610,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operace otisku prstu byla zrušena."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Uživatel operaci s otiskem prstu zrušil."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Příliš mnoho pokusů. Zkuste to později."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Příliš mnoho pokusů. Snímač otisků prstů byl deaktivován."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Zkuste to znovu."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nejsou zaregistrovány žádné otisky prstů."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Toto zařízení nemá snímač otisků prstů."</string>
@@ -1251,10 +1252,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Příprava aplikace <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Spouštění aplikací."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Dokončování inicializace."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Pokračovat v nastavování?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Stiskli jste vypínač – tím se obvykle vypíná obrazovka.\n\nPři nastavování otisku prstu je třeba klepat lehce."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Vypnout obrazovku"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Pokračovat v nastavení"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Klepnutím vypnete obrazovku"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Vypnout obrazovku"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Pokračovat v ověřování otisku prstu?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Stiskli jste vypínač – tím se obvykle vypíná obrazovka.\n\nZkuste lehkým klepnutím ověřit svůj otisk prstu."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Vypnout obrazovku"</string>
@@ -1407,16 +1407,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Klepnutím médium nastavíte"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Vyberte, pokud chcete nastavit"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Zařízení možná bude nutné znovu naformátovat. Klepnutím ho vyjmete."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"K přenosu fotek a médií"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Pro ukládání fotek, videí, hudby a dalšího obsahu"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Procházet soubory na médiu"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problém s médiem <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"Médium <xliff:g id="NAME">%s</xliff:g> nefunguje"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Problém odstraníte klepnutím"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Úložiště <xliff:g id="NAME">%s</xliff:g> je poškozeno. Vyberte ho a zahajte opravu."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Zařízení možná bude nutné znovu naformátovat. Klepnutím ho vyjmete."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Úložiště <xliff:g id="NAME">%s</xliff:g> není podporováno"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Zjištěno zařízení <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"Médium <xliff:g id="NAME">%s</xliff:g> nefunguje"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Úložiště <xliff:g id="NAME">%s</xliff:g> není v tomto zařízení podporováno. Klepnutím zahájíte nastavení v podporovaném formátu."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Nastavíte klepnutím."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Vyberte, pokud chcete <xliff:g id="NAME">%s</xliff:g> nastavit v podporovaném formátu."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Zařízení možná bude nutné znovu naformátovat"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Úložiště <xliff:g id="NAME">%s</xliff:g> neočekávaně odpojeno"</string>
@@ -1430,7 +1430,7 @@
<string name="ext_media_browse_action" msgid="344865351947079139">"Otevřít"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Přepnout výstup"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> chybí"</string>
- <string name="ext_media_missing_message" msgid="4408988706227922909">"Znovu vložte zařízení"</string>
+ <string name="ext_media_missing_message" msgid="4408988706227922909">"Vložte zařízení znovu"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"Přesouvání aplikace <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"Probíhá přesun dat"</string>
<string name="ext_media_move_success_title" msgid="4901763082647316767">"Přenos obsahu je dokončen"</string>
@@ -1569,7 +1569,7 @@
<string name="action_bar_home_description_format" msgid="5087107531331621803">"%1$s – %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="4346835454749569826">"%1$s, %2$s – %3$s"</string>
<string name="storage_internal" msgid="8490227947584914460">"Interní sdílené úložiště"</string>
- <string name="storage_sd_card" msgid="3404740277075331881">"Karta SD"</string>
+ <string name="storage_sd_card" msgid="3404740277075331881">"SD karta"</string>
<string name="storage_sd_card_label" msgid="7526153141147470509">"SD karta <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="448030813201444573">"Jednotka USB"</string>
<string name="storage_usb_drive_label" msgid="6631740655876540521">"Jednotka USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
@@ -1929,6 +1929,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Preferovaná oblast"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Zadejte název jazyka"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Navrhované"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Navrženo"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Všechny jazyky"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Všechny oblasti"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Vyhledávání"</string>
@@ -2051,7 +2052,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Povolit aplikaci <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> přístup ke všem protokolům zařízení?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Povolit jednorázový přístup"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Nepovolovat"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Do protokolů zařízení se zaznamenává, co se na zařízení děje. Aplikace tyto protokoly mohou používat k vyhledání a odstranění problémů.\n\nNěkteré protokoly mohou zahrnovat citlivé údaje. Přístup k protokolům zařízení proto povolte pouze aplikacím, kterým důvěřujete. \n\nPokud této aplikaci nepovolíte přístup ke všem protokolům zařízení, bude mít stále přístup ke svým vlastním protokolům. Výrobce zařízení může mít stále přístup k některým protokolům nebo informacím na vašem zařízení. Další informace"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Do protokolů zařízení se zaznamenává, co se na zařízení děje. Aplikace tyto protokoly mohou používat k vyhledání a odstranění problémů.\n\nNěkteré protokoly mohou zahrnovat citlivé údaje. Přístup k protokolům zařízení proto povolte pouze aplikacím, kterým důvěřujete. \n\nPokud této aplikaci nepovolíte přístup ke všem protokolům zařízení, bude mít stále přístup ke svým vlastním protokolům. Výrobce zařízení může mít stále přístup k některým protokolům nebo informacím na vašem zařízení."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Příště nezobrazovat"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Aplikace <xliff:g id="APP_0">%1$s</xliff:g> chce zobrazovat ukázky z aplikace <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Upravit"</string>
@@ -2292,5 +2293,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Zkontrolujte aktivní aplikace"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Ze zařízení <xliff:g id="DEVICE">%1$s</xliff:g> nelze získat přístup k fotoaparátu telefonu"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Ze zařízení <xliff:g id="DEVICE">%1$s</xliff:g> nelze získat přístup k fotoaparátu tabletu"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Tento obsah při streamování nelze zobrazit. Zkuste to na telefonu."</string>
<string name="system_locale_title" msgid="711882686834677268">"Výchozí nastavení systému"</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index b6b33f6..8f70d36 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingeraftrykshandlingen blev annulleret."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingeraftrykshandlingen blev annulleret af brugeren."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Du har prøvet for mange gange. Prøv igen senere."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Du har brugt for mange forsøg. Fingeraftrykslæseren er deaktiveret."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Prøv igen."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Der er ikke registreret nogen fingeraftryk."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Denne enhed har ingen fingeraftrykslæser."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Forbereder <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Åbner dine apps."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Gennemfører start."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Vil du fortsætte konfigurationen?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Du har trykket på afbryderknappen, hvilket som regel slukker skærmen.\n\nPrøv at trykke let på knappen, mens du konfigurerer dit fingeraftryk."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Sluk skærm"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Fortsæt"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tryk for at slukke skærmen"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Sluk skærm"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Vil du bekræfte dit fingeraftryk?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Du har trykket på afbryderknappen, hvilket som regel slukker skærmen.\n\nPrøv at trykke let på knappen for at bekræfte dit fingeraftryk."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Sluk skærm"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Tryk for at konfigurere"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Vælg for at konfigurere"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Du skal muligvis formatere enheden igen. Tryk for at skubbe den ud."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Til overførsel af billeder og medier"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Til opbevaring af billeder, videoer, musik m.m."</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Gennemse mediefiler"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problem med <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> fungerer ikke"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Tryk for at løse problemet"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> er beskadiget. Vælg for at rette."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Du skal muligvis formatere enheden igen. Tryk for at skubbe den ud."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> understøttes ikke"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> er registreret"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> fungerer ikke"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Denne enhed understøtter ikke dette <xliff:g id="NAME">%s</xliff:g>. Tryk for at konfigurere det til et understøttet format."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Tryk for at konfigurere ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Vælg for at konfigurere <xliff:g id="NAME">%s</xliff:g> i et understøttet format."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Du skal muligvis formatere enheden igen"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> blev fjernet uventet"</string>
@@ -1568,7 +1568,7 @@
<string name="action_bar_home_subtitle_description_format" msgid="4346835454749569826">"%1$s, %2$s, %3$s"</string>
<string name="storage_internal" msgid="8490227947584914460">"Intern delt lagerplads"</string>
<string name="storage_sd_card" msgid="3404740277075331881">"SD-kort"</string>
- <string name="storage_sd_card_label" msgid="7526153141147470509">"SD-kort fra <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
+ <string name="storage_sd_card_label" msgid="7526153141147470509">"SD-kort (<xliff:g id="MANUFACTURER">%s</xliff:g>)"</string>
<string name="storage_usb_drive" msgid="448030813201444573">"USB-drev"</string>
<string name="storage_usb_drive_label" msgid="6631740655876540521">"USB-drev fra <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb" msgid="2391213347883616886">"USB-lager"</string>
@@ -1695,7 +1695,7 @@
<string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Tillad"</string>
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Afvis"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tryk på en funktion for at bruge den:"</string>
- <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Vælg, hvilke funktioner du vil bruge med knappen Hjælpefunktioner"</string>
+ <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Vælg, hvilke funktioner du vil bruge med knappen til hjælpefunktioner"</string>
<string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Vælg de funktioner, du vil bruge via lydstyrkeknapperne"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> er blevet deaktiveret"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Rediger genveje"</string>
@@ -1709,10 +1709,10 @@
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er aktiveret."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er deaktiveret."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Hold begge lydstyrkeknapper nede i tre sekunder for at bruge <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Vælg, hvilken funktion du vil bruge, når du trykker på knappen Hjælpefunktioner:"</string>
+ <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Vælg, hvilken funktion du vil bruge, når du trykker på knappen til hjælpefunktioner:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Vælg, hvilken funktion du vil bruge, når du laver bevægelsen for hjælpefunktioner (stryger opad fra bunden af skærmen med to fingre):"</string>
<string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Vælg, hvilken funktion du vil bruge, når du laver bevægelsen for hjælpefunktioner (stryger opad fra bunden af skærmen med tre fingre):"</string>
- <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Du kan skifte mellem funktioner ved at holde knappen Hjælpefunktioner nede."</string>
+ <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Du kan skifte mellem funktioner ved at holde knappen til hjælpefunktioner nede."</string>
<string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"Du kan skifte mellem funktioner ved at stryge opad med to fingre og holde dem nede."</string>
<string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"Du kan skifte mellem funktioner ved at stryge opad med tre fingre og holde dem nede."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Forstørrelse"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Områdeindstilling"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Angiv sprog"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Foreslået"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Forslag"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Alle sprog"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Alle områder"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Søg"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Vil du give <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> adgang til alle enhedslogs?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Tillad engangsadgang"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Tillad ikke"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Enhedslogs registrerer, hvad der sker på din enhed. Apps kan bruge disse logs til at finde og løse problemer.\n\nNogle logs kan indeholde følsomme oplysninger, så giv kun apps, du har tillid til, adgang til alle enhedslogs. \n\nSelvom du ikke giver denne app adgang til alle enhedslogs, kan den stadig tilgå sine egne logs. Producenten af din enhed kan muligvis fortsat tilgå visse logs eller oplysninger på din enhed. Få flere oplysninger"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Enhedslogs registrerer, hvad der sker på din enhed. Apps kan bruge disse logs til at finde og løse problemer.\n\nNogle logs kan indeholde følsomme oplysninger, så giv kun apps, du har tillid til, adgang til alle enhedslogs. \n\nSelvom du ikke giver denne app adgang til alle enhedslogs, kan den stadig tilgå sine egne logs. Producenten af din enhed kan muligvis fortsat tilgå visse logs eller oplysninger på din enhed."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Vis ikke igen"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> anmoder om tilladelse til at vise eksempler fra <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Rediger"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Tjek aktive apps"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Kameraet på din telefon kan ikke tilgås via din <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Kameraet på din tablet kan ikke tilgås via din <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Der er ikke adgang til dette indhold under streaming. Prøv på din telefon i stedet."</string>
<string name="system_locale_title" msgid="711882686834677268">"Systemstandard"</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 1e4bbfc..64ef8e1 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerabdruckvorgang abgebrochen"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Vorgang der Fingerabdruckauthentifizierung vom Nutzer abgebrochen."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Zu viele Versuche, bitte später noch einmal versuchen"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Zu viele Versuche. Der Fingerabdrucksensor wurde deaktiviert."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Bitte versuche es noch einmal."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Keine Fingerabdrücke erfasst."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Dieses Gerät hat keinen Fingerabdrucksensor."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> wird vorbereitet"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Apps werden gestartet..."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Start wird abgeschlossen..."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Einrichtung fortsetzen?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Du hast die Ein-/Aus-Taste gedrückt — damit wird der Bildschirm ausgeschaltet.\n\nTippe die Taste leicht an, um deinen Fingerabdruck einzurichten."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Ausschalten"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Weiter einrichten"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tippen, um Display auszuschalten"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Display ausschalten"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Mit der Fingerabdruckprüfung fortfahren?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Du hast die Ein-/Aus-Taste gedrückt — damit wird der Bildschirm ausgeschaltet.\n\nTippe die Taste leicht an, um mit deinem Fingerabdruck deine Identität zu bestätigen."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Ausschalten"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Zum Einrichten tippen"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Zum Einrichten auswählen"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Eventuell musst du das Gerät neu formatieren. Zum Auswerfen tippen."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Zum Übertragen von Fotos und Medien"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Zum Speichern von Fotos, Videos, Musik und mehr"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"In Mediendateien stöbern"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problem mit <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> funktioniert nicht"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Tippen, um das Problem zu beheben"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> ist beschädigt. Zur Problembehebung auswählen."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Eventuell musst du das Gerät neu formatieren. Zum Auswerfen tippen."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> nicht unterstützt"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"„<xliff:g id="NAME">%s</xliff:g>“ erkannt"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> funktioniert nicht"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"<xliff:g id="NAME">%s</xliff:g> wird von diesem Gerät nicht unterstützt. Zum Einrichten in einem unterstützten Format tippen."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Zum Einrichten tippen"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Wähle <xliff:g id="NAME">%s</xliff:g> aus, um das Medium in einem unterstützten Format einzurichten."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Eventuell musst du das Gerät neu formatieren"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> wurde unerwartet entfernt"</string>
@@ -1858,7 +1858,7 @@
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Von deinem Administrator gelöscht"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
<string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Der Energiesparmodus aktiviert das dunkle Design. Hintergrundaktivitäten, einige Funktionen und optische Effekte und manche Netzwerkverbindungen werden eingeschränkt oder deaktiviert."</string>
- <string name="battery_saver_description" msgid="8518809702138617167">"Der Energiesparmodus aktiviert das dunkle Design. Hintergrundaktivitäten, einige Funktionen und optische Effekte und manche Netzwerkverbindungen werden eingeschränkt oder deaktiviert."</string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Der Energiesparmodus aktiviert das dunkle Design. Hintergrundaktivitäten, einige Funktionen und optische Effekte sowie manche Netzwerkverbindungen werden eingeschränkt oder deaktiviert."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Der Datensparmodus verhindert, dass manche Apps im Hintergrund Daten senden oder empfangen, sodass weniger Daten verbraucht werden. Auch werden die Datenzugriffe der gerade aktiven App eingeschränkt, was z. B. dazu führen kann, dass Bilder erst angetippt werden müssen, bevor sie sichtbar werden."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Datensparmodus aktivieren?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Aktivieren"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Region auswählen"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Sprache eingeben"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Vorschläge"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Vorschläge"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Alle Sprachen"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Alle Regionen"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Suche"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> den Zugriff auf alle Geräteprotokolle erlauben?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Einmaligen Zugriff zulassen"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Nicht zulassen"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"In Geräteprotokollen wird aufgezeichnet, welche Aktionen auf deinem Gerät ausgeführt werden. Apps können sie verwenden, um Probleme zu finden und zu beheben.\n\nEinige Protokolle enthalten unter Umständen vertrauliche Informationen, daher solltest du nur vertrauenswürdigen Apps den Zugriff auf alle Geräteprotokolle erlauben. \n\nWenn du dieser App keinen Zugriff auf alle Geräteprotokolle gewährst, kann sie trotzdem auf ihre eigenen Protokolle zugreifen. Dein Gerätehersteller hat möglicherweise auch Zugriff auf einige Protokolle oder Informationen auf deinem Gerät. Weitere Informationen"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"In Geräteprotokollen wird aufgezeichnet, welche Aktionen auf deinem Gerät ausgeführt werden. Apps können diese Protokolle verwenden, um Probleme zu finden und zu beheben.\n\nEinige Protokolle enthalten unter Umständen vertrauliche Informationen, daher solltest du nur vertrauenswürdigen Apps den Zugriff auf alle Geräteprotokolle erlauben. \n\nWenn du dieser App keinen Zugriff auf alle Geräteprotokolle gewährst, kann sie trotzdem auf ihre eigenen Protokolle zugreifen. Dein Gerätehersteller hat möglicherweise auch Zugriff auf einige Protokolle oder Informationen auf deinem Gerät."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Nicht mehr anzeigen"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> möchte Teile von <xliff:g id="APP_2">%2$s</xliff:g> anzeigen"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Bearbeiten"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Aktive Apps prüfen"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Zugriff auf die Kamera des Smartphones über dein Gerät (<xliff:g id="DEVICE">%1$s</xliff:g>) nicht möglich"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Zugriff auf die Kamera des Tablets über dein Gerät (<xliff:g id="DEVICE">%1$s</xliff:g>) nicht möglich"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Während des Streamings ist kein Zugriff möglich. Versuch es stattdessen auf deinem Smartphone."</string>
<string name="system_locale_title" msgid="711882686834677268">"Standardeinstellung des Systems"</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index fc5396b..cca5c9f 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Η λειτουργία δακτυλικού αποτυπώματος ακυρώθηκε."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Η λειτουργία δακτυλικού αποτυπώματος ακυρώθηκε από τον χρήστη."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Πάρα πολλές προσπάθειες. Δοκιμάστε ξανά αργότερα."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Πάρα πολλές προσπάθειες. Ο αισθητήρας δακτυλικών αποτυπωμάτων απενεργοποιήθηκε."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Δοκιμάστε ξανά."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Δεν έχουν καταχωριστεί δακτυλικά αποτυπώματα."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Αυτή η συσκευή δεν διαθέτει αισθητήρα δακτυλικού αποτυπώματος."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Προετοιμασία <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Έναρξη εφαρμογών."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Ολοκλήρωση εκκίνησης."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Συνέχιση ρύθμισης;"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Πατήσατε το κουμπί λειτουργίας. Αυτό συνήθως απενεργοποιεί την οθόνη.\n\nΔοκιμάστε να πατήσετε απαλά κατά τη ρύθμιση του δακτυλικού σας αποτυπώματος."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Απενεργοπ. οθόνης"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Συνέχιση ρύθμισης"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Πατήστε για απενεργοποίηση οθόνης"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Απενεργοπ. οθόνης"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Συνέχιση επαλήθευσης δακτ. αποτυπώματος;"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Πατήσατε το κουμπί λειτουργίας. Αυτό συνήθως απενεργοποιεί την οθόνη.\n\nΔοκιμάστε να πατήστε απαλά για να επαληθεύσετε το δακτυλικό σας αποτύπωμα."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Απενεργοπ. οθόνης"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Πατήστε για ρύθμιση"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Επιλέξτε για ρύθμιση"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Μπορεί να χρειαστεί να διαμορφώσετε ξανά τη συσκευή. Πατήστε για κατάργηση."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Για μεταφορά φωτ./πολυμέσων"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Για αποθήκευση φωτογραφιών, βίντεο, μουσικής και άλλου περιεχομένου"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Περιήγηση στα αρχεία μέσων"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Πρόβλημα με <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"Η συσκευή <xliff:g id="NAME">%s</xliff:g> δεν λειτουργεί."</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Πατήστε για επιδιόρθωση"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Το μέσο <xliff:g id="NAME">%s</xliff:g> έχει καταστραφεί. Επιλέξτε να γίνει επιδιόρθωση."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Μπορεί να χρειαστεί να διαμορφώσετε ξανά τη συσκευή. Πατήστε για κατάργηση."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Η κάρτα <xliff:g id="NAME">%s</xliff:g> δεν υποστηρίζεται"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Ανιχνεύθηκε <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"Η συσκευή <xliff:g id="NAME">%s</xliff:g> δεν λειτουργεί."</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Αυτή η συσκευή δεν υποστηρίζει αυτό το μέσο <xliff:g id="NAME">%s</xliff:g>. Πατήστε για ρύθμιση σε μια υποστηριζόμενη μορφή."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Πατήστε για ρύθμιση ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Επιλέξτε για να ρυθμίσετε το μέσο <xliff:g id="NAME">%s</xliff:g> σε μια υποστηριζόμενη μορφή."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Μπορεί να χρειαστεί να διαμορφώσετε ξανά τη συσκευή."</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Μη αναμενόμενη αφαίρεση <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Προτίμηση περιοχής"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Εισαγ. όνομα γλώσσας"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Προτεινόμενες"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Προτεινόμενα"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Όλες οι γλώσσες"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Όλες οι περιοχές"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Αναζήτηση"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Να επιτρέπεται στο <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> η πρόσβαση σε όλα τα αρχεία καταγραφής συσκευής;"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Να επιτρέπεται η πρόσβαση για μία φορά"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Να μην επιτραπεί"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Τα αρχεία καταγραφής συσκευής καταγράφουν ό,τι συμβαίνει στη συσκευή σας. Οι εφαρμογές μπορούν να χρησιμοποιούν αυτά τα αρχεία καταγραφής για να εντοπίζουν και να διορθώνουν ζητήματα.\n\nΟρισμένα αρχεία καταγραφής ενδέχεται να περιέχουν ευαίσθητες πληροφορίες. Ως εκ τούτου, επιτρέψτε την πρόσβαση σε όλα τα αρχεία καταγραφής συσκευής μόνο στις εφαρμογές που εμπιστεύεστε. \n\nΕάν δεν επιτρέψετε σε αυτήν την εφαρμογή την πρόσβαση σε όλα τα αρχεία καταγραφής συσκευής, η εφαρμογή εξακολουθεί να έχει πρόσβαση στα δικά της αρχεία καταγραφής. Ο κατασκευαστής της συσκευής σας ενδέχεται να εξακολουθεί να έχει πρόσβαση σε ορισμένα αρχεία καταγραφής ή ορισμένες πληροφορίες στη συσκευή σας. Μάθετε περισσότερα"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Τα αρχεία καταγραφής συσκευής καταγράφουν ό,τι συμβαίνει στη συσκευή σας. Οι εφαρμογές μπορούν να χρησιμοποιούν αυτά τα αρχεία καταγραφής για να εντοπίζουν και να διορθώνουν ζητήματα.\n\nΟρισμένα αρχεία καταγραφής ενδέχεται να περιέχουν ευαίσθητες πληροφορίες. Ως εκ τούτου, επιτρέψτε την πρόσβαση σε όλα τα αρχεία καταγραφής συσκευής μόνο στις εφαρμογές που εμπιστεύεστε. \n\nΕάν δεν επιτρέψετε σε αυτήν την εφαρμογή την πρόσβαση σε όλα τα αρχεία καταγραφής συσκευής, η εφαρμογή εξακολουθεί να έχει πρόσβαση στα δικά της αρχεία καταγραφής. Ο κατασκευαστής της συσκευής σας ενδέχεται να εξακολουθεί να έχει πρόσβαση σε ορισμένα αρχεία καταγραφής ή ορισμένες πληροφορίες στη συσκευή σας."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Να μην εμφανισ. ξανά"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Η εφαρμογή <xliff:g id="APP_0">%1$s</xliff:g> θέλει να εμφανίζει τμήματα της εφαρμογής <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Επεξεργασία"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Έλεγχος ενεργών εφαρμογών"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Δεν είναι δυνατή η πρόσβαση στην κάμερα του τηλεφώνου από τη συσκευή <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Δεν είναι δυνατή η πρόσβαση στην κάμερα του tablet από τη συσκευή <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Δεν είναι δυνατή η πρόσβαση σε αυτό το στοιχείο κατά τη ροή. Δοκιμάστε στο τηλέφωνό σας."</string>
<string name="system_locale_title" msgid="711882686834677268">"Προεπιλογή συστήματος"</string>
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 8863c34..d0351a7 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -608,7 +608,7 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation cancelled."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation cancelled by user."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Too many attempts. Try again later."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Too many attempts. Fingerprint sensor disabled."</string>
+ <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string>
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Try again."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No fingerprints enrolled."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string>
@@ -1249,10 +1249,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Continue setup?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly while setting up your fingerprint."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Turn off screen"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Continue setup"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tap to turn off screen"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Turn off screen"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continue verifying your fingerprint?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly to verify your fingerprint."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Turn off screen"</string>
@@ -1405,16 +1404,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Tap to set up"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Select to set up"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"You may need to reformat the device. Tap to eject."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"For transferring photos and media"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"For storing photos, videos, music and more"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Browse media files"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Issue with <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> isn’t working"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Tap to fix"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> is corrupt. Select to fix."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"You may need to reformat the device. Tap to eject."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Unsupported <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> detected"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> isn’t working"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"This device doesn’t support this <xliff:g id="NAME">%s</xliff:g>. Tap to set up in a supported format."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Tap to set up."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Select to set up <xliff:g id="NAME">%s</xliff:g> in a supported format."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"You may need to reformat the device"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> unexpectedly removed"</string>
@@ -1927,6 +1926,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Region preference"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Type language name"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Suggested"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Suggested"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"All languages"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"All regions"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Search"</string>
@@ -2049,7 +2049,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Allow <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> to access all device logs?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Allow one-time access"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Don’t allow"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps that you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device. Learn more"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps that you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Don’t show again"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> wants to show <xliff:g id="APP_2">%2$s</xliff:g> slices"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Edit"</string>
@@ -2290,5 +2290,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Check active apps"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Can’t access the phone’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Can’t access the tablet’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"This can’t be accessed while streaming. Try on your phone instead."</string>
<string name="system_locale_title" msgid="711882686834677268">"System default"</string>
</resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 1204d01..cb4f71e 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -608,7 +608,7 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation cancelled."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation cancelled by user."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Too many attempts. Try again later."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Too many attempts. Fingerprint sensor disabled."</string>
+ <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string>
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Try again."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No fingerprints enrolled."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string>
@@ -1249,10 +1249,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Continue setup?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly while setting up your fingerprint."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Turn off screen"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Continue setup"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tap to turn off screen"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Turn off screen"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continue verifying your fingerprint?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly to verify your fingerprint."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Turn off screen"</string>
@@ -1405,16 +1404,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Tap to set up"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Select to set up"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"You may need to reformat the device. Tap to eject."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"For transferring photos and media"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"For storing photos, videos, music and more"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Browse media files"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Issue with <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> isn’t working"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Tap to fix"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> is corrupt. Select to fix."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"You may need to reformat the device. Tap to eject."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Unsupported <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> detected"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> isn’t working"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"This device doesn’t support this <xliff:g id="NAME">%s</xliff:g>. Tap to set up in a supported format."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Tap to set up."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Select to set up <xliff:g id="NAME">%s</xliff:g> in a supported format."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"You may need to reformat the device"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> unexpectedly removed"</string>
@@ -1927,6 +1926,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Region preference"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Type language name"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Suggested"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Suggested"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"All languages"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"All regions"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Search"</string>
@@ -2049,7 +2049,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Allow <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> to access all device logs?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Allow one-time access"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Don’t allow"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps that you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device. Learn more"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps that you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Don’t show again"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> wants to show <xliff:g id="APP_2">%2$s</xliff:g> slices"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Edit"</string>
@@ -2290,5 +2290,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Check active apps"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Can’t access the phone’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Can’t access the tablet’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"This can’t be accessed while streaming. Try on your phone instead."</string>
<string name="system_locale_title" msgid="711882686834677268">"System default"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 753be10..8c31f7b 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -608,7 +608,7 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation cancelled."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation cancelled by user."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Too many attempts. Try again later."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Too many attempts. Fingerprint sensor disabled."</string>
+ <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string>
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Try again."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No fingerprints enrolled."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string>
@@ -1249,10 +1249,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Continue setup?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly while setting up your fingerprint."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Turn off screen"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Continue setup"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tap to turn off screen"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Turn off screen"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continue verifying your fingerprint?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly to verify your fingerprint."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Turn off screen"</string>
@@ -1405,16 +1404,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Tap to set up"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Select to set up"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"You may need to reformat the device. Tap to eject."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"For transferring photos and media"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"For storing photos, videos, music and more"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Browse media files"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Issue with <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> isn’t working"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Tap to fix"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> is corrupt. Select to fix."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"You may need to reformat the device. Tap to eject."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Unsupported <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> detected"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> isn’t working"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"This device doesn’t support this <xliff:g id="NAME">%s</xliff:g>. Tap to set up in a supported format."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Tap to set up."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Select to set up <xliff:g id="NAME">%s</xliff:g> in a supported format."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"You may need to reformat the device"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> unexpectedly removed"</string>
@@ -1927,6 +1926,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Region preference"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Type language name"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Suggested"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Suggested"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"All languages"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"All regions"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Search"</string>
@@ -2049,7 +2049,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Allow <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> to access all device logs?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Allow one-time access"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Don’t allow"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps that you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device. Learn more"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps that you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Don’t show again"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> wants to show <xliff:g id="APP_2">%2$s</xliff:g> slices"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Edit"</string>
@@ -2290,5 +2290,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Check active apps"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Can’t access the phone’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Can’t access the tablet’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"This can’t be accessed while streaming. Try on your phone instead."</string>
<string name="system_locale_title" msgid="711882686834677268">"System default"</string>
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8db1151..cdce2f09e 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -608,7 +608,7 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation cancelled."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation cancelled by user."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Too many attempts. Try again later."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Too many attempts. Fingerprint sensor disabled."</string>
+ <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string>
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Try again."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No fingerprints enrolled."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string>
@@ -1249,10 +1249,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Continue setup?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly while setting up your fingerprint."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Turn off screen"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Continue setup"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tap to turn off screen"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Turn off screen"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continue verifying your fingerprint?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly to verify your fingerprint."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Turn off screen"</string>
@@ -1405,16 +1404,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Tap to set up"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Select to set up"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"You may need to reformat the device. Tap to eject."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"For transferring photos and media"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"For storing photos, videos, music and more"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Browse media files"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Issue with <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> isn’t working"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Tap to fix"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> is corrupt. Select to fix."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"You may need to reformat the device. Tap to eject."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Unsupported <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> detected"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> isn’t working"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"This device doesn’t support this <xliff:g id="NAME">%s</xliff:g>. Tap to set up in a supported format."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Tap to set up."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Select to set up <xliff:g id="NAME">%s</xliff:g> in a supported format."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"You may need to reformat the device"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> unexpectedly removed"</string>
@@ -1927,6 +1926,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Region preference"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Type language name"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Suggested"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Suggested"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"All languages"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"All regions"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Search"</string>
@@ -2049,7 +2049,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Allow <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> to access all device logs?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Allow one-time access"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Don’t allow"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps that you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device. Learn more"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps that you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Don’t show again"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> wants to show <xliff:g id="APP_2">%2$s</xliff:g> slices"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Edit"</string>
@@ -2290,5 +2290,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Check active apps"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Can’t access the phone’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Can’t access the tablet’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"This can’t be accessed while streaming. Try on your phone instead."</string>
<string name="system_locale_title" msgid="711882686834677268">"System default"</string>
</resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 4f643c3..c29ad1a 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -608,7 +608,7 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation canceled."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation canceled by user."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Too many attempts. Try again later."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Too many attempts. Fingerprint sensor disabled."</string>
+ <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string>
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Try again."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No fingerprints enrolled."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string>
@@ -1249,10 +1249,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Continue setup?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"You pressed the power button — this usually turns off the screen.\n\nTry tapping lightly while setting up your fingerprint."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Turn off screen"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Continue setup"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tap to turn off screen"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Turn off screen"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continue verifying your fingerprint?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"You pressed the power button — this usually turns off the screen.\n\nTry tapping lightly to verify your fingerprint."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Turn off screen"</string>
@@ -1405,16 +1404,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Tap to set up"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Select to set up"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"You may need to reformat the device. Tap to eject."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"For transferring photos and media"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"For storing photos, videos, music and more"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Browse media files"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Issue with <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> isn’t working"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Tap to fix"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> is corrupt. Select to fix."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"You may need to reformat the device. Tap to eject."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Unsupported <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> detected"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> isn’t working"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"This device doesn’t support this <xliff:g id="NAME">%s</xliff:g>. Tap to set up in a supported format."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Tap to set up ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Select to set up <xliff:g id="NAME">%s</xliff:g> in a supported format."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"You may need to reformat the device"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> unexpectedly removed"</string>
@@ -1927,6 +1926,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Region preference"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Type language name"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Suggested"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Suggested"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"All languages"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"All regions"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Search"</string>
@@ -2049,7 +2049,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Allow <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> to access all device logs?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Allow one-time access"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Don’t allow"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device. Learn more"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Don’t show again"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> wants to show <xliff:g id="APP_2">%2$s</xliff:g> slices"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Edit"</string>
@@ -2290,5 +2290,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Check active apps"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Can’t access the phone’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Can’t access the tablet’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"This can’t be accessed while streaming. Try on your phone instead."</string>
<string name="system_locale_title" msgid="711882686834677268">"System default"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 2fdb821..9e968fc 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Se canceló la operación de huella dactilar."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"El usuario canceló la operación de huella dactilar."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Demasiados intentos. Vuelve a intentarlo más tarde."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Realizaste demasiados intentos. Se inhabilitó el sensor de huellas dactilares."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Vuelve a intentarlo."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No se registraron huellas digitales."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo no tiene sensor de huellas dactilares."</string>
@@ -921,7 +922,7 @@
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Presionar Menú para desbloquear."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Dibujar el patrón de desbloqueo"</string>
<string name="lockscreen_emergency_call" msgid="7500692654885445299">"Emergencia"</string>
- <string name="lockscreen_return_to_call" msgid="3156883574692006382">"Regresar a llamada"</string>
+ <string name="lockscreen_return_to_call" msgid="3156883574692006382">"Regresar a la llamada"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correcto"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Vuelve a intentarlo."</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Volver a intentarlo"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando aplicaciones"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Finalizando el inicio"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"¿Continuar con la configuración?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Presionaste el botón de encendido. Por lo general, esta acción apaga la pantalla.\n\nPresiona suavemente mientras configuras tu huella dactilar."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Apagar pantalla"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Continuar config."</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Presiona para apagar la pantalla"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Apagar pantalla"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"¿Verificar huella dactilar?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Presionaste el botón de encendido. Por lo general, esta acción apaga la pantalla.\n\nPresiona suavemente para verificar tu huella dactilar."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Apagar pantalla"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Presiona para configurar"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Selecciona para configurar"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Es posible que debas reformatear el dispositivo. Presiona para expulsar."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Para transferir fotos y contenido multimedia"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Para almacenar fotos, videos, música y mucho más"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Explora archivos multimedia"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problema con <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g>: no funciona"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Presiona para solucionar el problema"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> se dañó. Selecciona el medio para solucionar el problema."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Es posible que debas reformatear el dispositivo. Presiona para expulsar."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> no es compatible"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Se detectó <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g>: no funciona"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"El dispositivo no es compatible con <xliff:g id="NAME">%s</xliff:g>. Presiona la pantalla para configurarlo en un formato compatible."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Presiona para configurar."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Selecciona para configurar <xliff:g id="NAME">%s</xliff:g> en un formato compatible."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Es posible que debas reformatear el dispositivo"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Se extrajo <xliff:g id="NAME">%s</xliff:g> de forma inesperada."</string>
@@ -1427,7 +1427,7 @@
<string name="ext_media_unmount_action" msgid="966992232088442745">"Expulsar"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"Explorar"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Cambiar salida"</string>
- <string name="ext_media_missing_title" msgid="3209472091220515046">"No se encuentra dispositivo <xliff:g id="NAME">%s</xliff:g>."</string>
+ <string name="ext_media_missing_title" msgid="3209472091220515046">"Falta <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_missing_message" msgid="4408988706227922909">"Vuelve a insertar dispositivo"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"Transfiriendo la aplicación <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"Transfiriendo los datos"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Preferencia de región"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Nombre del idioma"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Sugeridos"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Sugerencias"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Todos los idiomas"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Todas las regiones"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Búsqueda"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"¿Quieres permitir que <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> acceda a todos los registros del dispositivo?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Permitir acceso por única vez"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"No permitir"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Los registros del dispositivo permiten documentar lo que sucede en él. Las apps pueden usar estos registros para encontrar y solucionar problemas.\n\nEs posible que algunos registros del dispositivo contengan información sensible, por lo que solo debes permitir que accedan a todos los registros las apps que sean de tu confianza. \n\n Ten en cuenta que la app puede acceder a sus propios registros aun si no permites que acceda a todos los registros del dispositivo. También es posible que el fabricante del dispositivo acceda a algunos registros o información en tu dispositivo. Más información"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Los registros del dispositivo permiten documentar lo que sucede en él. Las apps pueden usar estos registros para encontrar y solucionar problemas.\n\nEs posible que algunos registros del dispositivo contengan información sensible, por lo que solo debes permitir que accedan a todos ellos las apps que sean de tu confianza. \n\nSi no permites que esta app acceda a todos los registros del dispositivo, aún puede acceder a sus propios registros. Además, es posible que el fabricante del dispositivo acceda a algunos registros o información en tu dispositivo."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"No volver a mostrar"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> quiere mostrar fragmentos de <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Editar"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Consulta las apps activas"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"No se puede acceder a la cámara del dispositivo desde tu <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"No se puede acceder a la cámara de la tablet desde tu <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"No se puede acceder a este contenido durante una transmisión. Inténtalo en tu teléfono."</string>
<string name="system_locale_title" msgid="711882686834677268">"Predeterminado del sistema"</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 0b24e30..6be15fc 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Se ha cancelado la operación de huella digital."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"El usuario ha cancelado la operación de huella digital."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Demasiados intentos. Vuelve a intentarlo más tarde."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Demasiados intentos. Se ha inhabilitado el sensor de huellas digitales."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Vuelve a intentarlo."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No se ha registrado ninguna huella digital."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo no tiene sensor de huellas digitales."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando aplicaciones"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Finalizando inicio..."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"¿Quieres seguir con la configuración?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Has pulsado el botón de encendido, lo que suele apagar la pantalla.\n\nPrueba a apoyar el dedo ligeramente para verificar tu huella digital."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Apagar pantalla"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Seguir configurando"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toca para apagar la pantalla"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Apagar pantalla"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"¿Seguir verificando tu huella digital?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Has pulsado el botón de encendido, lo que suele apagar la pantalla.\n\nPrueba a apoyar el dedo ligeramente para verificar tu huella digital."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Apagar pantalla"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Toca para configurar"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Selecciona para configurar"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Es posible que tengas que reformatear el dispositivo. Toca para expulsar."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Para transferir fotos y multimedia"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Para almacenar fotos, vídeos, música, y más"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Consulta los archivos del dispositivo"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problema con <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> no funciona"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Toca para solucionar el problema"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> está dañada. Selecciónala para arreglarla."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Es posible que tengas que reformatear el dispositivo. Toca para expulsar."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Medio externo (<xliff:g id="NAME">%s</xliff:g>) no admitido"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Detectado: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> no funciona"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"El dispositivo no admite este medio externo (<xliff:g id="NAME">%s</xliff:g>). Toca para configurarlo con un formato admitido."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Toca para configurar."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Selecciona para configurar <xliff:g id="NAME">%s</xliff:g> en un formato compatible."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Es posible que tengas que reformatear el dispositivo"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Extracción inesperada de <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Preferencia de región"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Nombre de idioma"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Sugeridos"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Sugerencias"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Todos los idiomas"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Todas las regiones"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Buscar"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"¿Permitir que <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> acceda a todos los registros del dispositivo?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Permitir el acceso una vez"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"No permitir"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Los registros del dispositivo documentan lo que sucede en tu dispositivo. Las aplicaciones pueden usar estos registros para encontrar y solucionar problemas.\n\nComo algunos registros pueden contener información sensible, es mejor que solo permitas que accedan a ellos las aplicaciones en las que confíes. \n\nAunque no permitas que esta aplicación acceda a todos los registros del dispositivo, podrá seguir accediendo a sus propios registros. Es posible que el fabricante del dispositivo pueda acceder a algunos registros o información de tu dispositivo. Más información"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Los registros del dispositivo documentan lo que sucede en tu dispositivo. Las aplicaciones pueden usar estos registros para encontrar y solucionar problemas.\n\nComo algunos registros pueden contener información sensible, es mejor que solo permitas que accedan a ellos las aplicaciones en las que confíes. \n\nAunque no permitas que esta aplicación acceda a todos los registros del dispositivo, aún podrá acceder a sus propios registros. El fabricante de tu dispositivo aún puede acceder a algunos registros o información de tu dispositivo."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"No volver a mostrar"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> quiere mostrar fragmentos de <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Editar"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Consultar aplicaciones activas"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"No se puede acceder a la cámara del teléfono desde tu <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"No se puede acceder a la cámara del tablet desde tu <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"No se puede acceder a este contenido durante una emisión. Prueba en tu teléfono."</string>
<string name="system_locale_title" msgid="711882686834677268">"Predeterminado del sistema"</string>
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 7a706e5..dcddeab 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Sõrmejälje toiming tühistati."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Kasutaja tühistas sõrmejälje kasutamise."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Liiga palju katseid. Proovige hiljem uuesti."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Liiga palju katseid. Sõrmejäljeandur on keelatud."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Proovige uuesti."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Ühtegi sõrmejälge pole registreeritud."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Selles seadmes pole sõrmejäljeandurit."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Rakenduse <xliff:g id="APPNAME">%1$s</xliff:g> ettevalmistamine."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Rakenduste käivitamine."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Käivitamise lõpuleviimine."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Kas jätkata seadistamist?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Vajutasite toitenuppu – tavaliselt lülitab see ekraani välja.\n\nPuudutage õrnalt ja seadistage oma sõrmejälg."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Lülita ekraan välja"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Jätka seadistamist"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Puudutage ekraani väljalülitamiseks"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Lülita ekraan välja"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Kas jätkata sõrmejälje kinnitamist?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Vajutasite toitenuppu – tavaliselt lülitab see ekraani välja.\n\nPuudutage õrnalt, et oma sõrmejälg kinnitada."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Lülita ekraan välja"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Puudutage seadistamiseks"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Valige seadistamiseks"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Peate võib-olla seadme uuesti vormindama. Puudutage väljutamiseks."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Fotode ja meedia ülekandmiseks"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Salvestage fotosid, videoid, muusikat ja muud"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Sirvige meediafaile"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Probleem üksusega <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ei tööta"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Puudutage parandamiseks"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Kaart <xliff:g id="NAME">%s</xliff:g> on rikutud. Valige parandamiseks."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Peate võib-olla seadme uuesti vormindama. Puudutage väljutamiseks."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Toetamata <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Tuvastati meedium <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ei tööta"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"See seade ei toeta üksust <xliff:g id="NAME">%s</xliff:g>. Puudutage toetatud vormingus seadistamiseks."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Puudutage seadistamiseks."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Valige üksuse <xliff:g id="NAME">%s</xliff:g> seadistamiseks toetatud vormingus."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Peate võib-olla seadme uuesti vormindama"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Üksus <xliff:g id="NAME">%s</xliff:g> eemaldati ootamatult"</string>
@@ -1424,8 +1424,8 @@
<string name="ext_media_unmounting_notification_title" msgid="4147986383917892162">"Üksuse <xliff:g id="NAME">%s</xliff:g> väljutamine …"</string>
<string name="ext_media_unmounting_notification_message" msgid="5717036261538754203">"Ärge eemaldage"</string>
<string name="ext_media_init_action" msgid="2312974060585056709">"Seadistus"</string>
- <string name="ext_media_unmount_action" msgid="966992232088442745">"Eemaldamine"</string>
- <string name="ext_media_browse_action" msgid="344865351947079139">"Avastamine"</string>
+ <string name="ext_media_unmount_action" msgid="966992232088442745">"Eemalda"</string>
+ <string name="ext_media_browse_action" msgid="344865351947079139">"Avasta"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Vahetage väljundit"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"Üksust <xliff:g id="NAME">%s</xliff:g> pole"</string>
<string name="ext_media_missing_message" msgid="4408988706227922909">"Sisestage seade uuesti"</string>
@@ -1568,9 +1568,9 @@
<string name="action_bar_home_subtitle_description_format" msgid="4346835454749569826">"%1$s, %2$s, %3$s"</string>
<string name="storage_internal" msgid="8490227947584914460">"Sisemine jagatud mäluruum"</string>
<string name="storage_sd_card" msgid="3404740277075331881">"SD-kaart"</string>
- <string name="storage_sd_card_label" msgid="7526153141147470509">"Tootja <xliff:g id="MANUFACTURER">%s</xliff:g> SD-kaart"</string>
+ <string name="storage_sd_card_label" msgid="7526153141147470509">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD-kaart"</string>
<string name="storage_usb_drive" msgid="448030813201444573">"USB-ketas"</string>
- <string name="storage_usb_drive_label" msgid="6631740655876540521">"Tootja <xliff:g id="MANUFACTURER">%s</xliff:g> USB-ketas"</string>
+ <string name="storage_usb_drive_label" msgid="6631740655876540521">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB-ketas"</string>
<string name="storage_usb" msgid="2391213347883616886">"USB-mäluseade"</string>
<string name="extract_edit_menu_button" msgid="63954536535863040">"Muuda"</string>
<string name="data_usage_warning_title" msgid="9034893717078325845">"Andmekasutuse hoiatus"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Piirkonnaeelistus"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Sisestage keele nimi"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Soovitatud"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Soovitatud"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Kõik keeled"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Kõik piirkonnad"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Otsing"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Kas anda rakendusele <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> juurdepääs kõigile seadmelogidele?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Luba ühekordne juurdepääs"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Ära luba"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Seadmelogid jäädvustavad, mis teie seadmes toimub. Rakendused saavad neid logisid kasutada probleemide tuvastamiseks ja lahendamiseks.\n\nMõned logid võivad sisaldada tundlikku teavet, seega lubage juurdepääs kõigile seadmelogidele ainult rakendustele, mida usaldate. \n\nKui te ei luba sellel rakendusel kõigile seadmelogidele juurde pääseda, pääseb see siiski juurde oma logidele. Teie seadme tootja võib teie seadmes siiski teatud logidele või teabele juurde pääseda. Lisateave"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Seadmelogid jäädvustavad, mis teie seadmes toimub. Rakendused saavad neid logisid kasutada probleemide tuvastamiseks ja lahendamiseks.\n\nMõned logid võivad sisaldada tundlikku teavet, seega lubage juurdepääs kõigile seadmelogidele ainult rakendustele, mida usaldate. \n\nKui te ei luba sellel rakendusel kõigile seadmelogidele juurde pääseda, pääseb see siiski juurde oma logidele. Teie seadme tootja võib teie seadmes siiski teatud logidele või teabele juurde pääseda."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ära kuva uuesti"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Rakendus <xliff:g id="APP_0">%1$s</xliff:g> soovib näidata rakenduse <xliff:g id="APP_2">%2$s</xliff:g> lõike"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Muuda"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Vaadake aktiivseid rakendusi"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Teie seadmest <xliff:g id="DEVICE">%1$s</xliff:g> ei pääse telefoni kaamerale juurde"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Teie seadmest <xliff:g id="DEVICE">%1$s</xliff:g> ei pääse tahvelarvuti kaamerale juurde"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Sellele ei pääse voogesituse ajal juurde. Proovige juurde pääseda oma telefonis."</string>
<string name="system_locale_title" msgid="711882686834677268">"Süsteemi vaikeseade"</string>
</resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index c301611..10f6857 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -57,7 +57,7 @@
<string name="imei" msgid="2157082351232630390">"IMEIa"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Sarrerako deien identifikazio-zerbitzua"</string>
- <string name="ClirMmi" msgid="6752346475055446417">"Ezkutatu irteerako deitzailearen IDa"</string>
+ <string name="ClirMmi" msgid="6752346475055446417">"Ezkutatu irteerako deitzailearen identitatea"</string>
<string name="ColpMmi" msgid="4736462893284419302">"Konektatutako linearen IDa"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Konektatutako linearen ID murriztapena"</string>
<string name="CfMmi" msgid="8390012691099787178">"Dei-desbideratzea"</string>
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Hatz-markaren eragiketa bertan behera utzi da."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Erabiltzaileak bertan behera utzi du hatz-marka bidezko eragiketa."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Saiakera gehiegi egin dituzu. Saiatu berriro geroago."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Saiakera gehiegi egin dituzu. Desgaitu egin da hatz-marken sentsorea."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Saiatu berriro."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Ez da erregistratu hatz-markarik."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Gailu honek ez du hatz-marken sentsorerik."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> prestatzen."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Aplikazioak abiarazten."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Bertsio-berritzea amaitzen."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Konfiguratzen jarraitu nahi duzu?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Etengailua sakatu duzu; pantaila itzaltzeko balio du horrek.\n\nUki ezazu arin, hatz-marka konfiguratu bitartean."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Itzali pantaila"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Jarraitu konfiguratzen"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Pantaila itzaltzeko, sakatu hau"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Itzali pantaila"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Hatz-marka egiaztatzen jarraitu nahi duzu?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Etengailua sakatu duzu; pantaila itzaltzeko balio du horrek.\n\nUki ezazu arin, hatz-marka egiaztatzeko."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Itzali pantaila"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Sakatu konfiguratzeko"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Hauta ezazu konfiguratzeko"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Gailua formateatu beharko duzu, agian. Saka ezazu kanporatzeko."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Argazkiak eta multimedia-fitxategiak transferitzeko"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Argazkiak, bideoak, musika eta abar gordetzeko"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Arakatu multimedia-fitxategiak"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Arazo bat dago honekin: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ez da funtzionatzen ari"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Sakatu konpontzeko"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Hondatuta dago <xliff:g id="NAME">%s</xliff:g>. Hauta ezazu konpontzeko."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Gailua formateatu beharko duzu, agian. Saka ezazu kanporatzeko."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Ez da onartzen <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> hauteman da"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ez da funtzionatzen ari"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Gailuak ez du <xliff:g id="NAME">%s</xliff:g> onartzen. Sakatu onartzen den formatu batean konfiguratzeko."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Sakatu konfiguratzeko"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Hauta ezazu onartzen den formatu batean <xliff:g id="NAME">%s</xliff:g> konfiguratzeko."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Gailua formateatu beharko duzu, agian"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ustekabean kendu da"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Lurralde-hobespena"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Adierazi hizkuntza"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Iradokitakoak"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Iradokitakoak"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Hizkuntza guztiak"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Lurralde guztiak"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Bilaketa"</string>
@@ -1944,8 +1945,7 @@
<string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera ez dago erabilgarri"</string>
<string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Jarraitu telefonoan"</string>
<string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofonoa ez dago erabilgarri"</string>
- <!-- no translation found for app_streaming_blocked_title_for_playstore_dialog (8149823099822897538) -->
- <skip />
+ <string name="app_streaming_blocked_title_for_playstore_dialog" msgid="8149823099822897538">"Play Store ez dago erabilgarri"</string>
<string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-ren ezarpenak ez daude erabilgarri"</string>
<string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tabletaren ezarpenak ez daude erabilgarri"</string>
<string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Telefonoaren ezarpenak ez daude erabilgarri"</string>
@@ -1955,12 +1955,9 @@
<string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Segurtasun gehigarria eskatzen ari da aplikazioa. Gailu horren ordez, erabili Android TV darabilen bat."</string>
<string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Segurtasun gehigarria eskatzen ari da aplikazioa. Gailu horren ordez, erabili tableta."</string>
<string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Segurtasun gehigarria eskatzen ari da aplikazioa. Gailu horren ordez, erabili telefonoa."</string>
- <!-- no translation found for app_streaming_blocked_message_for_settings_dialog (820334666354451145) -->
- <skip />
- <!-- no translation found for app_streaming_blocked_message_for_settings_dialog (3286849551133045896) -->
- <skip />
- <!-- no translation found for app_streaming_blocked_message_for_settings_dialog (6264287556598916295) -->
- <skip />
+ <string name="app_streaming_blocked_message_for_settings_dialog" product="tv" msgid="820334666354451145">"Aplikazioa ezin da <xliff:g id="DEVICE">%1$s</xliff:g> erabilita atzitu. Gailu horren ordez, erabili Android TV darabilen bat."</string>
+ <string name="app_streaming_blocked_message_for_settings_dialog" product="tablet" msgid="3286849551133045896">"Aplikazioa ezin da <xliff:g id="DEVICE">%1$s</xliff:g> erabilita atzitu. Gailu horren ordez, erabili tableta."</string>
+ <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Aplikazioa ezin da <xliff:g id="DEVICE">%1$s</xliff:g> erabilita atzitu. Gailu horren ordez, erabili telefonoa."</string>
<string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Aplikazioa Android-en bertsio zaharrago baterako sortu zenez, baliteke behar bezala ez funtzionatzea. Bilatu eguneratzerik baden, edo jarri garatzailearekin harremanetan."</string>
<string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Bilatu eguneratzeak"</string>
<string name="new_sms_notification_title" msgid="6528758221319927107">"Mezu berriak dituzu"</string>
@@ -2053,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Gailuko erregistro guztiak atzitzeko baimena eman nahi diozu <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> aplikazioari?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Eman behin erabiltzeko baimena"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Ez eman baimenik"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Gailuko erregistroetan gailuan gertatzen den guztia gordetzen da. Arazoak bilatu eta konpontzeko erabil ditzakete aplikazioek erregistro horiek.\n\nBaliteke erregistro batzuek kontuzko informazioa edukitzea. Beraz, eman gailuko erregistro guztiak atzitzeko baimena fidagarritzat jotzen dituzun aplikazioei bakarrik. \n\nNahiz eta gailuko erregistro guztiak atzitzeko baimena ez eman aplikazio honi, aplikazioak hari dagozkion erregistroak atzitu ahalko ditu. Gainera, baliteke gailuaren fabrikatzaileak gailuko erregistro edo datu batzuk atzitu ahal izatea. Lortu informazio gehiago"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Gailuko erregistroetan gailuan gertatzen den guztia gordetzen da. Arazoak bilatu eta konpontzeko erabil ditzakete aplikazioek erregistro horiek.\n\nBaliteke erregistro batzuek kontuzko informazioa edukitzea. Beraz, eman gailuko erregistro guztiak atzitzeko baimena fidagarritzat jotzen dituzun aplikazioei bakarrik. \n\nNahiz eta gailuko erregistro guztiak atzitzeko baimena ez eman aplikazio honi, aplikazioak hari dagozkion erregistroak atzitu ahalko ditu. Gainera, baliteke gailuaren fabrikatzaileak gailuko erregistro edo datu batzuk atzitu ahal izatea."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ez erakutsi berriro"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> aplikazioak <xliff:g id="APP_2">%2$s</xliff:g> aplikazioaren zatiak erakutsi nahi ditu"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Editatu"</string>
@@ -2294,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Ikusi zer aplikazio dauden aktibo"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Ezin da atzitu telefonoaren kamera <xliff:g id="DEVICE">%1$s</xliff:g> gailutik"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Ezin da atzitu tabletaren kamera <xliff:g id="DEVICE">%1$s</xliff:g> gailutik"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Ezin da atzitu edukia hura igorri bitartean. Oraingo gailuaren ordez, erabili telefonoa."</string>
<string name="system_locale_title" msgid="711882686834677268">"Sistemaren balio lehenetsia"</string>
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index fc284fe..184010f 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"عملکرد اثر انگشت لغو شد."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"کاربر عملیات اثر انگشت را لغو کرد"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"تلاشهای زیادی انجام شده است. بعداً دوباره امتحان کنید."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"تلاشهای بسیاری زیادی انجام شده است. حسگر اثر انگشت غیرفعال شد."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"دوباره امتحان کنید."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"اثر انگشتی ثبت نشده است."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"این دستگاه حسگر اثر انگشت ندارد."</string>
@@ -1021,7 +1022,7 @@
<string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"ماندن در این صفحه"</string>
<string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nمطمئنید میخواهید این صفحه را ترک کنید؟"</string>
<string name="save_password_label" msgid="9161712335355510035">"تأیید"</string>
- <string name="double_tap_toast" msgid="7065519579174882778">"نکته: برای نزدیکنمایی و دورنمایی، دو بار ضربه بزنید."</string>
+ <string name="double_tap_toast" msgid="7065519579174882778">"نکته: برای زومپیش و زومپس کردن، دو بار ضربه بزنید."</string>
<string name="autofill_this_form" msgid="3187132440451621492">"تکمیل خودکار"</string>
<string name="setup_autofill" msgid="5431369130866618567">"راهاندازی تکمیل خودکار"</string>
<string name="autofill_window_title" msgid="4379134104008111961">"تکمیل خودکار با <xliff:g id="SERVICENAME">%1$s</xliff:g>"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"آمادهسازی <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"درحال آغاز کردن برنامهها."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"درحال اتمام راهاندازی."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"ادامه راهاندازی؟"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"دکمه روشن/ خاموش را فشار دادید — این کار معمولاً صفحهنمایش را خاموش میکند.\n\nهنگام راهاندازی اثر انگشت، آرام ضربه بزنید."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"خاموش کردن صفحه"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"ادامه راهاندازی"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"برای خاموش کردن صفحهنمایش، ضربه بزنید"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"خاموش کردن صفحه"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"تأیید اثر انگشت را ادامه میدهید؟"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"دکمه روشن/ خاموش را فشار دادید — این کار معمولاً صفحهنمایش را خاموش میکند.\n\nبرای تأیید اثر انگشتتان، آرام ضربه بزنید."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"خاموش کردن صفحه"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"برای راهاندازی ضربه بزنید"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"برای راهاندازی، انتخاب کنید"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"شاید لازم باشد دستگاه را دوباره قالببندی کنید. برای خارج کردن، ضربه بزنید."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"برای انتقال عکسها و رسانه"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"برای ذخیره کردن عکس، ویدیو، موسیقی و غیره"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"فایلهای رسانهای را مرور کنید"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"مشکل مرتبط با <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> کار نمیکند"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"برای برطرف کردن مشکل، ضربه بزنید"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> خراب است. رفع خطا را انتخاب کنید."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"شاید لازم باشد دستگاه را دوباره قالببندی کنید. برای خارج کردن، ضربه بزنید."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> پشتیبانی نشده"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> تشخیص داده شد"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> کار نمیکند"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"این دستگاه از این <xliff:g id="NAME">%s</xliff:g> پشتیبانی نمیکند. برای نصب آن در قالب پشتیبانیشده ضربه بزنید."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"برای راهاندازی ضربه بزنید."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"برای راهاندازی <xliff:g id="NAME">%s</xliff:g> در قالب پشتیبانیشده، انتخاب کنید."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"شاید لازم باشد دستگاه را دوباره قالببندی کنید"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> بهطور غیرمنتظره جدا شد"</string>
@@ -1424,7 +1424,7 @@
<string name="ext_media_unmounting_notification_title" msgid="4147986383917892162">"درحال بیرون راندن <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmounting_notification_message" msgid="5717036261538754203">"جدا نکنید"</string>
<string name="ext_media_init_action" msgid="2312974060585056709">"راهاندازی"</string>
- <string name="ext_media_unmount_action" msgid="966992232088442745">"بیرون راندن"</string>
+ <string name="ext_media_unmount_action" msgid="966992232088442745">"خارج کردن"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"کاوش"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"تغییر خروجی"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> وجود ندارد"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"اولویتهای منطقه"</string>
<string name="search_language_hint" msgid="7004225294308793583">"نام زبان را تایپ کنید"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"پیشنهادی"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"پیشنهادی"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"همه زبانها"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"همه منطقهها"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"جستجو"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"به <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> اجازه میدهید به همه گزارشهای دستگاه دسترسی داشته باشد؟"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"مجاز کردن دسترسی یکباره"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"اجازه ندادن"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"گزارشهای دستگاه آنچه را در دستگاهتان رخ میدهد ثبت میکند. برنامهها میتوانند از این گزارشها برای پیدا کردن مشکلات و رفع آنها استفاده کنند.\n\nبرخیاز گزارشها ممکن است حاوی اطلاعات حساس باشند، بنابراین فقط به برنامههای مورداعتمادتان اجازه دسترسی به همه گزارشهای دستگاه را بدهید. \n\nاگر به این برنامه اجازه ندهید به همه گزارشهای دستگاه دسترسی داشته باشد، همچنان میتواند به گزارشهای خودش دسترسی داشته باشد. سازنده دستگاه نیز ممکن است همچنان بتواند به برخیاز گزارشها یا اطلاعات دستگاهتان دسترسی داشته باشد. بیشتر بدانید"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"گزارشهای دستگاه آنچه را در دستگاهتان رخ میدهد ثبت میکند. برنامهها میتوانند از این گزارشها برای پیدا کردن مشکلات و رفع آنها استفاده کنند.\n\nبرخیاز گزارشها ممکن است حاوی اطلاعات حساس باشند، بنابراین فقط به برنامههای مورداعتمادتان اجازه دسترسی به همه گزارشهای دستگاه را بدهید. \n\nاگر به این برنامه اجازه ندهید به همه گزارشهای دستگاه دسترسی داشته باشد، همچنان میتواند به گزارشهای خودش دسترسی داشته باشد. سازنده دستگاه نیز ممکن است همچنان بتواند به برخیاز گزارشها یا اطلاعات دستگاهتان دسترسی داشته باشد."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"دوباره نشان داده نشود"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> میخواهد تکههای <xliff:g id="APP_2">%2$s</xliff:g> را نشان دهد"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"ویرایش"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"بررسی برنامههای فعال"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"نمیتوان از <xliff:g id="DEVICE">%1$s</xliff:g> شما به دوربین تلفن دسترسی داشت"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"نمیتوان از <xliff:g id="DEVICE">%1$s</xliff:g> شما به دوربین رایانه لوحی دسترسی داشت"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"درحین جاریسازی، نمیتوانید به آن دسترسی داشته باشید. دسترسی به آن را در تلفنتان امتحان کنید."</string>
<string name="system_locale_title" msgid="711882686834677268">"پیشفرض سیستم"</string>
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index ab4502f..dcbe1ba 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Sormenjälkitoiminto peruutettiin."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Käyttäjä peruutti sormenjälkitoiminnon."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Liian monta yritystä. Yritä myöhemmin uudelleen."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Liian monta yritystä. Sormenjälkitunnistin poistettu käytöstä."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Yritä uudelleen."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Sormenjälkiä ei ole otettu käyttöön."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Laitteessa ei ole sormenjälkitunnistinta."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Valmistellaan: <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Käynnistetään sovelluksia."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Viimeistellään päivitystä."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Haluatko jatkaa?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Painoit virtapainiketta, mikä yleensä sammuttaa näytön.\n\nKosketa painiketta kevyesti tallentaessasi sormenjälkeä."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Sammuta näyttö"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Jatka käyttöönottoa"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Sammuta näyttö napauttamalla"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Sammuta näyttö"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Jatketaanko sormenjäljen vahvistamista?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Painoit virtapainiketta, mikä yleensä sammuttaa näytön.\n\nVahvista sormenjälki koskettamalla painiketta kevyesti."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Sammuta näyttö"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Määritä koskettamalla."</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Valitse käyttöönottoa varten"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Sinun on ehkä alustettava laite uudelleen. Poista napauttamalla."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Kuvien ja median siirtämiseen"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Kuvien, videoiden ja muun tallentamiseen"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Selaa mediatiedostoja"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Ongelma: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ei toimi"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Korjaa napauttamalla."</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> on viallinen. Korjaa valitsemalla."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Sinun on ehkä alustettava laite uudelleen. Poista napauttamalla."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Epäyhteensopiva <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> havaittu"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ei toimi"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"<xliff:g id="NAME">%s</xliff:g> ei ole yhteensopiva tämän laitteen kanssa. Ota se käyttöön tuetussa tilassa napauttamalla."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Ota käyttöön napauttamalla."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Valitse tämä, jos haluat, että <xliff:g id="NAME">%s</xliff:g> otetaan käyttöön tuetussa muodossa."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Sinun on ehkä alustettava laite uudelleen"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> poistettiin yllättäen"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Alueasetus"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Anna kielen nimi"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Ehdotukset"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Ehdotettu"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Kaikki kielet"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Kaikki alueet"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Haku"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Saako <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> pääsyn kaikkiin laitelokeihin?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Salli kertaluonteinen pääsy"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Älä salli"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Laitteen tapahtumat tallentuvat laitelokeihin. Niiden avulla sovellukset voivat löytää ja korjata ongelmia.\n\nJotkin lokit voivat sisältää arkaluontoista tietoa, joten salli pääsy kaikkiin laitelokeihin vain sovelluksille, joihin luotat. \n\nJos et salli tälle sovellukselle pääsyä kaikkiin laitelokeihin, sillä on kuitenkin pääsy sen omiin lokeihin. Laitteen valmistajalla voi olla pääsy joihinkin lokeihin tai tietoihin laitteella. Lue lisää"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Laitteen tapahtumat tallentuvat laitelokeihin. Niiden avulla sovellukset voivat löytää ja korjata ongelmia.\n\nJotkin lokit voivat sisältää arkaluontoista tietoa, joten salli pääsy kaikkiin laitelokeihin vain sovelluksille, joihin luotat. \n\nJos et salli tälle sovellukselle pääsyä kaikkiin laitelokeihin, sillä on kuitenkin pääsy sen omiin lokeihin. Laitteen valmistajalla voi olla pääsy joihinkin lokeihin tai tietoihin laitteella."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Älä näytä uudelleen"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> haluaa näyttää osia sovelluksesta <xliff:g id="APP_2">%2$s</xliff:g>."</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Muokkaa"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Tarkista aktiiviset sovellukset"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> ei pääse puhelimen kameraan"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"<xliff:g id="DEVICE">%1$s</xliff:g> ei pääse tabletin kameraan"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Sisältöön ei saa pääsyä striimauksen aikana. Kokeile striimausta puhelimella."</string>
<string name="system_locale_title" msgid="711882686834677268">"Järjestelmän oletusarvo"</string>
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 5fa8727..e9ec78a 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -303,7 +303,7 @@
<string name="permgroupdesc_location" msgid="1995955142118450685">"accéder à la position de cet appareil"</string>
<string name="permgrouplab_calendar" msgid="6426860926123033230">"Agenda"</string>
<string name="permgroupdesc_calendar" msgid="6762751063361489379">"accéder à votre agenda"</string>
- <string name="permgrouplab_sms" msgid="795737735126084874">"Messagerie texte"</string>
+ <string name="permgrouplab_sms" msgid="795737735126084874">"Messages texte"</string>
<string name="permgroupdesc_sms" msgid="5726462398070064542">"envoyer et afficher des messages texte"</string>
<string name="permgrouplab_storage" msgid="17339216290379241">"Fichiers"</string>
<string name="permgroupdesc_storage" msgid="5378659041354582769">"accéder aux fichiers sur votre appareil"</string>
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Opération d\'empreinte digitale numérique annulée."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"L\'opération d\'empreinte digitale a été annulée par l\'utilisateur."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Trop de tentatives. Veuillez réessayer plus tard."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Trop de tentatives. Capteur d\'empreintes digitales désactivé."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Réessayer."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Aucune empreinte digitale enregistrée."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Cet appareil ne possède pas de capteur d\'empreintes digitales."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Préparation de <xliff:g id="APPNAME">%1$s</xliff:g> en cours…"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Lancement des applications…"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Finalisation de la mise à jour."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Poursuivre la configuration?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Vous avez appuyé sur le l\'interrupteur – cette action éteint habituellement l\'écran.\n\nEssayez de toucher légèrement pendant la configuration de votre empreinte digitale."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Éteindre l\'écran"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Poursuivre configu."</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toucher pour éteindre l\'écran"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Éteindre l\'écran"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Poursuivre vérifica. empreinte digitale?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Vous avez appuyé sur le l\'interrupteur – cette action éteint habituellement l\'écran.\n\nEssayez de toucher légèrement pour vérifier votre empreinte digitale."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Éteindre l\'écran"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Toucher pour configurer"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Sélectionnez pour configurer"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Vous devrez peut-être reformater l\'appareil. Touchez pour l\'éjecter."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Pour transférer des photos et d\'autres fichiers"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Pour stocker des photos, des vidéos, de la musique et plus encore"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Parcourir les fichiers multimédias"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Il y a un problème avec <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ne fonctionne pas"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Touchez la notification pour corriger la situation"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Le média « <xliff:g id="NAME">%s</xliff:g> » est corrompu. Sélectionnez-le pour corriger la situation."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Vous devrez peut-être reformater l\'appareil. Touchez pour l\'éjecter."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> non compatible"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> détecté"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ne fonctionne pas"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Cet appareil n\'est pas compatible avec la mémoire de stockage « <xliff:g id="NAME">%s</xliff:g> ». Touchez pour la configurer dans un format compatible."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Toucher pour configurer ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Sélectionner pour configurer <xliff:g id="NAME">%s</xliff:g> dans un format pris en charge."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Vous devrez peut-être reformater l\'appareil"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Retrait inattendu de la mémoire « <xliff:g id="NAME">%s</xliff:g> »"</string>
@@ -1425,7 +1425,7 @@
<string name="ext_media_unmounting_notification_message" msgid="5717036261538754203">"Ne pas retirer"</string>
<string name="ext_media_init_action" msgid="2312974060585056709">"Configurer"</string>
<string name="ext_media_unmount_action" msgid="966992232088442745">"Éjecter"</string>
- <string name="ext_media_browse_action" msgid="344865351947079139">"Découvrir"</string>
+ <string name="ext_media_browse_action" msgid="344865351947079139">"Explorer"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Changer de sortie"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"Mémoire de stockage <xliff:g id="NAME">%s</xliff:g> manquante"</string>
<string name="ext_media_missing_message" msgid="4408988706227922909">"Insérez l\'appareil de nouveau"</string>
@@ -1705,7 +1705,7 @@
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversion des couleurs"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correction des couleurs"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode Une main"</string>
- <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Réduction supplémentaire de la luminosité"</string>
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Très sombre"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume maintenues enfoncées. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume maintenues enfoncées. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Maintenez les deux touches de volume enfoncées pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Préférences régionales"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Entrez la langue"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Suggestions"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Suggestions"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Toutes les langues"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Toutes les régions"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Rechercher"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Autoriser <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> à accéder à l\'ensemble des journaux de l\'appareil?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Autoriser un accès unique"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Ne pas autoriser"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Les journaux de l\'appareil enregistrent ce qui se passe sur celui-ci. Les applications peuvent utiliser ces journaux pour trouver et résoudre des problèmes.\n\nCertains journaux peuvent contenir des renseignements confidentiels. N\'autorisez donc que les applications auxquelles vous faites confiance puisque celles-ci pourront accéder à l\'ensemble des journaux de l\'appareil. \n\nMême si vous n\'autorisez pas cette application à accéder à l\'ensemble des journaux de l\'appareil, elle aura toujours accès à ses propres journaux. Le fabricant de votre appareil pourrait toujours être en mesure d\'accéder à certains journaux ou renseignements sur votre appareil. En savoir plus"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Les journaux de l\'appareil enregistrent ce qui se passe sur celui-ci. Les applications peuvent utiliser ces journaux pour trouver et résoudre des problèmes.\n\nCertains journaux peuvent contenir des renseignements confidentiels. N\'autorisez donc que les applications auxquelles vous faites confiance puisque celles-ci pourront accéder à l\'ensemble des journaux de l\'appareil. \n\nMême si vous n\'autorisez pas cette application à accéder à l\'ensemble des journaux de l\'appareil, elle aura toujours accès à ses propres journaux. Le fabricant de votre appareil pourrait toujours être en mesure d\'accéder à certains journaux ou renseignements sur votre appareil."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ne plus afficher"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> souhaite afficher <xliff:g id="APP_2">%2$s</xliff:g> tranches"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Modifier"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Vérifier les applications actives"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Impossible d\'accéder à l\'appareil photo du téléphone à partir de votre <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Impossible d\'accéder à l\'appareil photo de la tablette à partir de votre <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Vous ne pouvez pas y accéder lorsque vous utilisez la diffusion en continu. Essayez sur votre téléphone à la place."</string>
<string name="system_locale_title" msgid="711882686834677268">"Paramètre système par défaut"</string>
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 4ad22af..dbbe31b 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Opération d\'empreinte digitale annulée."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Opération d\'authentification par empreinte digitale annulée par l\'utilisateur."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Trop de tentatives. Veuillez réessayer plus tard."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Trop de tentatives. Lecteur d\'empreinte digitale désactivé."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Veuillez réessayer."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Aucune empreinte digitale enregistrée."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Aucun lecteur d\'empreinte digitale n\'est installé sur cet appareil."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Préparation de <xliff:g id="APPNAME">%1$s</xliff:g> en cours…"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Lancement des applications…"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Finalisation de la mise à jour."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Poursuivre la configuration ?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Vous avez appuyé sur le bouton Marche/Arrêt, ce qui éteint généralement l\'écran.\n\nEssayez d\'appuyer doucement pendant la configuration de votre empreinte digitale."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Éteindre l\'écran"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Poursuivre"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Appuyer pour éteindre l\'écran"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Éteindre l\'écran"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continuer de valider votre empreinte ?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Vous avez appuyé sur le bouton Marche/Arrêt, ce qui éteint généralement l\'écran.\n\nPour valider votre empreinte digitale, appuyez plus doucement."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Éteindre l\'écran"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Appuyer pour configurer"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Sélectionnez pour configurer"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Vous devez peut-être reformater le périphérique. Appuyez pour l\'éjecter."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Pour transférer photos et fichiers"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Pour stocker des photos, des vidéos, de la musique, etc."</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Parcourez les fichiers multimédias"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problème avec : <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ne fonctionne pas"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Appuyez sur la notification pour résoudre le problème"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"La <xliff:g id="NAME">%s</xliff:g> est corrompue. Sélectionnez cette option pour résoudre le problème."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Vous devez peut-être reformater le périphérique. Appuyez pour l\'éjecter."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> non compatible"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> détectée"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ne fonctionne pas"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Cet appareil n\'est pas compatible avec le support \"<xliff:g id="NAME">%s</xliff:g>\". Appuyez ici pour le configurer dans un format accepté."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Appuyez pour configurer."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Sélectionnez pour configurer <xliff:g id="NAME">%s</xliff:g> dans un format accepté."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Vous devez peut-être reformater le périphérique"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Retrait inattendu de mémoire \"<xliff:g id="NAME">%s</xliff:g>\""</string>
@@ -1427,7 +1427,7 @@
<string name="ext_media_unmount_action" msgid="966992232088442745">"Éjecter"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"Parcourir"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Changer de sortie"</string>
- <string name="ext_media_missing_title" msgid="3209472091220515046">"Mémoire de stockage \"<xliff:g id="NAME">%s</xliff:g>\" manquante"</string>
+ <string name="ext_media_missing_title" msgid="3209472091220515046">"Support \"<xliff:g id="NAME">%s</xliff:g>\" manquant"</string>
<string name="ext_media_missing_message" msgid="4408988706227922909">"Insérez le périphérique"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"Transfert de l\'application <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"Déplacement des données en cours"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Préférences régionales"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Saisissez la langue"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Suggestions"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Suggestions"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Toutes les langues"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Toutes les régions"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Rechercher"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Autoriser <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> à accéder à tous les journaux de l\'appareil ?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Autoriser un accès unique"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Ne pas autoriser"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Les journaux enregistrent ce qui se passe sur votre appareil. Les applis peuvent les utiliser pour rechercher et résoudre les problèmes.\n\nCertains journaux pouvant contenir des infos sensibles, autorisez uniquement les applis de confiance à accéder à tous les journaux de l\'appareil. \n\nSi vous refusez à cette appli l\'accès à tous les journaux de l\'appareil, elle a quand même accès aux siens. Le fabricant de l\'appareil peut accéder à certains journaux ou certaines infos sur votre appareil. En savoir plus"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Les journaux enregistrent ce qui se passe sur votre appareil. Les applis peuvent les utiliser pour rechercher et résoudre les problèmes.\n\nCertains journaux pouvant contenir des infos sensibles, autorisez uniquement les applis de confiance à accéder à tous les journaux de l\'appareil. \n\nSi vous refusez à cette appli l\'accès à tous les journaux de l\'appareil, elle a quand même accès aux siens. Le fabricant de l\'appareil peut accéder à certains journaux ou certaines infos sur votre appareil."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ne plus afficher"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> souhaite afficher des éléments de <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Modifier"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Vérifier les applis actives"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Impossible d\'accéder à l\'appareil photo du téléphone depuis votre <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Impossible d\'accéder à l\'appareil photo de la tablette depuis votre <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Impossible d\'accéder à cela pendant le streaming. Essayez plutôt sur votre téléphone."</string>
<string name="system_locale_title" msgid="711882686834677268">"Paramètre système par défaut"</string>
</resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index a754421..e6384e6 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Cancelouse a operación da impresión dixital."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"O usuario cancelou a operación da impresión dixital."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Demasiados intentos. Téntao de novo máis tarde."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Demasiados intentos. Desactivouse o sensor de impresión dixital."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Téntao de novo."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Non se rexistraron impresións dixitais."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo non ten sensor de impresión dixital."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando aplicacións."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Está finalizando o arranque"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Queres continuar coa configuración?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Premiches o botón de acendido, o que adoita facer que se apague a pantalla.\n\nProba a dar un toque suave namentres configuras a impresión dixital."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Desactivar pantalla"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Seguir configurando"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toca para desactivar a pantalla"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Desactivar pantalla"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Queres seguir verificando a impresión?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Premiches o botón de acendido, o que adoita facer que se apague a pantalla.\n\nProba a dar un toque suave para verificar a impresión dixital."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Desactivar pantalla"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Toca para configurar"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Selecciona o soporte para configuralo"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Pode ser necesario que formates de novo o dispositivo. Toca para expulsalo."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Para transferir fotos e contidos multimedia"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Para almacenar fotos, vídeos, música e moito máis"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Explora os ficheiros do soporte"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Produciuse un problema coa <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"O dispositivo (<xliff:g id="NAME">%s</xliff:g>) non funciona"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Toca para solucionalo"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"A <xliff:g id="NAME">%s</xliff:g> está danada. Selecciona para corrixir o problema."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Pode ser necesario que formates de novo o dispositivo. Toca para expulsalo."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> incompatible"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Detectouse o seguinte: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"O dispositivo (<xliff:g id="NAME">%s</xliff:g>) non funciona"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Este dispositivo non é compatible con esta <xliff:g id="NAME">%s</xliff:g>. Toca para configurala nun formato compatible."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Toca para configurar"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Selecciona <xliff:g id="NAME">%s</xliff:g> para configurar o soporte cun formato compatible."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Pode ser necesario que formates de novo o dispositivo"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Retirouse a <xliff:g id="NAME">%s</xliff:g> de forma inesperada"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Preferencia de rexión"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Escribe o nome do idioma"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Suxeridos"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Rexións suxeridas"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Todos os idiomas"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Todas as rexións"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Buscar"</string>
@@ -1944,8 +1945,7 @@
<string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"A cámara non está dispoñible"</string>
<string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continúa no teléfono"</string>
<string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"O micrófono non está dispoñible"</string>
- <!-- no translation found for app_streaming_blocked_title_for_playstore_dialog (8149823099822897538) -->
- <skip />
+ <string name="app_streaming_blocked_title_for_playstore_dialog" msgid="8149823099822897538">"Play Store non está dispoñible"</string>
<string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"A configuración de Android TV non está dispoñible"</string>
<string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"A configuración da tableta non está dispoñible"</string>
<string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"A configuración do teléfono non está dispoñible"</string>
@@ -1955,12 +1955,9 @@
<string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Esta aplicación solicita seguranza adicional. Proba a facelo desde o dispositivo con Android TV."</string>
<string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Esta aplicación solicita seguranza adicional. Proba a facelo desde a tableta."</string>
<string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Esta aplicación solicita seguranza adicional. Proba a facelo desde o teléfono."</string>
- <!-- no translation found for app_streaming_blocked_message_for_settings_dialog (820334666354451145) -->
- <skip />
- <!-- no translation found for app_streaming_blocked_message_for_settings_dialog (3286849551133045896) -->
- <skip />
- <!-- no translation found for app_streaming_blocked_message_for_settings_dialog (6264287556598916295) -->
- <skip />
+ <string name="app_streaming_blocked_message_for_settings_dialog" product="tv" msgid="820334666354451145">"Non se puido acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o dispositivo con Android TV."</string>
+ <string name="app_streaming_blocked_message_for_settings_dialog" product="tablet" msgid="3286849551133045896">"Non se puido acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde a tableta."</string>
+ <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Non se puido acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o teléfono."</string>
<string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta aplicación deseñouse para unha versión anterior de Android e quizais non funcione correctamente. Proba a buscar actualizacións ou contacta co programador."</string>
<string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualización"</string>
<string name="new_sms_notification_title" msgid="6528758221319927107">"Tes mensaxes novas"</string>
@@ -2053,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Queres permitir que a aplicación <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> acceda a todos os rexistros do dispositivo?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Permitir acceso unha soa vez"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Non permitir"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Os rexistros do dispositivo dan conta do que ocorre neste. As aplicacións poden usalos para buscar problemas e solucionalos.\n\nAlgúns poden conter información confidencial, polo que che recomendamos que só permitas que accedan a todos os rexistros do dispositivo as aplicacións nas que confíes. \n\nEsta aplicación pode acceder aos seus propios rexistros aínda que non lle permitas acceder a todos. É posible que o fabricante do dispositivo teña acceso a algúns rexistros ou á información do teu dispositivo. Máis información"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Os rexistros do dispositivo dan conta do que ocorre neste. As aplicacións poden usalos para buscar problemas e solucionalos.\n\nAlgúns poden conter información confidencial, polo que che recomendamos que só permitas que accedan a todos os rexistros do dispositivo as aplicacións nas que confíes. \n\nEsta aplicación pode acceder aos seus propios rexistros aínda que non lle permitas acceder a todos. É posible que o fabricante do dispositivo teña acceso a algúns rexistros ou á información do teu dispositivo."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Non amosar outra vez"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> quere mostrar fragmentos de aplicación de <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Editar"</string>
@@ -2294,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Comprobar aplicacións activas"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Non se puido acceder á cámara do teléfono desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>)"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Non se puido acceder á cámara da tableta desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>)"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Non se puido acceder a este contido durante a reprodución en tempo real. Téntao desde o teléfono."</string>
<string name="system_locale_title" msgid="711882686834677268">"Opción predeterminada do sistema"</string>
</resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 14864ad..9a5b87c 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ફિંગરપ્રિન્ટ ઓપરેશન રદ કર્યું."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ફિંગરપ્રિન્ટ ચકાસવાની પ્રક્રિયા વપરાશકર્તાએ રદ કરી."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"ઘણા બધા પ્રયત્નો. પછીથી ફરી પ્રયાસ કરો."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"ઘણા વધુ પ્રયત્નો. ફિંગરપ્રિન્ટ સેન્સર અક્ષમ કરવામાં આવ્યું છે."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ફરી પ્રયાસ કરો."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"કોઈ ફિંગરપ્રિન્ટની નોંધણી કરવામાં આવી નથી."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"આ ડિવાઇસમાં કોઈ ફિંગરપ્રિન્ટ સેન્સર નથી."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> તૈયાર કરી રહ્યું છે."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ઍપ્લિકેશનો શરૂ કરી રહ્યાં છે."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"બૂટ સમાપ્ત કરી રહ્યાં છે."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"શું સેટઅપ કરવાનું ચાલુ રાખીએ?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"તમે પાવર બટન દબાવ્યું છે — જેનાથી સામાન્ય રીતે સ્ક્રીન બંધ થઈ જાય છે.\n\nતમારી ફિંગરપ્રિન્ટનું સેટઅપ કરતી વખતે હળવેથી ટૅપ કરવાનો પ્રયાસ કરો."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"સ્ક્રીન બંધ કરો"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"સેટઅપ આગળ વધારો"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"સ્ક્રીન બંધ કરવા માટે ટૅપ કરો"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"સ્ક્રીન બંધ કરો"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"શું તમારી ફિંગરપ્રિન્ટની ચકાસણી કરીએ?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"તમે પાવર બટન દબાવ્યું છે — જેનાથી સામાન્ય રીતે સ્ક્રીન બંધ થઈ જાય છે.\n\nતમારી ફિંગરપ્રિન્ટની ચકાસણી કરવા માટે, તેને હળવેથી ટૅપ કરવાનો પ્રયાસ કરો."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"સ્ક્રીન બંધ કરો"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"સેટ કરવા માટે ટૅપ કરો"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"સેટઅપ કરવા માટે પસંદ કરો"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"તમને કદાચ ડિવાઇસને ફરીથી ફૉર્મેટ કરવાની જરૂર પડી શકે છે. બહાર કાઢવા માટે ટૅપ કરો."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ફોટો અને મીડિયા ટ્રાન્સફર કરવા માટે"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ફોટા, વીડિયો, મ્યુઝિક અને બીજું ઘણું સ્ટોર કરવા માટે"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"મીડિયા ફાઇલો બ્રાઉઝ કરો"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g>ની સમસ્યા"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> કામ કરી રહ્યું નથી"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"ઠીક કરવા માટે ટૅપ કરો"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> દૂષિત છે. સુધારવા માટે પસંદ કરો."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"તમને કદાચ ડિવાઇસને ફરીથી ફૉર્મેટ કરવાની જરૂર પડી શકે છે. બહાર કાઢવા માટે ટૅપ કરો."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"અસમર્થિત <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g>ની ભાળ મળી"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> કામ કરી રહ્યું નથી"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"આ ઉપકરણ આ <xliff:g id="NAME">%s</xliff:g> નું સમર્થન કરતું નથી. સમર્થિત ફોર્મેટમાં સેટ કરવા માટે ટૅપ કરો."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"સેટઅપ કરવા માટે ટૅપ કરો."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"સપોર્ટ કરતા હોય એવા ફૉર્મેટમાં <xliff:g id="NAME">%s</xliff:g>નું સેટઅપ કરવા માટે પસંદ કરો."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"તમને કદાચ ડિવાઇસને ફરીથી ફૉર્મેટ કરવાની જરૂર પડી શકે છે"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> અનપેક્ષિત રીતે દૂર કર્યું"</string>
@@ -1428,7 +1428,7 @@
<string name="ext_media_browse_action" msgid="344865351947079139">"અન્વેષણ કરો"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"આઉટપુટ સ્વિચ કરો"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> ખૂટે છે"</string>
- <string name="ext_media_missing_message" msgid="4408988706227922909">"ફરીથી ઉપકરણ દાખલ કરો"</string>
+ <string name="ext_media_missing_message" msgid="4408988706227922909">"ફરીથી ડિવાઇસ દાખલ કરો"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"<xliff:g id="NAME">%s</xliff:g> ખસેડી રહ્યાં છીએ"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"ડેટાને ખસેડી રહ્યાં છીએ"</string>
<string name="ext_media_move_success_title" msgid="4901763082647316767">"કન્ટેન્ટ ટ્રાન્સફર કરવાનું પૂર્ણ થયું"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"પ્રદેશ પસંદગી"</string>
<string name="search_language_hint" msgid="7004225294308793583">"ભાષાનું નામ ટાઇપ કરો"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"સૂચવેલી ભાષા"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"સૂચવેલા"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"બધી ભાષાઓ"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"તમામ પ્રદેશ"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"શોધ"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>ને ડિવાઇસનો બધો લૉગ ઍક્સેસ કરવાની મંજૂરી આપવી છે?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"એક-વખતના ઍક્સેસની મંજૂરી આપો"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"મંજૂરી આપશો નહીં"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"તમારા ડિવાઇસ પર થતી કામગીરીને ડિવાઇસ લૉગ રેકોર્ડ કરે છે. ઍપ આ લૉગનો ઉપયોગ સમસ્યાઓ શોધી તેનું નિરાકરણ કરવા માટે કરી શકે છે.\n\nઅમુક લૉગમાં સંવેદનશીલ માહિતી હોઈ શકે, આથી ડિવાઇસનો બધો લૉગ ઍક્સેસ કરવાની મંજૂરી માત્ર તમારી વિશ્વાસપાત્ર ઍપને જ આપો. \n\nતમે આ ઍપને ડિવાઇસનો બધો લૉગ ઍક્સેસ કરવાની મંજૂરી નહીં આપી હોય, તો પણ તે તેના પોતાના લૉગ ઍક્સેસ કરી શકે છે. તમારા ડિવાઇસના નિર્માતા હજુ પણ કદાચ તમારા ડિવાઇસ પર અમુક લૉગ અથવા માહિતી ઍક્સેસ કરી શકે છે. વધુ જાણો"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"તમારા ડિવાઇસ પર થતી કામગીરીને ડિવાઇસ લૉગ રેકોર્ડ કરે છે. ઍપ આ લૉગનો ઉપયોગ સમસ્યાઓ શોધી તેનું નિરાકરણ કરવા માટે કરી શકે છે.\n\nઅમુક લૉગમાં સંવેદનશીલ માહિતી હોઈ શકે, આથી ડિવાઇસનો બધો લૉગ ઍક્સેસ કરવાની મંજૂરી માત્ર તમારી વિશ્વાસપાત્ર ઍપને જ આપો. \n\nજો તમે આ ઍપને ડિવાઇસનો બધો લૉગ ઍક્સેસ કરવાની મંજૂરી ન આપો, તો પણ તે તેના પોતાના લૉગ ઍક્સેસ કરી શકે છે. તમારા ડિવાઇસના નિર્માતા હજુ પણ કદાચ તમારા ડિવાઇસ પર અમુક લૉગ અથવા માહિતી ઍક્સેસ કરી શકે છે."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"ફરીથી બતાવશો નહીં"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g>એ <xliff:g id="APP_2">%2$s</xliff:g> સ્લાઇસ બતાવવા માગે છે"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"ફેરફાર કરો"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"સક્રિય ઍપ ચેક કરો"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"તમારા <xliff:g id="DEVICE">%1$s</xliff:g> પરથી ફોનના કૅમેરાનો ઍક્સેસ કરી શકતાં નથી"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"તમારા <xliff:g id="DEVICE">%1$s</xliff:g> પરથી ટૅબ્લેટના કૅમેરાનો ઍક્સેસ કરી શકતાં નથી"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"સ્ટ્રીમ કરતી વખતે આ ઍક્સેસ કરી શકાતું નથી. તેના બદલે તમારા ફોન પર પ્રયાસ કરો."</string>
<string name="system_locale_title" msgid="711882686834677268">"સિસ્ટમ ડિફૉલ્ટ"</string>
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index b901c02..7e0e8c3 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"फ़िंगरप्रिंट ऑपरेशन रोक दिया गया."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"उपयोगकर्ता ने फिंगरप्रिंट की पुष्टि की कार्रवाई रद्द कर दी है."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"बहुत ज़्यादा प्रयास कर लिए गए हैं. बाद में फिर से प्रयास करें."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"बहुत ज़्यादा कोशिशें. फ़िंगरप्रिंट सेंसर अक्षम है."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"फिर से कोशिश करें."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"कोई फ़िंगरप्रिंट रजिस्टर नहीं किया गया है."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"इस डिवाइस में फ़िंगरप्रिंट सेंसर नहीं है."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> तैयार हो रहा है."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ऐप्स प्रारंभ होने वाले हैं"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"बूट खत्म हो रहा है."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"सेट अप जारी रखना है?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"आपने पावर बटन दबाया - आम तौर पर, इससे स्क्रीन बंद हो जाती है.\n\nअपना फ़िंगरप्रिंट सेट अप करते समय, बटन को हल्के से टैप करके देखें."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"स्क्रीन बंद करें"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"सेट अप जारी रखें"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"स्क्रीन बंद करने के लिए टैप करें"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"स्क्रीन बंद करें"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"फ़िंगरप्रिंट की पुष्टि करना जारी रखना है?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"आपने पावर बटन दबाया - आम तौर पर, इससे स्क्रीन बंद हो जाती है.\n\nअपने फ़िंगरप्रिंट की पुष्टि करने के लिए, बटन पर हल्के से टैप करके देखें."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"स्क्रीन बंद करें"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"सेटअप करने के लिए टैप करें"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"सेट अप करने के लिए चुनें"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"आपको डिवाइस फिर से फ़ॉर्मैट करना पड़ सकता है. निकालने के लिए टैप करें."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"फ़ोटो और मीडिया ट्रांसफर करने के लिए"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"फ़ोटो, वीडियो, संगीत वगैरह सेव करने के लिए"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"मीडिया फ़ाइलों को ब्राउज़ करें"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> में गड़बड़ी है"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> काम नहीं कर रहा है"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"समस्या ठीक करने के लिए टैप करें"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> काम नहीं कर रहा है. ठीक करने के लिए चुनें."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"आपको डिवाइस फिर से फ़ॉर्मैट करना पड़ सकता है. निकालने के लिए टैप करें."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"असमर्थित <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> का पता चला"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> काम नहीं कर रहा है"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"यह डिवाइस इस <xliff:g id="NAME">%s</xliff:g> का समर्थन नहीं करता है. समर्थित प्रारूप में सेट करने के लिए टैप करें."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"सेट अप करने के लिए टैप करें."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"<xliff:g id="NAME">%s</xliff:g> को काम करने वाले फ़ॉर्मैट में सेट अप करने के लिए चुनें."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"आपको डिवाइस फिर से फ़ॉर्मैट करना पड़ सकता है"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> अप्रत्याशित रूप से निकाला गया"</string>
@@ -1427,7 +1427,7 @@
<string name="ext_media_unmount_action" msgid="966992232088442745">"निकालें"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"एक्सप्लोर करें"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"आउटपुट बदलें"</string>
- <string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> गुम है"</string>
+ <string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> नहीं मिल रहा है"</string>
<string name="ext_media_missing_message" msgid="4408988706227922909">"डिवाइस को दोबारा लगाएं"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"<xliff:g id="NAME">%s</xliff:g> को ले जाया जा रहा है"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"डेटा ले जाया जा रहा है"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"क्षेत्र प्राथमिकता"</string>
<string name="search_language_hint" msgid="7004225294308793583">"भाषा का नाम लिखें"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"दिए गए सुझाव"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"सुझाए गए देश/इलाके"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"सभी भाषाएं"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"सभी क्षेत्र"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"खोजें"</string>
@@ -1987,7 +1988,7 @@
<string name="app_category_productivity" msgid="1844422703029557883">"उत्पादकता"</string>
<string name="app_category_accessibility" msgid="6643521607848547683">"सुलभता"</string>
<string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"डिवाइस में जगह"</string>
- <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"यूएसबी डीबग करना"</string>
+ <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"यूएसबी डीबग करें"</string>
<string name="time_picker_hour_label" msgid="4208590187662336864">"घंटा"</string>
<string name="time_picker_minute_label" msgid="8307452311269824553">"मिनट"</string>
<string name="time_picker_header_text" msgid="9073802285051516688">"समय सेट करें"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"क्या <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> को डिवाइस लॉग का ऐक्सेस देना है?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"एक बार ऐक्सेस करने की अनुमति दें"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"अनुमति न दें"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"डिवाइस लॉग में आपके डिवाइस पर की गई कार्रवाइयां रिकॉर्ड होती हैं. ऐप्लिकेशन, इन लॉग का इस्तेमाल गड़बड़ियां ढूंढने और उन्हें सही करने के लिए करता है.\n\nकुछ लॉग में संवेदनशील जानकारी हो सकती है. इसलिए, सिर्फ़ भरोसेमंद ऐप्लिकेशन को डिवाइस लॉग का ऐक्सेस दें. \n\nअगर इस ऐप्लिकेशन को डिवाइस के सभी लॉग का ऐक्सेस नहीं दिया जाता है, तब भी यह डिवाइस पर अपने लॉग को ऐक्सेस कर सकता है. डिवाइस को बनाने वाली कंपनी अब भी डिवाइस के कुछ लॉग या जानकारी को ऐक्सेस कर सकती है. ज़्यादा जानें"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"डिवाइस लॉग में, आपके डिवाइस पर की गई कार्रवाइयां रिकॉर्ड होती हैं. ऐप्लिकेशन, इन लॉग का इस्तेमाल गड़बड़ियां ढूंढने और उन्हें ठीक करने के लिए करते हैं.\n\nकुछ लॉग में संवेदनशील जानकारी हो सकती है. इसलिए, सिर्फ़ भरोसेमंद ऐप्लिकेशन को डिवाइस लॉग का ऐक्सेस दें. \n\nअगर इस ऐप्लिकेशन को डिवाइस के सभी लॉग का ऐक्सेस नहीं दिया जाता है, तब भी यह डिवाइस पर अपने लॉग को ऐक्सेस कर सकता है. डिवाइस को बनाने वाली कंपनी अब भी डिवाइस के कुछ लॉग या जानकारी को ऐक्सेस कर सकती है."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"फिर से न दिखाएं"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g>, <xliff:g id="APP_2">%2$s</xliff:g> के हिस्से (स्लाइस) दिखाना चाहता है"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"बदलाव करें"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"चालू ऐप्लिकेशन देखें"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"आपके <xliff:g id="DEVICE">%1$s</xliff:g> से फ़ोन के कैमरे को ऐक्सेस नहीं किया जा सकता"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"आपके <xliff:g id="DEVICE">%1$s</xliff:g> से टैबलेट के कैमरे को ऐक्सेस नहीं किया जा सकता"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"स्ट्रीमिंग के दौरान, इसे ऐक्सेस नहीं किया जा सकता. इसके बजाय, अपने फ़ोन पर ऐक्सेस करके देखें."</string>
<string name="system_locale_title" msgid="711882686834677268">"सिस्टम डिफ़ॉल्ट"</string>
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 39db7b9..8200714 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -609,7 +609,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Radnja otiska prsta otkazana je."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Radnju s otiskom prsta otkazao je korisnik."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Senzor otiska prsta onemogućen je zbog previše pokušaja."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Pokušajte ponovo."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nije registriran nijedan otisak prsta."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ovaj uređaj nema senzor otiska prsta."</string>
@@ -1250,10 +1251,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Pripremanje aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Pokretanje aplikacija."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Završetak inicijalizacije."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Želite li nastaviti s postavljanjem?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Pritisnuli ste tipku za uključivanje/isključivanje, čime se obično isključuje zaslon.\n\nPokušajte lagano dodirnuti dok postavljate svoj otisak prsta."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Isključi zaslon"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Nastavi postavljanje"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Dodirnite da biste isključili zaslon"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Isključi zaslon"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Nastaviti s potvrđivanjem otiska prsta?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Pritisnuli ste tipku za uključivanje/isključivanje, čime se obično isključuje zaslon.\n\nPokušajte lagano dodirnuti da biste potvrdili svoj otisak prsta."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Isključi zaslon"</string>
@@ -1406,16 +1406,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Dodirnite za postavljanje"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Odaberite da biste postavili"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Možda ćete morati ponovo formatirati uređaj. Dodirnite za izbacivanje."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Za prijenos fotografija i medija"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Za pohranu fotografija, videozapisa, glazbe i drugih sadržaja"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Pregledajte datoteke na medijima"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Poteškoća s medijem <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ne radi"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Dodirnite za popravak"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Medij je oštećen (<xliff:g id="NAME">%s</xliff:g>). Odaberite da biste ispravili pogrešku."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Možda ćete morati ponovo formatirati uređaj. Dodirnite za izbacivanje."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Nepodržani medij za pohranu <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Otkriven je uređaj <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ne radi"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Uređaj ne podržava ovaj medij (<xliff:g id="NAME">%s</xliff:g>). Dodirnite da biste ga postavili u podržanom formatu."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Dodirnite da biste postavili ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Odaberite da biste postavili medij <xliff:g id="NAME">%s</xliff:g> u podržanom formatu."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Možda ćete morati ponovo formatirati uređaj"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Uređaj <xliff:g id="NAME">%s</xliff:g> iznenada je uklonjen"</string>
@@ -1928,6 +1928,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Postavke regije"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Unesite naziv jezika"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Predloženo"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Predloženo"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Svi jezici"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Sve regije"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Pretraži"</string>
@@ -2050,7 +2051,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Želite li dopustiti aplikaciji <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> da pristupa svim zapisnicima uređaja?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Omogući jednokratni pristup"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Nemoj dopustiti"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"U zapisnicima uređaja bilježi se što se događa na uređaju. Aplikacije mogu koristiti te zapisnike kako bi pronašle i riješile poteškoće.\n\nNeki zapisnici mogu sadržavati osjetljive podatke, pa pristup svim zapisnicima uređaja odobrite samo pouzdanim aplikacijama. \n\nAko ne dopustite ovoj aplikaciji da pristupa svim zapisnicima uređaja, ona i dalje može pristupati svojim zapisnicima. Proizvođač vašeg uređaja i dalje može pristupati nekim zapisnicima ili podacima na vašem uređaju. Saznajte više"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"U zapisnicima uređaja bilježi se što se događa na uređaju. Aplikacije mogu koristiti te zapisnike kako bi pronašle i riješile poteškoće.\n\nNeki zapisnici mogu sadržavati osjetljive podatke, pa pristup svim zapisnicima uređaja odobrite samo pouzdanim aplikacijama. \n\nAko ne dopustite ovoj aplikaciji da pristupa svim zapisnicima uređaja, ona i dalje može pristupati svojim zapisnicima. Proizvođač vašeg uređaja i dalje može pristupati nekim zapisnicima ili podacima na vašem uređaju."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ne prikazuj ponovo"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> želi prikazivati isječke aplikacije <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Uredi"</string>
@@ -2291,5 +2292,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Provjera aktivnih aplikacija"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"S vašeg uređaja <xliff:g id="DEVICE">%1$s</xliff:g> nije moguće pristupiti fotoaparatu telefona"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"S vašeg uređaja <xliff:g id="DEVICE">%1$s</xliff:g> nije moguće pristupiti fotoaparatu tableta"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Sadržaju nije moguće pristupiti tijekom streaminga. Pokušajte mu pristupiti na telefonu."</string>
<string name="system_locale_title" msgid="711882686834677268">"Zadane postavke sustava"</string>
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d0baae0..f92b1d7 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Ujjlenyomattal kapcsolatos művelet megszakítva"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Az ujjlenyomattal kapcsolatos műveletet a felhasználó megszakította."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Túl sok próbálkozás. Próbálja újra később."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Túl sok próbálkozás. Ujjlenyomat-érzékelő letiltva."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Próbálkozzon újra."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nincsenek regisztrált ujjlenyomatok."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ez az eszköz nem rendelkezik ujjlenyomat-érzékelővel."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> előkészítése."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Kezdő alkalmazások."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Rendszerindítás befejezése."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Folytatja a beállítást?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Megnyomta a bekapcsológombot — ezzel általában kikapcsol a képernyő.\n\nPróbáljon finoman rákoppintani az ujjlenyomat beállítása közben."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Kikapcsolom"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Beállítás folytatása"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Koppintson a képernyő kikapcsolásához"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Képernyő kikapcsolása"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Folytatja az ujjlenyomat ellenőrzését?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Megnyomta a bekapcsológombot — ezzel általában kikapcsol a képernyő.\n\nPróbáljon finoman rákoppintani az ujjlenyomat ellenőrzéséhez."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Kikapcsolom"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Koppintson ide a beállításhoz"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Válassza ki a beállításhoz"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Előfordulhat, hogy újra kell formáznia az eszközt. Koppintson az eltávolításhoz."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Fotók és más tartalmak átviteléhez"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Fotók, videók, zene és egyéb tárolására"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Médiafájlok böngészése"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Probléma a következővel: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"A(z) <xliff:g id="NAME">%s</xliff:g> nem működik"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Koppintson a javításhoz"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"A(z) <xliff:g id="NAME">%s</xliff:g> sérült. Válassza ki a javításhoz."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Előfordulhat, hogy újra kell formáznia az eszközt. Koppintson az eltávolításhoz."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Nem támogatott <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> felismerve"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"A(z) <xliff:g id="NAME">%s</xliff:g> nem működik"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Ez az eszköz nem támogatja ezt a(z) <xliff:g id="NAME">%s</xliff:g> eszközt. Koppintson rá a támogatott formátumban való beállításhoz."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Koppintson ide a beállításhoz ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Válassza ki a(z) <xliff:g id="NAME">%s</xliff:g> támogatott formátumban történő beállításához."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Előfordulhat, hogy újra kell formáznia az eszközt"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"A(z) <xliff:g id="NAME">%s</xliff:g> váratlanul eltávolítva"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Régió beállítása"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Adja meg a nyelvet"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Javasolt"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Javasolt"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Minden nyelv"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Minden régió"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Keresés"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Engedélyezi a(z) <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> számára, hogy hozzáférjen az összes eszköznaplóhoz?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Egyszeri hozzáférés engedélyezése"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Tiltás"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Az eszköznaplók rögzítik, hogy mi történik az eszközén. Az alkalmazások ezeket a naplókat használhatják a problémák megkeresésére és kijavítására.\n\nBizonyos naplók érzékeny adatokat is tartalmazhatnak, ezért csak olyan alkalmazások számára engedélyezze az összes eszköznaplóhoz való hozzáférést, amelyekben megbízik. \n\nHa nem engedélyezi ennek az alkalmazásnak, hogy hozzáférjen az összes eszköznaplójához, az app továbbra is hozzáférhet a saját naplóihoz. Előfordulhat, hogy az eszköz gyártója továbbra is hozzáfér az eszközön található bizonyos naplókhoz és adatokhoz. További információ."</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Az eszköznaplók rögzítik, hogy mi történik az eszközén. Az alkalmazások ezeket a naplókat használhatják a problémák megkeresésére és kijavítására.\n\nBizonyos naplók bizalmas adatokat is tartalmazhatnak, ezért csak olyan alkalmazások számára engedélyezze az összes eszköznaplóhoz való hozzáférést, amelyekben megbízik. \n\nHa nem engedélyezi ennek az alkalmazásnak, hogy hozzáférjen az összes eszköznaplójához, az app továbbra is hozzáférhet a saját naplóihoz. Előfordulhat, hogy az eszköz gyártója továbbra is hozzáfér az eszközön található bizonyos naplókhoz és adatokhoz."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ne jelenjen meg újra"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"A(z) <xliff:g id="APP_0">%1$s</xliff:g> alkalmazás részleteket szeretne megjeleníteni a(z) <xliff:g id="APP_2">%2$s</xliff:g> alkalmazásból"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Szerkesztés"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Aktív alkalmazások ellenőrzése"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nem lehet hozzáférni a telefon kamerájához a következő eszközön: <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Nem lehet hozzáférni a táblagép kamerájához a következő eszközön: <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Ehhez a tartalomhoz nem lehet hozzáférni streamelés közben. Próbálja újra a telefonján."</string>
<string name="system_locale_title" msgid="711882686834677268">"Rendszerbeállítás"</string>
</resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index e262dbd..1e4900c 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Իսկորոշումը մատնահետքի միջոցով չեղարկվեց:"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Մատնահետքով նույնականացման գործողությունը չեղարկվել է օգտատիրոջ կողմից:"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Չափից շատ փորձ եք կատարել: Փորձեք նորից քիչ հետո:"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Չափից շատ փորձ եք կատարել: Մատնահետքերի սկաներն անջատվել է:"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Փորձեք նորից:"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Գրանցված մատնահետք չկա:"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Այս սարքը չունի մատնահետքերի սկաներ։"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> հավելվածը պատրաստվում է:"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Հավելվածները մեկնարկում են:"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Բեռնումն ավարտվում է:"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Շարունակե՞լ կարգավորումը"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Դուք սեղմել եք սնուցման կոճակը։ Սովորաբար դրա արդյունքում էկրանն անջատվում է։\n\nՄատնահետքը ավելացնելու համար թեթևակի հպեք կոճակին։"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Անջատել էկրանը"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Շարունակել գրանցումը"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Հպեք՝ էկրանն անջատելու համար"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Անջատել էկրանը"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Շարունակե՞լ մատնահետքի սկանավորումը"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Դուք սեղմել եք սնուցման կոճակը։ Սովորաբար դրա արդյունքում էկրանն անջատվում է։\n\nՄատնահետքը սկանավորելու համար թեթևակի հպեք կոճակին։"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Անջատել էկրանը"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Հպեք՝ կարգավորելու համար"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Ընտրեք՝ կարգավորելու համար"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Կարող է պահանջվել, որ նորից ֆորմատավորեք սարքը։ Հպեք՝ հեռացնելու համար։"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Լուսանկարներ և մեդիա ֆայլեր տեղափոխելու համար"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Լուսանկարներ, տեսանյութեր, երգեր և այլ բովանդակություն պահելու համար"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Մեդիա ֆայլերի դիտում"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> հիշասարքի հետ կապված խնդիր կա"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g>ը չի աշխատում"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Հպեք՝ շտկելու համար"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g>-ը վնասված է: Ընտրեք՝ շտկելու համար:"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Կարող է պահանջվել, որ նորից ֆորմատավորեք սարքը։ Հպեք՝ հեռացնելու համար։"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Չապահովվող <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Հայտնաբերվել է <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g>ը չի աշխատում"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Այս սարքը չի աջակցում այս <xliff:g id="NAME">%s</xliff:g>-ը: Հպեք՝ աջակցվող ձևաչափով կարգավորելու համար:"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Հպեք կարգավորելու համար։"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Ընտրեք՝ կրիչը (<xliff:g id="NAME">%s</xliff:g>) աջակցվող ձևաչափով կարգավորելու համար։"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Կարող է պահանջվել, որ նորից ֆորմատավորեք սարքը"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>-ը հեռացվել է առանց անջատելու"</string>
@@ -1424,7 +1424,7 @@
<string name="ext_media_unmounting_notification_title" msgid="4147986383917892162">"<xliff:g id="NAME">%s</xliff:g> հիշասարքն անջատվում է"</string>
<string name="ext_media_unmounting_notification_message" msgid="5717036261538754203">"Չհեռացնեք սարքը"</string>
<string name="ext_media_init_action" msgid="2312974060585056709">"Կարգավորել"</string>
- <string name="ext_media_unmount_action" msgid="966992232088442745">"Անջատել"</string>
+ <string name="ext_media_unmount_action" msgid="966992232088442745">"Հանել"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"Ուսումնասիրել"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Աուդիոելքի սարքի փոխարկում"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g>-ը տեղադրված չէ"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Նախընտրելի տարածաշրջան"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Մուտքագրեք լեզուն"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Առաջարկվող"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Առաջարկվող"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Բոլոր լեզուները"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Բոլոր տարածաշրջանները"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Որոնում"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Հասանելի դարձնե՞լ <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> հավելվածին սարքի բոլոր մատյանները"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Թույլատրել մեկանգամյա մուտքը"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Չթույլատրել"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Այն, ինչ տեղի է ունենում ձեր սարքում, գրանցվում է սարքի մատյաններում։ Հավելվածները կարող են դրանք օգտագործել անսարքությունները հայտնաբերելու և վերացնելու նպատակով։\n\nՔանի որ որոշ մատյաններ անձնական տեղեկություններ են պարունակում, խորհուրդ ենք տալիս հասանելի դարձնել ձեր սարքի բոլոր մատյանները միայն այն հավելվածներին, որոնց վստահում եք։ \n\nԵթե այս հավելվածին նման թույլտվություն չեք տվել, դրան նախկինի պես հասանելի կլինեն իր մատյանները։ Հնարավոր է՝ ձեր սարքի արտադրողին ևս հասանելի լինեն սարքի որոշ մատյաններ և տեղեկություններ։ Իմանալ ավելին"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Այն, ինչ տեղի է ունենում ձեր սարքում, գրանցվում է սարքի մատյաններում։ Հավելվածները կարող են դրանք օգտագործել անսարքությունները հայտնաբերելու և վերացնելու նպատակով։\n\nՔանի որ որոշ մատյաններ անձնական տեղեկություններ են պարունակում, խորհուրդ ենք տալիս հասանելի դարձնել ձեր սարքի բոլոր մատյանները միայն այն հավելվածներին, որոնց վստահում եք։ \n\nԵթե այս հավելվածին նման թույլտվություն չեք տվել, դրան նախկինի պես հասանելի կլինեն իր մատյանները։ Հնարավոր է՝ ձեր սարքի արտադրողին ևս հասանելի լինեն սարքի որոշ մատյաններ և տեղեկություններ։"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Այլևս ցույց չտալ"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> հավելվածն ուզում է ցուցադրել հատվածներ <xliff:g id="APP_2">%2$s</xliff:g> հավելվածից"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Փոփոխել"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Ստուգել ակտիվ հավելվածները"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Հնարավոր չէ օգտագործել հեռախոսի տեսախցիկը ձեր <xliff:g id="DEVICE">%1$s</xliff:g> սարքից"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Հնարավոր չէ օգտագործել պլանշետի տեսախցիկը ձեր <xliff:g id="DEVICE">%1$s</xliff:g> սարքից"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Այս բովանդակությունը հասանելի չէ հեռարձակման ընթացքում։ Օգտագործեք ձեր հեռախոսը։"</string>
<string name="system_locale_title" msgid="711882686834677268">"Կանխադրված"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 11bb2b1..1a7ecf1 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operasi sidik jari dibatalkan."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operasi sidik jari dibatalkan oleh pengguna."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Terlalu banyak upaya. Coba lagi nanti."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Terlalu sering dicoba. Sensor sidik jari dinonaktifkan."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Coba lagi."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Tidak ada sidik jari yang terdaftar."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Perangkat ini tidak memiliki sensor sidik jari."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Menyiapkan <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Memulai aplikasi."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Menyelesaikan boot."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Lanjutkan penyiapan?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Anda menekan tombol daya; tindakan ini biasanya akan menonaktifkan layar.\n\nCoba ketuk lembut saat menyiapkan sidik jari Anda."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Nonaktifkan layar"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Lanjutkan penyiapan"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Ketuk untuk menonaktifkan layar"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Nonaktifkan layar"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Lanjutkan verifikasi sidik jari?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Anda menekan tombol daya; tindakan ini biasanya akan menonaktifkan layar.\n\nCoba ketuk lembut untuk memverifikasi sidik jari Anda."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Nonaktifkan layar"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Ketuk untuk menyiapkan"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Pilih untuk menyiapkan"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Anda mungkin perlu memformat ulang perangkat. Ketuk untuk mengeluarkan"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Untuk mentransfer foto dan media"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Untuk menyimpan foto, video, musik, dan lainnya"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Jelajahi file media"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Masalah pada <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> tidak berfungsi"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Ketuk untuk memperbaiki"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> rusak. Pilih untuk memperbaikinya."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Anda mungkin perlu memformat ulang perangkat. Ketuk untuk mengeluarkan"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> tidak didukung"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> terdeteksi"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> tidak berfungsi"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Perangkat tidak mendukung <xliff:g id="NAME">%s</xliff:g> ini. Ketuk untuk menyiapkan dalam format yang didukung."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Ketuk untuk menyiapkan ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Pilih untuk menyiapkan <xliff:g id="NAME">%s</xliff:g> dalam format yang didukung."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Anda mungkin perlu memformat ulang perangkat"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> tiba-tiba dicabut"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Preferensi wilayah"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Ketik nama bahasa"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Disarankan"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Disarankan"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Semua bahasa"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Semua wilayah"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Telusuri"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Izinkan <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> mengakses semua log perangkat?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Izinkan akses satu kali"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Jangan izinkan"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Log perangkat merekam hal-hal yang terjadi di perangkat Anda. Aplikasi dapat menggunakan log ini untuk menemukan dan memperbaiki masalah.\n\nBeberapa log mungkin berisi info sensitif, jadi hanya izinkan aplikasi yang Anda percayai untuk mengakses semua log perangkat. \n\nJika Anda tidak mengizinkan aplikasi ini mengakses semua log perangkat, aplikasi masih dapat mengakses log-nya sendiri. Produsen perangkat masih dapat mengakses beberapa log atau info di perangkat Anda. Pelajari lebih lanjut"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Log perangkat merekam hal-hal yang terjadi di perangkat Anda. Aplikasi dapat menggunakan log ini untuk menemukan dan memperbaiki masalah.\n\nBeberapa log mungkin berisi info sensitif, jadi hanya izinkan aplikasi yang Anda percayai untuk mengakses semua log perangkat. \n\nJika Anda tidak mengizinkan aplikasi ini mengakses semua log perangkat, aplikasi masih dapat mengakses log-nya sendiri. Produsen perangkat masih dapat mengakses beberapa log atau info di perangkat Anda."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Jangan tampilkan lagi"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> ingin menampilkan potongan <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Edit"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Periksa aplikasi aktif"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Tidak dapat mengakses kamera ponsel dari <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Tidak dapat mengakses kamera tablet dari <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Konten ini tidak dapat diakses saat melakukan streaming. Coba di ponsel."</string>
<string name="system_locale_title" msgid="711882686834677268">"Default sistem"</string>
</resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 4e384c8..24720ef 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Hætt við fingrafarsaðgerð."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Notandi hætti við að nota fingrafar."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Of margar tilraunir. Reyndu aftur síðar."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Of margar tilraunir. Fingrafaralesari gerður óvirkur."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Reyndu aftur."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Engin fingraför hafa verið skráð."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Þetta tæki er ekki með fingrafaralesara."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Undirbýr <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Ræsir forrit."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Lýkur ræsingu."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Halda uppsetningu áfram?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Þú ýttir á aflrofann. Yfirleitt slekkur það á skjánum.\n\nPrófaðu að ýta laust þegar þú setur upp fingrafarið."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Slökkva á skjá"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Halda uppsetningu áfram"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Ýttu til að slökkva á skjá"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Slökkva á skjá"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Halda áfram að staðfesta fingrafarið?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Þú ýttir á aflrofann. Yfirleitt slekkur það á skjánum.\n\nPrófaðu að ýta laust til að staðfesta fingrafarið þitt."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Slökkva á skjá"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Ýttu til að setja upp"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Veldu til að setja upp"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Þú gætir þurft að endursníða tækið. Ýttu til að fjarlægja."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Til að flytja myndir og aðrar skrár"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Til að geyma myndir, myndskeið, tónlist og fleira"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Skoða efnisskrár"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Vandamál með <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> virkar ekki"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Ýttu til að lagfæra"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> er skemmt. Veldu til að lagfæra."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Þú gætir þurft að endursníða tækið. Ýttu til að fjarlægja."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Óstutt <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> greindist"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> virkar ekki"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Þetta tæki styður ekki <xliff:g id="NAME">%s</xliff:g>. Ýttu til að setja upp með studdu sniði."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Ýttu til að setja upp ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Veldu til að setja <xliff:g id="NAME">%s</xliff:g> upp á studdu sniði."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Þú gætir þurft að endursníða tækið"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> fjarlægt án fyrirvara"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Svæðisval"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Sláðu inn heiti tungumáls"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Tillögur"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Tillögur"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Öll tungumál"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Öll svæði"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Leita"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Veita <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> aðgang að öllum annálum í tækinu?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Leyfa aðgang í eitt skipti"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Ekki leyfa"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Annálar tækisins skrá það sem gerist í tækinu. Forrit geta notað þessa annála til að finna og lagfæra vandamál.\n\nTilteknir annálar innihalda viðkvæmar upplýsingar og því skaltu einungis veita forritum sem þú treystir aðgang að öllum annálum tækisins. \n\nEf þú veitir þessu forriti ekki aðgang að öllum annálum tækisins hefur það áfram aðgang að eigin annálum. Framleiðandi tækisins getur þó hugsanlega opnað tiltekna annála eða upplýsingar í tækinu. Nánar"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Annálar tækisins skrá það sem gerist í tækinu. Forrit geta notað þessa annála til að finna og lagfæra vandamál.\n\nTilteknir annálar innihalda viðkvæmar upplýsingar og því skaltu einungis veita forritum sem þú treystir aðgang að öllum annálum tækisins. \n\nEf þú veitir þessu forriti ekki aðgang að öllum annálum tækisins hefur það áfram aðgang að eigin annálum. Framleiðandi tækisins getur þó hugsanlega opnað tiltekna annála eða upplýsingar í tækinu."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ekki sýna aftur"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> vill sýna sneiðar úr <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Breyta"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Skoða virk forrit"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Ekki er hægt að opna myndavél símans úr <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Ekki er hægt að opna myndavél spjaldtölvunnar úr <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Ekki er hægt að opna þetta á meðan streymi stendur yfir. Prófaðu það í símanum í staðinn."</string>
<string name="system_locale_title" msgid="711882686834677268">"Sjálfgildi kerfis"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index f313f86..841d07d 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operazione associata all\'impronta annullata."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operazione di autenticazione dell\'impronta annullata dall\'utente."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Troppi tentativi. Riprova più tardi."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Troppi tentativi. Sensore di impronte disattivato."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Riprova."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nessuna impronta digitale registrata."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Questo dispositivo non dispone di sensore di impronte."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> in preparazione."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Avvio app."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Conclusione dell\'avvio."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Vuoi continuare la configurazione?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Hai premuto il tasto di accensione; in genere questa azione disattiva lo schermo.\n\nProva a toccare leggermente il tasto di accensione durante la configurazione della tua impronta."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Disattiva lo schermo"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Continua configuraz."</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tocca per disattivare lo schermo"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Disattiva lo schermo"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Vuoi continuare a verificare l\'impronta?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Hai premuto il tasto di accensione; in genere questa azione disattiva lo schermo.\n\nProva a toccare leggermente il tasto di accensione per verificare la tua impronta."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Disattiva lo schermo"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Tocca per configurare"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Seleziona per configurare"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Potresti dover riformattare il dispositivo. Tocca per espellere."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Per trasferire foto e altri file"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Per archiviare foto, video, musica e altro ancora"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Sfoglia i file multimediali"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problema con <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> non funziona"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Tocca per risolvere il problema"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Il supporto esterno <xliff:g id="NAME">%s</xliff:g> è danneggiato. Seleziona per risolvere il problema."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Potresti dover riformattare il dispositivo. Tocca per espellere."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> non supportata"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> rilevata"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> non funziona"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Il dispositivo non supporta il seguente elemento: <xliff:g id="NAME">%s</xliff:g>. Tocca per configurare un formato supportato."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Tocca per configurare"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Seleziona per configurare <xliff:g id="NAME">%s</xliff:g> in un formato supportato."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Potresti dover riformattare il dispositivo"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Rimozione imprevista della <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Regione preferita"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Digita nome lingua"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Suggerite"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Suggerite"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Tutte le lingue"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Tutte le regioni"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Cerca"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Consentire all\'app <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> di accedere a tutti i log del dispositivo?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Consenti accesso una tantum"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Non consentire"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"I log del dispositivo registrano tutto ciò che succede sul tuo dispositivo. Le app possono usare questi log per individuare problemi e correggerli.\n\nAlcuni log potrebbero contenere informazioni sensibili, quindi concedi l\'accesso a tutti i log del dispositivo soltanto alle app attendibili. \n\nSe le neghi l\'accesso a tutti i log del dispositivo, questa app può comunque accedere ai propri log. Il produttore del tuo dispositivo potrebbe essere comunque in grado di accedere ad alcuni log o informazioni sul dispositivo. Scopri di più"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"I log del dispositivo registrano tutto ciò che succede sul tuo dispositivo. Le app possono usare questi log per individuare problemi e correggerli.\n\nAlcuni log potrebbero contenere informazioni sensibili, quindi concedi l\'accesso a tutti i log del dispositivo soltanto alle app attendibili. \n\nSe le neghi l\'accesso a tutti i log del dispositivo, questa app può comunque accedere ai propri log. Il produttore del tuo dispositivo potrebbe essere comunque in grado di accedere ad alcuni log o informazioni sul dispositivo."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Non mostrare più"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"L\'app <xliff:g id="APP_0">%1$s</xliff:g> vuole mostrare porzioni dell\'app <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Modifica"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Verifica le app attive"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Impossibile accedere alla fotocamera del telefono dal tuo <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Impossibile accedere alla fotocamera del tablet dal tuo <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Impossibile accedere a questi contenuti durante lo streaming. Prova a usare il telefono."</string>
<string name="system_locale_title" msgid="711882686834677268">"Predefinita di sistema"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 246bc91..b827841 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -610,7 +610,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"פעולת טביעת האצבע בוטלה."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"פעולת טביעת האצבע בוטלה על ידי המשתמש."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"יותר מדי ניסיונות. יש לנסות שוב מאוחר יותר."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"יותר מדי ניסיונות. חיישן טביעות האצבע הושבת."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"כדאי לנסות שוב."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"לא נסרקו טביעות אצבע."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"במכשיר הזה אין חיישן טביעות אצבע."</string>
@@ -1251,10 +1252,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"המערכת מכינה את <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"מתבצעת הפעלה של אפליקציות."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"תהליך האתחול בשלבי סיום."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"להמשיך בהגדרה?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"לחצת על לחצן ההפעלה – בדרך כלל הפעולה הזו מכבה את המסך.\n\nעליך לנסות להקיש בעדינות במהלך ההגדרה של טביעת האצבע שלך."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"כיבוי המסך"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"להמשך ההגדרה"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"יש להקיש כדי לכבות את המסך"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"כיבוי המסך"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"להמשיך לאמת את טביעת האצבע שלך?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"לחצת על לחצן ההפעלה – בדרך כלל הפעולה הזו מכבה את המסך.\n\nעליך לנסות להקיש בעדינות כדי לאמת את טביעת האצבע שלך."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"כיבוי המסך"</string>
@@ -1407,16 +1407,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"צריך להקיש כדי להגדיר"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"יש לבחור כדי להגדיר"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"ייתכן שיהיה צורך לפרמט מחדש את המכשיר. יש להקיש כדי להוציא את המדיה."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"להעברת תמונות ומדיה"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"לאחסון של תמונות, סרטונים, מוזיקה ועוד"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"עיון בקובצי המדיה"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"בעיה עם <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"המדיה <xliff:g id="NAME">%s</xliff:g> לא פועלת"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"יש להקיש כדי לפתור את הבעיה"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> פגום. יש ללחוץ כדי לפתור את הבעיה."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"ייתכן שיהיה צורך לפרמט מחדש את המכשיר. יש להקיש כדי להוציא את המדיה."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> לא נתמך"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"בוצע זיהוי של <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"המדיה <xliff:g id="NAME">%s</xliff:g> לא פועלת"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"אין תמיכה ב-<xliff:g id="NAME">%s</xliff:g> במכשיר הזה. יש להקיש כדי לבצע הגדרה בפורמט נתמך."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"יש להקיש כדי להגדיר"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"יש לבחור כדי להגדיר את <xliff:g id="NAME">%s</xliff:g> בפורמט נתמך."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"ייתכן שיהיה צורך לפרמט מחדש את המכשיר"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> הוסר באופן בלתי צפוי"</string>
@@ -1929,6 +1929,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"העדפת אזור"</string>
<string name="search_language_hint" msgid="7004225294308793583">"יש להקליד את שם השפה"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"הצעות"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"הצעות"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"כל השפות"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"כל האזורים"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"חיפוש"</string>
@@ -2051,7 +2052,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"לתת לאפליקציה <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> הרשאת גישה לכל יומני המכשיר?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"הרשאת גישה חד-פעמית"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"אין אישור"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"ביומני המכשיר מתועדת הפעילות במכשיר. האפליקציות יכולות להשתמש ביומנים האלה כדי למצוא בעיות ולפתור אותן.\n\nהמידע בחלק מהיומנים יכול להיות רגיש, לכן יש לתת הרשאת גישה לכל יומני המכשיר רק לאפליקציות מהימנות. \n\nגם אם האפליקציה הזו לא תקבל הרשאת גישה לכל יומני המכשיר, היא תוכל לגשת ליומנים שלה. יכול להיות שליצרן המכשיר עדיין תהיה גישה לחלק מהיומנים או למידע במכשיר שלך. מידע נוסף"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"ביומני המכשיר מתועדת הפעילות במכשיר. האפליקציות יכולות להשתמש ביומנים האלה כדי למצוא בעיות ולפתור אותן.\n\nהמידע בחלק מהיומנים יכול להיות רגיש, לכן יש לתת הרשאת גישה לכל יומני המכשיר רק לאפליקציות מהימנות. \n\nגם אם האפליקציה הזו לא תקבל הרשאת גישה לכל יומני המכשיר, היא תוכל לגשת ליומנים שלה. יכול להיות שליצרן המכשיר עדיין תהיה גישה לחלק מהיומנים או למידע במכשיר שלך."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"אין להציג שוב"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> רוצה להציג חלקים מ-<xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"עריכה"</string>
@@ -2292,5 +2293,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"כדאי לבדוק את האפליקציות הפעילות"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"לא ניתן לגשת למצלמה של הטלפון מה‑<xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"לא ניתן לגשת למצלמה של הטאבלט מה‑<xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"אי אפשר לגשת לתוכן המאובטח הזה בזמן סטרימינג. במקום זאת, יש לנסות בטלפון."</string>
<string name="system_locale_title" msgid="711882686834677268">"ברירת המחדל של המערכת"</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 13ae3b7..9b651e2 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -289,7 +289,7 @@
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"電池を消費しているアプリ"</string>
<string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"拡大"</string>
<string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"ユーザー補助の使用"</string>
- <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」が電池を使用しています"</string>
+ <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」がバッテリーを使用しています"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個のアプリが電池を使用しています"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"タップしてバッテリーやデータの使用量を確認"</string>
<string name="foreground_service_multiple_separator" msgid="5002287361849863168">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>、<xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"指紋の操作をキャンセルしました。"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"指紋の操作がユーザーによりキャンセルされました。"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"所定の回数以上間違えました。しばらくしてからもう一度お試しください。"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"試行回数が上限を超えました。指紋認証センサーを無効にしました。"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"もう一度お試しください。"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"指紋が登録されていません。"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"このデバイスには指紋認証センサーがありません。"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>をペア設定しています。"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"アプリを起動しています。"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"ブートを終了しています。"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"設定を続行しますか?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"電源ボタンを押しました。通常、この操作で画面が OFF になります。\n\n指紋を設定する場合は電源ボタンに軽く触れてみましょう。"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"画面を OFF にする"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"設定を続行"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"タップして画面を OFF にする"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"画面を OFF にする"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"指紋の確認を続行しますか?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"電源ボタンを押しました。通常、この操作で画面が OFF になります。\n\n指紋を確認するには、電源ボタンに軽く触れてみましょう。"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"画面を OFF にする"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"タップして設定してください"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"選択してセットアップしてください"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"デバイスの再フォーマットが必要になる場合があります。取り出すにはタップしてください。"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"写真などのメディア転送用"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"写真、動画、音楽などを保存できます"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"メディア ファイルをブラウジングできます"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g>に関する問題"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g>は動作していません"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"タップして修正してください"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g>が破損しています。修正するには選択してください。"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"デバイスの再フォーマットが必要になる場合があります。取り出すにはタップしてください。"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"対応していない<xliff:g id="NAME">%s</xliff:g>です"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g>検出"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g>は動作していません"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"このデバイスはこの <xliff:g id="NAME">%s</xliff:g>に対応していません。タップして、対応している形式でセットアップしてください。"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"タップしてセットアップしてください。"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"<xliff:g id="NAME">%s</xliff:g>を選択して、対応している形式でセットアップしてください。"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"デバイスの再フォーマットが必要になる場合があります"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>が不適切に取り外されました"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"地域設定"</string>
<string name="search_language_hint" msgid="7004225294308793583">"言語名を入力"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"言語の候補"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"候補"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"すべての言語"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"すべての地域"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"検索"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> にすべてのデバイスログへのアクセスを許可しますか?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"1 回限りのアクセスを許可"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"許可しない"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"デバイスのログに、このデバイスで発生したことが記録されます。アプリは問題を検出、修正するためにこれらのログを使用することができます。\n\nログによっては機密性の高い情報が含まれている可能性があるため、すべてのデバイスログへのアクセスは信頼できるアプリにのみ許可してください。\n\nすべてのデバイスログへのアクセスを許可しなかった場合でも、このアプリはアプリ独自のログにアクセスできます。また、デバイスの製造メーカーもデバイスの一部のログや情報にアクセスできる可能性があります。詳細"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"デバイスのログに、このデバイスで発生したことが記録されます。アプリは問題を検出、修正するためにこれらのログを使用することができます。\n\nログによっては機密性の高い情報が含まれている可能性があるため、すべてのデバイスログへのアクセスは信頼できるアプリにのみ許可してください。\n\nすべてのデバイスログへのアクセスを許可しなかった場合も、このアプリはアプリ独自のログにアクセスできます。また、デバイスのメーカーもデバイスの一部のログや情報にアクセスできる可能性があります。"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"次回から表示しない"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"「<xliff:g id="APP_0">%1$s</xliff:g>」が「<xliff:g id="APP_2">%2$s</xliff:g>」のスライスの表示をリクエストしています"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"編集"</string>
@@ -2285,10 +2286,11 @@
<string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"バックグラウンド アクティビティ"</string>
<string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"アプリがバッテリーを消費しています"</string>
<string name="notification_title_long_running_fgs" msgid="8170284286477131587">"アプリがまだアクティブです"</string>
- <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> がバックグラウンドで実行されています。タップすると、バッテリー使用量を管理できます。"</string>
+ <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> がバックグラウンドで実行されています。タップすると、バッテリー使用状況を管理できます。"</string>
<string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> がバッテリー駆動時間に影響を与えている可能性があります。タップして、実行中のアプリをご確認ください。"</string>
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"実行中のアプリをチェック"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> からスマートフォンのカメラにアクセスできません"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"<xliff:g id="DEVICE">%1$s</xliff:g> からタブレットのカメラにアクセスできません"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"ストリーミング中はアクセスできません。スマートフォンでのアクセスをお試しください。"</string>
<string name="system_locale_title" msgid="711882686834677268">"システムのデフォルト"</string>
</resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index eb0e49f..1f18c90 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"თითის ანაბეჭდის აღების ოპერაცია გაუქმდა."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"თითის ანაბეჭდის ოპერაცია გააუქმა მომხმარებელმა."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"ძალიან ბევრი მცდელობა იყო. სცადეთ მოგვიანებით."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"დაფიქსირდა მეტისმეტად ბევრი მცდელობა. თითის ანაბეჭდის სენსორი გათიშულია."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ხელახლა სცადეთ"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"თითის ანაბეჭდები რეგისტრირებული არ არის."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ამ მოწყობილობას არ აქვს თითის ანაბეჭდის სენსორი."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"ემზადება <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"აპების ჩართვა"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"ჩატვირთვის დასასრული."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"გსურთ დაყენების გაგრძელება?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"თქვენ დააჭირეთ ჩართვის ღილაკს — ჩვეულებრივ, ის ეკრანს გამორთავს.\n\nთქვენი თითის ანაბეჭდის დაყენებისას ცადეთ მსუბუქად შეხება."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"ეკრანის გამორთვა"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"დაყენების გაგრძელება"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"შეეხეთ ეკრანის გამოსართავად"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ეკრანის გამორთვა"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"გსურთ ანაბეჭდის დადასტურების გაგრძელება?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"თქვენ დააჭირეთ ჩართვის ღილაკს — ჩვეულებრივ, ის ეკრანს გამორთავს.\n\nთქვენი თითის ანაბეჭდის დასადასტურებლად ცადეთ მსუბუქად შეხება."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ეკრანის გამორთვა"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"შეეხეთ დასაყენებლად"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"დასაყენებლად აირჩიეთ"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"შეიძლება მოწყობილობის რეფორმატირება დაგჭირდეთ. შეეხეთ ამოსაღებად."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ფოტოებისა და მედიის გადასატანად"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ფოტოების, ვიდეოების, მუსიკისა და ბევრი სხვა რამის შესანახად"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"მედიაფაილების დათვალიერება"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"პრობლემა <xliff:g id="NAME">%s</xliff:g>-თან მიმართებით"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> არ მუშაობს"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"შეეხეთ გამოსასწორებლად"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> დაზიანებულია. შეეხეთ გასასწორებლად."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"შეიძლება მოწყობილობის რეფორმატირება დაგჭირდეთ. შეეხეთ ამოსაღებად."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"მხარდაუჭერელი <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"აღმოჩენილია <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> არ მუშაობს"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ეს <xliff:g id="NAME">%s</xliff:g> მხარდაუჭერელია არ მოწყობილობაზე. შეეხეთ მხარდაჭერილ ფორმატში დასაყენებლად."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"შეეხეთ დასაყენებლად ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"აირჩიეთ, რათა დააყენოთ <xliff:g id="NAME">%s</xliff:g> მხარდაჭერილ ფორმატში."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"შეიძლება მოწყობილობის რეფორმატირება დაგჭირდეთ"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"მოულოდნელად მოხდა <xliff:g id="NAME">%s</xliff:g>-ის ამოღება"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"რეგიონის პარამეტრები"</string>
<string name="search_language_hint" msgid="7004225294308793583">"აკრიფეთ ენის სახელი"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"რეკომენდებული"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"რეკომენდებული"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"ყველა ენა"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"ყველა რეგიონი"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"ძიება"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"გსურთ <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>-ს მიანიჭოთ მოწყობილობის ყველა ჟურნალზე წვდომა?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"ერთჯერადი წვდომის დაშვება"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"არ დაიშვას"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"მოწყობილობის ჟურნალში იწერება, რა ხდება ამ მოწყობილობაზე. აპებს შეუძლია ამ ჟურნალების გამოყენება პრობლემების აღმოსაჩენად და მოსაგვარებლად.\n\nზოგი ჟურნალი შეიძლება სენსიტიური ინფორმაციის მატარებელი იყოს, ამიტომაც მოწყობილობის ყველა ჟურნალზე წვდომა მხოლოდ სანდო აპებს მიანიჭეთ. \n\nთუ ამ აპს მოწყობილობის ყველა ჟურნალზე წვდომას არ მიანიჭებთ, მას მაინც ექნება წვდომა საკუთარ ჟურნალებზე. თქვენი მოწყობილობის მწარმოებელს მაინც შეეძლება თქვენი მოწყობილობის ზოგიერთ ჟურნალსა თუ ინფორმაციაზე წვდომა. შეიტყვეთ მეტი"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"მოწყობილობის ჟურნალში იწერება, რა ხდება ამ მოწყობილობაზე. აპებს შეუძლია ამ ჟურნალების გამოყენება პრობლემების აღმოსაჩენად და მოსაგვარებლად.\n\nზოგი ჟურნალი შეიძლება სენსიტიური ინფორმაციის მატარებელი იყოს, ამიტომაც მოწყობილობის ყველა ჟურნალზე წვდომა მხოლოდ სანდო აპებს მიანიჭეთ. \n\nთუ ამ აპს მოწყობილობის ყველა ჟურნალზე წვდომას არ მიანიჭებთ, მას მაინც ექნება წვდომა თქვენს ჟურნალებზე. თქვენი მოწყობილობის მწარმოებელს მაინც შეეძლება თქვენი მოწყობილობის ზოგიერთ ჟურნალსა თუ ინფორმაციაზე წვდომა."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"აღარ გამოჩნდეს"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g>-ს სურს, გაჩვენოთ <xliff:g id="APP_2">%2$s</xliff:g>-ის ფრაგმენტები"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"რედაქტირება"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"აქტიური აპების შემოწმება"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"ტელეფონის კამერაზე წვდომა ვერ მოხერხდა თქვენი <xliff:g id="DEVICE">%1$s</xliff:g>-დან"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"ტაბლეტის კამერაზე წვდომა ვერ მოხერხდა თქვენი <xliff:g id="DEVICE">%1$s</xliff:g>-დან"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"მასზე წვდომის მიᲦება შეუძლებელია სტრიმინგის დროს. ცადეთ ტელეფონიდან."</string>
<string name="system_locale_title" msgid="711882686834677268">"სისტემის ნაგულისხმევი"</string>
</resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index db7baa4..1ba08e9 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Саусақ ізі операциясынан бас тартылған."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Пайдаланушы саусақ ізі операциясынан бас тартты."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Талпыныстар тым көп. Кейінірек қайталап көріңіз."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Тым көп әрекет жасалды. Саусақ ізін оқу сканері өшірілді."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Әрекетті қайталаңыз."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Саусақ іздері тіркелмеген."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Бұл құрылғыда саусақ ізін оқу сканері жоқ."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> дайындалуда."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Қолданбалар іске қосылуда."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Қосуды аяқтауда."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Реттеуді жалғастырасыз ба?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Қуат түймесін бастыңыз. Бұл әдетте экранды өшіреді.\n\nСаусақ ізін реттеу үшін, оны жайлап түртіп көріңіз."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Экранды өшіру"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Реттеуді жалғастыру"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Экранды өшіру үшін түртіңіз"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Экранды өшіру"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Саусақ ізін растауды жалғастырасыз ба?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Қуат түймесін бастыңыз. Бұл әдетте экранды өшіреді.\n\nСаусақ ізін растау үшін, оны жайлап түртіп көріңіз."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Экранды өшіру"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Реттеу үшін түртіңіз"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Реттеу үшін таңдаңыз."</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Құрылғыны қайта форматтау қажет болуы мүмкін. Шығару үшін түртіңіз."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Фотосуреттер мен медиа файлдарын тасымалдау үшін"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Фотосуреттерді, бейнелерді, музыка мен басқа мазмұнды сақтау үшін"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Медиа файлдарды таңдаңыз."</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> ақаулы"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> жұмыс істемейді"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Түзету үшін түртіңіз"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> бүлінген. Түзету үшін оны түртіңіз."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Құрылғыны қайта форматтау қажет болуы мүмкін. Шығару үшін түртіңіз."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Қолданылмайтын <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> анықталды"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> жұмыс істемейді"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Бұл құрылғы <xliff:g id="NAME">%s</xliff:g> картасына қолдау көрсетеді. Қолдау көрсетілетін пішімде орнату үшін түртіңіз."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Реттеу үшін түртіңіз."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"<xliff:g id="NAME">%s</xliff:g> құрылғысын қолдау көрсетілетін форматта реттеу үшін таңдаңыз."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Құрылғыны қайта форматтау қажет болуы мүмкін."</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> кенеттен шығарылды"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Аймақ параметрі"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Тіл атауын теріңіз"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Ұсынылған"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Ұсынылатын аймақтар"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Барлық тілдер"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Барлық аймақтар"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Іздеу"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> қолданбасына барлық құрылғының журналын пайдалануға рұқсат берілсін бе?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Бір реттік пайдалану рұқсатын беру"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Рұқсат бермеу"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Журналдарға құрылғыда не болып жатқаны жазылады. Қолданбалар осы журналдарды қате тауып, түзету үшін пайдаланады.\n\nКейбір журналдарда құпия ақпарат болуы мүмкін. Сондықтан барлық құрылғының журналын пайдалану рұқсаты тек сенімді қолданбаларға берілуі керек. \n\nБұл қолданбаға барлық құрылғының журналын пайдалануға рұқсат бермесеңіз де, ол өзінің журналдарын пайдалана береді. Құрылғы өндірушісі де құрылғыдағы кейбір журналдарды немесе ақпаратты пайдалануы мүмкін. Толығырақ"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Журналдарға құрылғыда не болып жатқаны жазылады. Қолданбалар осы журналдарды қате тауып, түзету үшін пайдаланады.\n\nКейбір журналдарда құпия ақпарат болуы мүмкін. Сондықтан барлық құрылғының журналын пайдалану рұқсаты тек сенімді қолданбаларға берілуі керек. \n\nБұл қолданбаға барлық құрылғының журналын пайдалануға рұқсат бермесеңіз де, ол өзінің журналдарын пайдалана береді. Құрылғы өндірушісі де құрылғыдағы кейбір журналдарды немесе ақпаратты пайдалануы мүмкін."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Қайта көрсетілмесін"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> қолданбасы <xliff:g id="APP_2">%2$s</xliff:g> қолданбасының үзінділерін көрсеткісі келеді"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Өзгерту"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Белсенді қолданбаларды тексеру"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> құрылғысынан телефон камерасын пайдалану мүмкін емес."</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"<xliff:g id="DEVICE">%1$s</xliff:g> құрылғысынан планшет камерасын пайдалану мүмкін емес."</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Трансляция кезінде мазмұнды көру мүмкін емес. Оның орнына телефоннан көріңіз."</string>
<string name="system_locale_title" msgid="711882686834677268">"Жүйенің әдепкі параметрі"</string>
</resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 458bceb..38fb1d0 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"បានបោះបង់ប្រតិបត្តិការស្នាមម្រាមដៃ។"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ប្រតិបត្តិការស្នាមម្រាមដៃត្រូវបានបោះបង់ដោយអ្នកប្រើប្រាស់។"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"ព្យាយាមចូលច្រើនពេកហើយ។ សូមព្យាយាមម្តងទៀតពេលក្រោយ។"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"ព្យាយាមចូលច្រើនដងពេកហើយ។ ឧបករណ៍ចាប់ស្នាមម្រាមដៃត្រូវបានបិទ។"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ព្យាយាមម្ដងទៀត។"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"មិនមានការចុះឈ្មោះស្នាមម្រាមដៃទេ។"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ឧបករណ៍នេះមិនមានឧបករណ៍ចាប់ស្នាមម្រាមដៃទេ។"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"កំពុងរៀបចំ <xliff:g id="APPNAME">%1$s</xliff:g>។"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ចាប់ផ្ដើមកម្មវិធី។"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"បញ្ចប់ការចាប់ផ្ដើម។"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"បន្តរៀបចំឬ?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"អ្នកបានចុចប៊ូតុងថាមពល — ជាធម្មតាការធ្វើបែបនេះនឹងបិទអេក្រង់។\n\nសាកល្បងចុចថ្នមៗ ខណៈពេលកំពុងរៀបចំស្នាមម្រាមដៃរបស់អ្នក។"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"បិទអេក្រង់"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"បន្តរៀបចំ"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ចុច ដើម្បីបិទអេក្រង់"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"បិទអេក្រង់"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"បន្តផ្ទៀងផ្ទាត់ស្នាមម្រាមដៃរបស់អ្នកឬ?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"អ្នកបានចុចប៊ូតុងថាមពល — ជាធម្មតាការធ្វើបែបនេះនឹងបិទអេក្រង់។\n\nសាកល្បងចុចថ្នមៗ ដើម្បីផ្ទៀងផ្ទាត់ស្នាមម្រាមដៃរបស់អ្នក។"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"បិទអេក្រង់"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"ចុចដើម្បីរៀបចំ"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"ជ្រើសរើសដើម្បីរៀបចំ"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"អ្នកប្រហែលជាត្រូវសម្អាតឧបករណ៍ឡើងវិញ។ សូមចុច ដើម្បីដកចេញ។"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"សម្រាប់ផ្ទេររូបភាព និងមេឌៀ"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"សម្រាប់រក្សាទុករូបថត វីដេអូ តន្ត្រី និងអ្វីៗជាច្រើនទៀត"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"រុករកឯកសារមេឌៀ"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"មានបញ្ហាជាមួយ <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> មិនដំណើរការទេ"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"ចុចដើម្បីកែបញ្ហា"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> ខូចហើយ។ សូមជ្រើសរើសដើម្បីជួសជុល។"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"អ្នកប្រហែលជាត្រូវសម្អាតឧបករណ៍ឡើងវិញ។ សូមចុច ដើម្បីដកចេញ។"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> មិនគាំទ្រ"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"បានរកឃើញ<xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> មិនដំណើរការទេ"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ឧបករណ៍នេះមិនគាំទ្រ <xliff:g id="NAME">%s</xliff:g> នេះទេ។ ប៉ះដើម្បីកំណត់ទម្រង់ដែលគាំទ្រ។"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"ចុចដើម្បីរៀបចំ។"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"ជ្រើសរើសដើម្បីរៀបចំ <xliff:g id="NAME">%s</xliff:g> ក្នុងទម្រង់ដែលអាចប្រើបាន។"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"អ្នកប្រហែលជាត្រូវសម្អាតឧបករណ៍ឡើងវិញ"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"បានដក <xliff:g id="NAME">%s</xliff:g> ចេញដោយមិនបានរំពឹងទុក"</string>
@@ -1427,7 +1427,7 @@
<string name="ext_media_unmount_action" msgid="966992232088442745">"ដកចេញ"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"រុករក"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"លទ្ធផល Switch"</string>
- <string name="ext_media_missing_title" msgid="3209472091220515046">"បាត់ <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_missing_title" msgid="3209472091220515046">"បាត់<xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_missing_message" msgid="4408988706227922909">"បញ្ចូលឧបករណ៍ម្តងទៀត"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"កំពុងផ្លាស់ទី <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"កំពុងផ្លាស់ទីទិន្នន័យ…"</string>
@@ -1567,7 +1567,7 @@
<string name="action_bar_home_description_format" msgid="5087107531331621803">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="4346835454749569826">"%1$s, %2$s, %3$s"</string>
<string name="storage_internal" msgid="8490227947584914460">"ទំហំផ្ទុករួមខាងក្នុង"</string>
- <string name="storage_sd_card" msgid="3404740277075331881">"កាតអេសឌី"</string>
+ <string name="storage_sd_card" msgid="3404740277075331881">"កាត SD"</string>
<string name="storage_sd_card_label" msgid="7526153141147470509">"កាត SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="448030813201444573">"ឧបករណ៍ផ្ទុក USB"</string>
<string name="storage_usb_drive_label" msgid="6631740655876540521">"ឧបករណ៍ផ្ទុក USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
@@ -1857,8 +1857,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ធ្វើបច្ចុប្បន្នភាពដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"លុបដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"យល់ព្រម"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"មុខងារសន្សំថ្មបើករចនាប័ទ្មងងឹត និងដាក់កំហិត ឬបិទសកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពលរូបភាពមួយចំនួន មុខងារជាក់លាក់ និងការតភ្ជាប់បណ្ដាញមួយចំនួន។"</string>
- <string name="battery_saver_description" msgid="8518809702138617167">"មុខងារសន្សំថ្មបើករចនាប័ទ្មងងឹត និងដាក់កំហិត ឬបិទសកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពលរូបភាពមួយចំនួន មុខងារជាក់លាក់ និងការតភ្ជាប់បណ្ដាញមួយចំនួន។"</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"មុខងារសន្សំថ្មបើកទម្រង់រចនាងងឹត និងដាក់កំហិត ឬបិទសកម្មភាពផ្ទៃខាងក្រោយ បែបផែនរូបភាពមួយចំនួន មុខងារជាក់លាក់ និងការតភ្ជាប់បណ្ដាញមួយចំនួន។"</string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"មុខងារសន្សំថ្មបើកទម្រង់រចនាងងឹត និងដាក់កំហិត ឬបិទសកម្មភាពផ្ទៃខាងក្រោយ បែបផែនរូបភាពមួយចំនួន មុខងារជាក់លាក់ និងការតភ្ជាប់បណ្ដាញមួយចំនួន។"</string>
<string name="data_saver_description" msgid="4995164271550590517">"ដើម្បីជួយកាត់បន្ថយការប្រើប្រាស់ទិន្នន័យ មុខងារសន្សំសំចៃទិន្នន័យរារាំងកម្មវិធីមួយចំនួនមិនឲ្យបញ្ជូន ឬទទួលទិន្នន័យនៅផ្ទៃខាងក្រោយទេ។ កម្មវិធីដែលអ្នកកំពុងប្រើនាពេលបច្ចុប្បន្នអាចចូលប្រើប្រាស់ទិន្នន័យបាន ប៉ុន្តែអាចនឹងមិនញឹកញាប់ដូចមុនទេ។ ឧទាហរណ៍ រូបភាពមិនបង្ហាញទេ លុះត្រាតែអ្នកប៉ះរូបភាពទាំងនោះ។"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"បើកកម្មវិធីសន្សំសំចៃទិន្នន័យ?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"បើក"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"ចំណូលចិត្តតំបន់"</string>
<string name="search_language_hint" msgid="7004225294308793583">"វាយបញ្ចូលឈ្មោះភាសា"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"បានណែនាំ"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"បានណែនាំ"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"ភាសាទាំងអស់"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"តំបន់ទាំងអស់"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"ស្វែងរក"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"អនុញ្ញាតឱ្យ <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ចូលប្រើកំណត់ហេតុឧបករណ៍ទាំងអស់ឬ?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"អនុញ្ញាតឱ្យចូលប្រើម្ដង"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"មិនអនុញ្ញាត"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"កំណត់ហេតុឧបករណ៍កត់ត្រាអ្វីដែលកើតឡើងនៅលើឧបករណ៍របស់អ្នក។ កម្មវិធីអាចប្រើកំណត់ហេតុទាំងនេះដើម្បីស្វែងរក និងដោះស្រាយបញ្ហាបាន។\n\nកំណត់ហេតុមួយចំនួនអាចមានព័ត៌មានរសើប ដូច្នេះគួរអនុញ្ញាតឱ្យចូលប្រើកំណត់ហេតុឧបករណ៍ទាំងអស់សម្រាប់តែកម្មវិធីដែលអ្នកទុកចិត្តប៉ុណ្ណោះ។ \n\nប្រសិនបើអ្នកមិនអនុញ្ញាតឱ្យកម្មវិធីនេះចូលប្រើកំណត់ហេតុឧបករណ៍ទាំងអស់ទេ វានៅតែអាចចូលប្រើកំណត់ហេតុរបស់វាផ្ទាល់បាន។ ក្រុមហ៊ុនផលិតឧបករណ៍របស់អ្នកប្រហែលជានៅតែអាចចូលប្រើកំណត់ហេតុ ឬព័ត៌មានមួយចំនួននៅលើឧបករណ៍របស់អ្នកបានដដែល។ ស្វែងយល់បន្ថែម"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"កំណត់ហេតុឧបករណ៍កត់ត្រាអ្វីដែលកើតឡើងនៅលើឧបករណ៍របស់អ្នក។ កម្មវិធីអាចប្រើកំណត់ហេតុទាំងនេះដើម្បីស្វែងរក និងដោះស្រាយបញ្ហាបាន។\n\nកំណត់ហេតុមួយចំនួនអាចមានព័ត៌មានរសើប ដូច្នេះគួរអនុញ្ញាតឱ្យចូលប្រើកំណត់ហេតុឧបករណ៍ទាំងអស់សម្រាប់តែកម្មវិធីដែលអ្នកទុកចិត្តប៉ុណ្ណោះ។ \n\nប្រសិនបើអ្នកមិនអនុញ្ញាតឱ្យកម្មវិធីនេះចូលប្រើកំណត់ហេតុឧបករណ៍ទាំងអស់ទេ វានៅតែអាចចូលប្រើកំណត់ហេតុរបស់វាផ្ទាល់បាន។ ក្រុមហ៊ុនផលិតឧបករណ៍របស់អ្នកប្រហែលជានៅតែអាចចូលប្រើកំណត់ហេតុ ឬព័ត៌មានមួយចំនួននៅលើឧបករណ៍របស់អ្នកបានដដែល។"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"កុំបង្ហាញម្ដងទៀត"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> ចង់បង្ហាញស្ថិតិប្រើប្រាស់របស់ <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"កែ"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ពិនិត្យមើលកម្មវិធីសកម្ម"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"មិនអាចចូលប្រើកាមេរ៉ាទូរសព្ទពី <xliff:g id="DEVICE">%1$s</xliff:g> របស់អ្នកបានទេ"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"មិនអាចចូលប្រើកាមេរ៉ាថេប្លេតពី <xliff:g id="DEVICE">%1$s</xliff:g> របស់អ្នកបានទេ"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"មិនអាចចូលប្រើប្រាស់ខ្លឹមសារនេះបានទេ ពេលផ្សាយ។ សូមសាកល្បងប្រើនៅលើទូរសព្ទរបស់អ្នកជំនួសវិញ។"</string>
<string name="system_locale_title" msgid="711882686834677268">"លំនាំដើមប្រព័ន្ធ"</string>
</resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index af95039..11dc96b 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ಬಳಕೆದಾರರು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಪಡಿಸಿದ್ದಾರೆ."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"ಹಲವಾರು ಪ್ರಯತ್ನಗಳು. ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ಯಾವುದೇ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ನೋಂದಣಿ ಮಾಡಿಲ್ಲ."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ಈ ಸಾಧನವು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಅನ್ನು ಹೊಂದಿಲ್ಲ."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> ಸಿದ್ಧಪಡಿಸಲಾಗುತ್ತಿದೆ."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"ಬೂಟ್ ಪೂರ್ಣಗೊಳಿಸಲಾಗುತ್ತಿದೆ."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"ಸೆಟ್ ಮಾಡುವುದನ್ನು ಮುಂದುವರಿಸಬೇಕೇ?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ನೀವು ಪವರ್ ಬಟನ್ ಒತ್ತಿದ್ದೀರಿ — ಇದು ಸಾಮಾನ್ಯವಾಗಿ ಸ್ಕ್ರೀನ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ.\n\nನಿಮ್ಮ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಹೊಂದಿಸುವಾಗ ಲಘುವಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸಿ."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"ಸ್ಕ್ರೀನ್ ಆಫ್ ಮಾಡಿ"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"ಸೆಟಪ್ ಮುಂದುವರಿಸಿ"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ಸ್ಕ್ರೀನ್ ಆಫ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ಸ್ಕ್ರೀನ್ ಆಫ್ ಮಾಡಿ"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಪರಿಶೀಲನೆ ಮುಂದುವರಿಸುವುದೇ?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"ನೀವು ಪವರ್ ಬಟನ್ ಒತ್ತಿದ್ದೀರಿ — ಇದು ಸಾಮಾನ್ಯವಾಗಿ ಸ್ಕ್ರೀನ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ.\n\nನಿಮ್ಮ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಪರಿಶೀಲಿಸಲು ಲಘುವಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ಸ್ಕ್ರೀನ್ ಆಫ್ ಮಾಡಿ"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"ಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"ಸೆಟಪ್ ಮಾಡಲು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"ನೀವು ಸಾಧನವನ್ನು ಮರು ಫಾರ್ಮ್ಯಾಟ್ ಮಾಡಬೇಕಾಗಬಹುದು. ಎಜೆಕ್ಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ಫೋಟೋಗಳು ಮತ್ತು ಮಾಧ್ಯಮವನ್ನು ವರ್ಗಾಯಿಸಲು"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ಫೋಟೋಗಳು, ವೀಡಿಯೋಗಳು, ಸಂಗೀತ ಹಾಗೂ ಇತ್ಯಾದಿಗಳನ್ನು ಸಂಗ್ರಹಿಸುವುದಕ್ಕಾಗಿ"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"ಮೀಡಿಯಾ ಫೈಲ್ಗಳನ್ನು ಬ್ರೌಸ್ ಮಾಡಿ"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> ನೊಂದಿಗೆ ಸಮಸ್ಯೆ"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತಿಲ್ಲ"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"ಸರಿಪಡಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> ದೋಷಪೂರಿತವಾಗಿದೆ. ಸರಿಪಡಿಸಲು ಆಯ್ಕೆ ಮಾಡಿ."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"ನೀವು ಸಾಧನವನ್ನು ಮರು ಫಾರ್ಮ್ಯಾಟ್ ಮಾಡಬೇಕಾಗಬಹುದು. ಎಜೆಕ್ಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"ಬೆಂಬಲಿಸದಿರುವ <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> ಪತ್ತೆಯಾಗಿದೆ"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತಿಲ್ಲ"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ಈ ಸಾಧನವು <xliff:g id="NAME">%s</xliff:g> ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ. ಬೆಂಬಲಿತ ಫಾರ್ಮ್ಯಾಟ್ನಲ್ಲಿ ಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"ಸೆಟಪ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"ಬೆಂಬಲಿಸಲಾಗುವ ಫಾರ್ಮ್ಯಾಟ್ನಲ್ಲಿ <xliff:g id="NAME">%s</xliff:g> ಅನ್ನು ಸೆಟಪ್ ಮಾಡಲು ಆಯ್ಕೆಮಾಡಿ."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"ನೀವು ಸಾಧನವನ್ನು ಮರು ಫಾರ್ಮ್ಯಾಟ್ ಮಾಡಬೇಕಾಗಬಹುದು"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ಅನಿರೀಕ್ಷಿತವಾಗಿ ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"ಪ್ರದೇಶ ಪ್ರಾಶಸ್ತ್ಯ"</string>
<string name="search_language_hint" msgid="7004225294308793583">"ಭಾಷೆ ಹೆಸರನ್ನು ಟೈಪ್ ಮಾಡಿ"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"ಸೂಚಿತ ಭಾಷೆ"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"ಸೂಚಿಸಲಾಗಿರುವುದು"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"ಎಲ್ಲಾ ಭಾಷೆಗಳು"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"ಎಲ್ಲಾ ಪ್ರದೇಶಗಳು"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"ಹುಡುಕಿ"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"ಎಲ್ಲಾ ಸಾಧನದ ಲಾಗ್ಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ಗೆ ಅನುಮತಿಸುವುದೇ?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"ಒಂದು ಬಾರಿಯ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"ಅನುಮತಿಸಬೇಡಿ"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿನ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಸಾಧನದ ಲಾಗ್ಗಳು ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತವೆ. ಸಮಸ್ಯೆಗಳನ್ನು ಪತ್ತೆಹಚ್ಚಲು ಮತ್ತು ಪರಿಹರಿಸಲು ಆ್ಯಪ್ಗಳು ಈ ಲಾಗ್ ಅನ್ನು ಬಳಸಬಹುದು.\n\nಕೆಲವು ಲಾಗ್ಗಳು ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಿರಬಹುದು, ಆದ್ದರಿಂದ ನಿಮ್ಮ ವಿಶ್ವಾಸಾರ್ಹ ಆ್ಯಪ್ಗಳಿಗೆ ಮಾತ್ರ ಸಾಧನದ ಎಲ್ಲಾ ಲಾಗ್ಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ. \n\nಎಲ್ಲಾ ಸಾಧನ ಲಾಗ್ಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ನೀವು ಈ ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸದಿದ್ದರೆ, ಅದು ಆಗಲೂ ತನ್ನದೇ ಆದ ಲಾಗ್ಗಳನ್ನು ಪ್ರವೇಶಿಸಬಹುದು. ನಿಮ್ಮ ಸಾಧನ ತಯಾರಕರಿಗೆ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿನ ಕೆಲವು ಲಾಗ್ಗಳು ಅಥವಾ ಮಾಹಿತಿಯನ್ನು ಪ್ರವೇಶಿಸಲು ಈಗಲೂ ಸಾಧ್ಯವಾಗುತ್ತದೆ. ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿನ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಸಾಧನದ ಲಾಗ್ಗಳು ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತವೆ. ಸಮಸ್ಯೆಗಳನ್ನು ಪತ್ತೆಹಚ್ಚಲು ಮತ್ತು ಪರಿಹರಿಸಲು ಆ್ಯಪ್ಗಳು ಈ ಲಾಗ್ ಅನ್ನು ಬಳಸಬಹುದು.\n\nಕೆಲವು ಲಾಗ್ಗಳು ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಿರಬಹುದು, ಆದ್ದರಿಂದ ನಿಮ್ಮ ವಿಶ್ವಾಸಾರ್ಹ ಆ್ಯಪ್ಗಳಿಗೆ ಮಾತ್ರ ಸಾಧನದ ಎಲ್ಲಾ ಲಾಗ್ಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ. \n\nಎಲ್ಲಾ ಸಾಧನ ಲಾಗ್ಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ನೀವು ಈ ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸದಿದ್ದರೆ, ಅದು ಆಗಲೂ ತನ್ನದೇ ಆದ ಲಾಗ್ಗಳನ್ನು ಪ್ರವೇಶಿಸಬಹುದು. ನಿಮ್ಮ ಸಾಧನ ತಯಾರಕರಿಗೆ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿನ ಕೆಲವು ಲಾಗ್ಗಳು ಅಥವಾ ಮಾಹಿತಿಯನ್ನು ಪ್ರವೇಶಿಸಲು ಈಗಲೂ ಸಾಧ್ಯವಾಗುತ್ತದೆ."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"ಮತ್ತೊಮ್ಮೆ ತೋರಿಸಬೇಡಿ"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_2">%2$s</xliff:g> ಸ್ಲೈಸ್ಗಳನ್ನು <xliff:g id="APP_0">%1$s</xliff:g> ತೋರಿಸಲು ಬಯಸಿದೆ"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"ಎಡಿಟ್"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ಸಕ್ರಿಯ ಆ್ಯಪ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"ನಿಮ್ಮ <xliff:g id="DEVICE">%1$s</xliff:g> ಮೂಲಕ ಫೋನ್ನ ಕ್ಯಾಮರಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"ನಿಮ್ಮ <xliff:g id="DEVICE">%1$s</xliff:g> ಮೂಲಕ ಟ್ಯಾಬ್ಲೆಟ್ನ ಕ್ಯಾಮರಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"ಸ್ಟ್ರೀಮ್ ಮಾಡುವಾಗ ಇದನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅದರ ಬದಲು ನಿಮ್ಮ ಫೋನ್ನಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="system_locale_title" msgid="711882686834677268">"ಸಿಸ್ಟಂ ಡೀಫಾಲ್ಟ್"</string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 29e9367..bc04d1e 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"지문 인식 작업이 취소되었습니다."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"사용자가 지문 인식 작업을 취소했습니다."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"시도 횟수가 너무 많습니다. 나중에 다시 시도하세요."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"시도 횟수가 너무 많습니다. 지문 센서가 사용 중지되었습니다."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"다시 시도해 보세요."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"등록된 지문이 없습니다."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"기기에 지문 센서가 없습니다."</string>
@@ -650,9 +651,9 @@
<string name="face_acquired_recalibrate" msgid="8724013080976469746">"얼굴을 다시 등록해 주세요."</string>
<string name="face_acquired_too_different" msgid="2520389515612972889">"얼굴을 인식할 수 없습니다. 다시 시도해 주세요."</string>
<string name="face_acquired_too_similar" msgid="8882920552674125694">"얼굴의 위치를 조금 변경해 주세요."</string>
- <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"휴대전화를 좀 더 똑바로 바라봐 주세요."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"휴대전화를 좀 더 똑바로 바라봐 주세요."</string>
- <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"휴대전화를 좀 더 똑바로 바라봐 주세요."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"휴대전화를 좀 더\\n똑바로 바라봐 주세요."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"휴대전화를 좀 더\\n똑바로 바라봐 주세요."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"휴대전화를 좀 더\\n똑바로 바라봐 주세요."</string>
<string name="face_acquired_obscured" msgid="4917643294953326639">"얼굴이 가려지지 않도록 해 주세요."</string>
<string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"검은색 바를 포함한 화면 상단을 청소하세요."</string>
<!-- no translation found for face_acquired_dark_glasses_detected (5643703296620631986) -->
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> 준비 중..."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"앱을 시작하는 중입니다."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"부팅 완료"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"설정을 계속하시겠어요?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"전원 버튼을 눌렀습니다. 이러면 보통 화면이 꺼집니다.\n\n지문 설정 중에 가볍게 탭하세요."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"화면 끄기"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"설정 계속"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"탭하여 화면 끄기"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"화면 끄기"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"지문 인증을 계속할까요?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"전원 버튼을 눌렀습니다. 이러면 보통 화면이 꺼집니다.\n\n지문을 인식하려면 화면을 가볍게 탭하세요."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"화면 끄기"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"설정하려면 탭하세요."</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"설정하려면 선택하세요."</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"기기를 다시 포맷해야 할 수 있습니다. 꺼내려면 탭하세요."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"사진 및 미디어를 전송하는 데 사용합니다."</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"사진, 동영상, 음악 등을 저장할 수 있습니다."</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"미디어 파일을 둘러보세요."</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g>에 문제 발생"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g>이(가) 작동하지 않음"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"문제를 해결하려면 탭하세요."</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g>이(가) 손상되었습니다. 선택하여 문제를 해결하세요."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"기기를 다시 포맷해야 할 수 있습니다. 꺼내려면 탭하세요."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"지원되지 않는 <xliff:g id="NAME">%s</xliff:g>입니다."</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> 인식됨"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g>이(가) 작동하지 않음"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"이 기기는 <xliff:g id="NAME">%s</xliff:g>을(를) 지원하지 않습니다. 지원하는 형식으로 설정하려면 탭하세요."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"탭하여 설정: ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"<xliff:g id="NAME">%s</xliff:g>을(를) 지원되는 형식으로 설정하려면 선택하세요."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"기기를 다시 포맷해야 할 수 있습니다."</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>이(가) 예기치 않게 삭제됨"</string>
@@ -1424,7 +1424,7 @@
<string name="ext_media_unmounting_notification_title" msgid="4147986383917892162">"<xliff:g id="NAME">%s</xliff:g> 마운트 해제 중"</string>
<string name="ext_media_unmounting_notification_message" msgid="5717036261538754203">"외부 미디어를 제거하지 마세요."</string>
<string name="ext_media_init_action" msgid="2312974060585056709">"설정"</string>
- <string name="ext_media_unmount_action" msgid="966992232088442745">"마운트 해제"</string>
+ <string name="ext_media_unmount_action" msgid="966992232088442745">"꺼내기"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"둘러보기"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"출력 전환"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> 없음"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"지역 환경설정"</string>
<string name="search_language_hint" msgid="7004225294308793583">"언어 이름 입력"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"추천"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"추천 지역"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"모든 언어"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"모든 지역"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"검색"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>에서 모든 기기 로그에 액세스하도록 허용하시겠습니까?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"일회성 액세스 허용"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"허용 안함"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"기기 로그에는 기기에서 발생한 상황이 기록됩니다. 앱은 문제를 찾고 해결하는 데 이 로그를 사용할 수 있습니다.\n\n일부 로그는 민감한 정보를 포함할 수 있으므로 신뢰할 수 있는 앱만 모든 기기 로그에 액세스하도록 허용하세요. \n\n앱에 전체 기기 로그에 대한 액세스 권한을 부여하지 않아도, 앱이 자체 로그에는 액세스할 수 있습니다. 기기 제조업체에서 일부 로그 또는 기기 내 정보에 액세스할 수도 있습니다. 자세히 알아보세요."</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"기기 로그에 기기에서 발생한 상황이 기록됩니다. 앱은 문제를 찾고 해결하는 데 이 로그를 사용할 수 있습니다.\n\n일부 로그는 민감한 정보를 포함할 수 있으므로 신뢰할 수 있는 앱만 모든 기기 로그에 액세스하도록 허용하세요. \n\n앱에 전체 기기 로그에 대한 액세스 권한을 부여하지 않아도 앱이 자체 로그에는 액세스할 수 있습니다. 기기 제조업체에서 일부 로그 또는 기기 내 정보에 액세스할 수도 있습니다."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"다시 표시 안함"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g>에서 <xliff:g id="APP_2">%2$s</xliff:g>의 슬라이스를 표시하려고 합니다"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"수정"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"활성 상태의 앱 확인"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"사용자의 <xliff:g id="DEVICE">%1$s</xliff:g>에서 휴대전화 카메라에 액세스할 수 없습니다."</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"사용자의 <xliff:g id="DEVICE">%1$s</xliff:g>에서 태블릿 카메라에 액세스할 수 없습니다."</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"스트리밍 중에는 액세스할 수 없습니다. 대신 휴대전화에서 시도해 보세요."</string>
<string name="system_locale_title" msgid="711882686834677268">"시스템 기본값"</string>
</resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 557e635..483b8c9 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Манжа изи иш-аракети жокко чыгарылды."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Манжа изи операциясын колдонуучу жокко чыгарды."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Аракеттер өтө көп болду. Бир аздан кийин кайталап көрүңүз."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Өтө көп жолу аракет жасадыңыз. Манжа изинин сенсору өчүрүлдү."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Кайра бир аракеттениңиз."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Бир да манжа изи катталган эмес."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Бул түзмөктө манжа изинин сенсору жок."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> даярдалууда."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Колдонмолорду иштетип баштоо"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Жүктөлүүдө"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Жөндөөнү улантасызбы?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Кубат баскычын бастыңыз — адатта, бул экранды өчүрөт.\n\nМанжаңыздын изин жөндөп жатканда аны акырын басып көрүңүз."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Экранды өчүрүү"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Жөндөөнү улантуу"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Экранды өчүрүү үчүн таптаңыз"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Экранды өчүрүү"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Манжаңыздын изин ырастоону улантасызбы?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Кубат баскычын бастыңыз — адатта, бул экранды өчүрөт.\n\nМанжаңыздын изин ырастоо үчүн аны акырын басып көрүңүз."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Экранды өчүрүү"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Жөндөө үчүн таптаңыз"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Жөндөө үчүн тандаңыз"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Түзмөктү форматташыңыз керек болушу мүмкүн. Чыгаруу үчүн таптап коюңуз."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Сүрөттөрдү жана медиа өткөрүү үчүн"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Сүрөттөрдү, видеолорду, ырларды жана башкаларды сактоо үчүн керек"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Медиа файлдарды серептөө"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> түзмөгүндө бир маселе бар"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> иштебей жатат"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Оңдоо үчүн таптап коюңуз"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> – бузук. Оңдоо үчүн тандаңыз."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Түзмөктү форматташыңыз керек болушу мүмкүн. Чыгаруу үчүн таптап коюңуз."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> колдоого алынбайт"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> аныкталды"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> иштебей жатат"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Бул түзмөктө <xliff:g id="NAME">%s</xliff:g> колдоого алынбайт. Колдоого алынуучу форматта орнотуу үчүн таптап коюңуз."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Тууралоо үчүн таптаңыз."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Колдоого алынуучу форматта орнотуу үчүн <xliff:g id="NAME">%s</xliff:g> тандаңыз."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Түзмөктү форматташыңыз керек болушу мүмкүн"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> күтүүсүздөн өчүрүлдү"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Чөлкөмдүк жөндөөлөр"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Тилди киргизиңиз"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Сунушталгандар"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Сунушталган"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Бардык тилдер"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Бардык өлкөлөр"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Издөө"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> колдонмосуна түзмөктөгү бардык таржымалдарды жеткиликтүү кыласызбы?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Бир жолу жеткиликтүү кылуу"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Жок"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Түзмөктө жасалган нерселердин баары таржымал болуп сактала берет. Колдонмолор анын жардамы менен көйгөйлөрдү аныктап, оңдоп турушат.\n\nАйрым таржымалдарда купуя маалымат болушу мүмкүн, андыктан түзмөктөгү бардык таржымалдарды ишенимдүү колдонмолорго гана пайдаланууга уруксат бериңиз. \n\nЭгер бул колдонмого түзмөктөгү айрым таржымалдарга кирүүгө тыюу салсаңыз, ал өзүнүн таржымалдарын пайдалана берет. Түзмөктү өндүрүүчү түзмөгүңүздөгү айрым таржымалдарды же маалыматты көрө берет. Кеңири маалымат"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Түзмөктө аткарылган бардык аракеттер түзмөктүн таржымалдарында сакталып калат. Колдонмолор бул таржымалдарды колдонуп, маселелерди оңдошот.\n\nАйрым таржымалдарда купуя маалымат болушу мүмкүн, андыктан түзмөктөгү бардык таржымалдарды ишенимдүү колдонмолорго гана пайдаланууга уруксат бериңиз. \n\nЭгер бул колдонмого түзмөктөгү айрым таржымалдарга кирүүгө тыюу салсаңыз, ал өзүнүн таржымалдарын пайдалана берет. Түзмөктү өндүрүүчү түзмөгүңүздөгү айрым таржымалдарды же маалыматты көрө берет."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Экинчи көрүнбөсүн"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> колдонмосу <xliff:g id="APP_2">%2$s</xliff:g> үлгүлөрүн көрсөткөнү жатат"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Түзөтүү"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Жигердүү колдонмолорду карап чыгуу"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүңүздөн телефондун камерасына мүмкүнчүлүк жок"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"<xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүңүздөн планшетиңиздин камерасына мүмкүнчүлүк жок"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Муну алып ойнотуу учурунда көрүүгө болбойт. Анын ордуна телефондон кирип көрүңүз."</string>
<string name="system_locale_title" msgid="711882686834677268">"Системанын демейки параметрлери"</string>
</resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index faa6b57..54d6af4 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ຍົກເລີກການດຳເນີນການລາຍນີ້ວມືແລ້ວ."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ຜູ້ໃຊ້ໄດ້ຍົກເລີກຄຳສັ່ງລາຍນິ້ວມືແລ້ວ."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"ມີຄວາມພະຍາຍາມຫຼາຍຄັ້ງເກີນໄປ. ລອງໃໝ່ພາຍຫຼັງ."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"ພະຍາຍາມຫຼາຍເທື່ອເກີນໄປ. ລະບົບປິດການເຮັດວຽກຂອງເຊັນເຊີລາຍນິ້ວມືແລ້ວ."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ລອງໃໝ່ອີກຄັ້ງ."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ບໍ່ມີການລົງທະບຽນລາຍນິ້ວມື."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ອຸປະກອນນີ້ບໍ່ມີເຊັນເຊີລາຍນິ້ວມື."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"ກຳລັງກຽມ <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ກຳລັງເປີດແອັບຯ."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"ກຳລັງສຳເລັດການເປີດລະບົບ."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"ສືບຕໍ່ການຕັ້ງຄ່າບໍ?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ທ່ານກົດປຸ່ມເປີດປິດ, ປົກກະຕິນີ້ຈະປິດໜ້າຈໍ.\n\nລອງແຕະຄ່ອຍໆໃນລະຫວ່າງຕັ້ງຄ່າລາຍນິ້ວມືຂອງທ່ານ."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"ປິດໜ້າຈໍ"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"ສືບຕໍ່ການຕັ້ງຄ່າ"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ແຕະເພື່ອປິດໜ້າຈໍ"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ປິດໜ້າຈໍ"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"ສືບຕໍ່ການຢັ້ງຢືນລາຍນິ້ວມືຂອງທ່ານບໍ?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"ທ່ານກົດປຸ່ມເປີດປິດ, ປົກກະຕິນີ້ຈະເປັນການປິດໜ້າຈໍ.\n\nໃຫ້ລອງແຕະຄ່ອຍໆເພື່ອຢັ້ງຢືນລາຍນິ້ວມືຂອງທ່ານ."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ປິດໜ້າຈໍ"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"ແຕະເພື່ອຕັ້ງຄ່າ"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"ເລືອກເພື່ອຕັ້ງຄ່າ"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"ທ່ານຈະຕ້ອງຟໍແມັດອຸປະກອນຄືນໃໝ່. ແຕະເພື່ອຖອດອອກ."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ສຳລັບການໂອນຮູບຖ່າຍ ແລະມີເດຍ"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ສຳລັບການຈັດເກັບຮູບພາບ, ວິດີໂອ, ເພງ ແລະ ອື່ນໆອີກ"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"ເລືອກໄຟລ໌ມີເດຍ"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"ເກີດບັນຫາກັບ <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ບໍ່ເຮັດວຽກ"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"ແຕະເພື່ອແກ້ໄຂ"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> ເສຍຫາຍ. ແຕະເພື່ອສ້ອມແປງ."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"ທ່ານຈະຕ້ອງຟໍແມັດອຸປະກອນຄືນໃໝ່. ແຕະເພື່ອຖອດອອກ."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"ບໍ່ຮອງຮັບ <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"ກວດພົບ <xliff:g id="NAME">%s</xliff:g> ແລ້ວ"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ບໍ່ເຮັດວຽກ"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ອຸປະກອນນີ້ບໍ່ຮອງຮັບ <xliff:g id="NAME">%s</xliff:g> ນີ້. ແຕະເພື່ອຕັ້ງຄ່າໃນຮູບແບບທີ່ຮອງຮັບ."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"ແຕະເພື່ອຕັ້ງຄ່າ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"ເລືອກເພື່ອຕັ້ງຄ່າ <xliff:g id="NAME">%s</xliff:g> ໃນຮູບແບບທີ່ຮອງຮັບ."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"ທ່ານຈະຕ້ອງຟໍແມັດອຸປະກອນຄືນໃໝ່"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ຖືກຖອດອອກໄປແບບບໍ່ຄາດຄິດ"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"ການຕັ້ງຄ່າພາກພື້ນ"</string>
<string name="search_language_hint" msgid="7004225294308793583">"ພິມຊື່ພາສາ"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"ແນະນຳ"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"ແນະນຳ"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"ທຸກພາສາ"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"ທຸກຂົງເຂດ"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"ຄົ້ນຫາ"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"ອະນຸຍາດໃຫ້ <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ເຂົ້າເຖິງບັນທຶກອຸປະກອນທັງໝົດບໍ?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"ອະນຸຍາດການເຂົ້າເຖິງແບບເທື່ອດຽວ"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"ບໍ່ອະນຸຍາດ"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"ບັນທຶກອຸປະກອນຈະບັນທຶກສິ່ງທີ່ເກີດຂຶ້ນຢູ່ອຸປະກອນຂອງທ່ານ. ແອັບສາມາດໃຊ້ບັນທຶກເຫຼົ່ານີ້ເພື່ອຊອກຫາ ແລະ ແກ້ໄຂບັນຫາໄດ້.\n\nບັນທຶກບາງຢ່າງອາດມີຂໍ້ມູນລະອຽດອ່ອນ, ດັ່ງນັ້ນໃຫ້ອະນຸຍາດສະເພາະແອັບທີ່ທ່ານເຊື່ອຖືໃຫ້ເຂົ້າເຖິງບັນທຶກອຸປະກອນທັງໝົດເທົ່ານັ້ນ. \n\nຫາກທ່ານບໍ່ອະນຸຍາດແອັບນີ້ໃຫ້ເຂົ້າເຖິງບັນທຶກອຸປະກອນທັງໝົດ, ມັນຈະຍັງຄົງສາມາດເຂົ້າເຖິງບັນທຶກຂອງຕົວມັນເອງໄດ້ຢູ່. ຜູ້ຜະລິດອຸປະກອນຂອງທ່ານອາດຍັງຄົງສາມາດເຂົ້າເຖິງບັນທຶກ ຫຼື ຂໍ້ມູນບາງຢ່າງຢູ່ອຸປະກອນຂອງທ່ານໄດ້. ສຶກສາເພີ່ມເຕີມ"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"ບັນທຶກອຸປະກອນຈະບັນທຶກສິ່ງທີ່ເກີດຂຶ້ນຢູ່ອຸປະກອນຂອງທ່ານ. ແອັບສາມາດໃຊ້ບັນທຶກເຫຼົ່ານີ້ເພື່ອຊອກຫາ ແລະ ແກ້ໄຂບັນຫາໄດ້.\n\nບັນທຶກບາງຢ່າງອາດມີຂໍ້ມູນລະອຽດອ່ອນ, ດັ່ງນັ້ນໃຫ້ອະນຸຍາດສະເພາະແອັບທີ່ທ່ານເຊື່ອຖືໃຫ້ເຂົ້າເຖິງບັນທຶກອຸປະກອນທັງໝົດເທົ່ານັ້ນ. \n\nຫາກທ່ານບໍ່ອະນຸຍາດແອັບນີ້ໃຫ້ເຂົ້າເຖິງບັນທຶກອຸປະກອນທັງໝົດ, ມັນຈະຍັງຄົງສາມາດເຂົ້າເຖິງບັນທຶກຂອງຕົວມັນເອງໄດ້ຢູ່. ຜູ້ຜະລິດອຸປະກອນຂອງທ່ານອາດຍັງຄົງສາມາດເຂົ້າເຖິງບັນທຶກ ຫຼື ຂໍ້ມູນບາງຢ່າງຢູ່ອຸປະກອນຂອງທ່ານໄດ້."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"ບໍ່ຕ້ອງສະແດງອີກ"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> ຕ້ອງການສະແດງ <xliff:g id="APP_2">%2$s</xliff:g> ສະໄລ້"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"ແກ້ໄຂ"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ກວດສອບແອັບທີ່ເຄື່ອນໄຫວ"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"ບໍ່ສາມາດເຂົ້າເຖິງກ້ອງຖ່າຍຮູບຂອງໂທລະສັບຈາກ <xliff:g id="DEVICE">%1$s</xliff:g> ຂອງທ່ານໄດ້"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"ບໍ່ສາມາດເຂົ້າເຖິງກ້ອງຖ່າຍຮູບຂອງແທັບເລັດຈາກ <xliff:g id="DEVICE">%1$s</xliff:g> ຂອງທ່ານໄດ້"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"ບໍ່ສາມາດເຂົ້າເຖິງເນື້ອຫານີ້ໄດ້ໃນຂະນະທີ່ຍັງສະຕຣີມຢູ່. ກະລຸນາລອງຢູ່ໂທລະສັບຂອງທ່ານແທນ."</string>
<string name="system_locale_title" msgid="711882686834677268">"ຄ່າເລີ່ມຕົ້ນຂອງລະບົບ"</string>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 1a11949..319ae15 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -610,7 +610,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Piršto antspaudo operacija atšaukta."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Piršto antspaudo operaciją atšaukė naudotojas."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Per daug bandymų. Vėliau bandykite dar kartą."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Per daug bandymų. Piršto antspaudo jutiklis išjungtas."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Bandykite dar kartą."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Neužregistruota jokių kontrolinių kodų."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Šiame įrenginyje nėra kontrolinio kodo jutiklio."</string>
@@ -1251,10 +1252,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Ruošiama „<xliff:g id="APPNAME">%1$s</xliff:g>“."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Paleidžiamos programos."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Užbaigiamas paleidimas."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Tęsti sąranką?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Paspaudėte maitinimo mygtuką, taip paprastai išjungiamas ekranas.\n\nNustatydami kontrolinį kodą, pabandykite jį švelniai paliesti."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Išjungti ekraną"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Tęsti sąranką"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Palieskite, kad išjungtumėte ekraną"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Išjungti ekraną"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Tęsti kontrolinio kodo patvirtinimą?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Paspaudėte maitinimo mygtuką, taip paprastai išjungiamas ekranas.\n\nNorėdami patvirtinti kontrolinį kodą, pabandykite jį švelniai paliesti."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Išjungti ekraną"</string>
@@ -1407,16 +1407,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Palieskite, kad nustatytumėte"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Pasirinkite, kad nustatytumėte"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Jums gali reikėti suformatuoti įrenginį iš naujo. Palieskite, kad pašalintumėte."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Norint perkelti nuotraukas ir mediją"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Nuotraukoms, vaizdo įrašams, muzikai ir kitam turiniui saugoti"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Naršykite medijos failus"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Kilo problema dėl laikmenos (<xliff:g id="NAME">%s</xliff:g>)"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> neveikia"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Palieskite ir ištaisykite tai"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> sugadinta. Pasirinkite, kad pataisytumėte."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Jums gali reikėti suformatuoti įrenginį iš naujo. Palieskite, kad pašalintumėte."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Nepalaikoma saugykla (<xliff:g id="NAME">%s</xliff:g>)"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Aptikta „<xliff:g id="NAME">%s</xliff:g>“"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> neveikia"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Šis įrenginys nepalaiko šios <xliff:g id="NAME">%s</xliff:g>. Palieskite, kad nustatytumėte palaikomu formatu."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Palieskite, kad nustatytumėte."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Pasirinkite, kad nustatytumėte <xliff:g id="NAME">%s</xliff:g> palaikomu formatu."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Jums gali reikėti suformatuoti įrenginį iš naujo"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> netikėtai pašalinta"</string>
@@ -1929,6 +1929,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Regiono nuostata"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Įveskite kalbos pav."</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Siūloma"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Siūloma"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Visos kalbos"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Visi regionai"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Paieška"</string>
@@ -2051,7 +2052,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Leisti „<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>“ pasiekti visus įrenginio žurnalus?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Leisti vienkartinę prieigą"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Neleisti"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Įrenginyje įrašoma, kas įvyksta jūsų įrenginyje. Programos gali naudoti šiuos žurnalus, kad surastų ir išspręstų problemas.\n\nKai kuriuose žurnaluose gali būti neskelbtinos informacijos, todėl visus įrenginio žurnalus leiskite pasiekti tik programoms, kuriomis pasitikite. \n\nJei neleisite šiai programai pasiekti visų įrenginio žurnalų, ji vis tiek galės pasiekti savo žurnalus. Įrenginio gamintojui vis tiek gali būti leidžiama pasiekti tam tikrus žurnalus ar informaciją jūsų įrenginyje. Sužinokite daugiau"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Įrenginyje įrašoma, kas įvyksta jūsų įrenginyje. Programos gali naudoti šiuos žurnalus, kad surastų ir išspręstų problemas.\n\nKai kuriuose žurnaluose gali būti neskelbtinos informacijos, todėl visus įrenginio žurnalus leiskite pasiekti tik programoms, kuriomis pasitikite. \n\nJei neleisite šiai programai pasiekti visų įrenginio žurnalų, ji vis tiek galės pasiekti savo žurnalus. Įrenginio gamintojui vis tiek gali būti leidžiama pasiekti tam tikrus žurnalus ar informaciją jūsų įrenginyje."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Daugiau neberodyti"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"„<xliff:g id="APP_0">%1$s</xliff:g>“ nori rodyti „<xliff:g id="APP_2">%2$s</xliff:g>“ fragmentus"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Redaguoti"</string>
@@ -2292,5 +2293,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Peržiūrėkite aktyvias programas"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nepavyko pasiekti telefono fotoaparato iš „<xliff:g id="DEVICE">%1$s</xliff:g>“"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Nepavyko pasiekti planšetinio kompiuterio fotoaparato iš „<xliff:g id="DEVICE">%1$s</xliff:g>“"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Nepavyksta pasiekti perduodant srautu. Pabandykite naudoti telefoną."</string>
<string name="system_locale_title" msgid="711882686834677268">"Numatytoji sistemos vertė"</string>
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 013e999..e8c9739 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -609,7 +609,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Nospieduma darbība neizdevās."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Lietotājs atcēla pirksta nospieduma darbību."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Pārāk daudz mēģinājumu. Vēlāk mēģiniet vēlreiz."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Pārāk daudz mēģinājumu. Pirksta nospieduma sensors atspējots."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Mēģiniet vēlreiz."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nav reģistrēts neviens pirksta nospiedums."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Šajā ierīcē nav pirksta nospieduma sensora."</string>
@@ -1250,10 +1251,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Notiek lietotnes <xliff:g id="APPNAME">%1$s</xliff:g> sagatavošana."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Notiek lietotņu palaišana."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Tiek pabeigta sāknēšana."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Vai turpināt iestatīšanu?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Jūs nospiedāt barošanas pogu — tādējādi parasti tiek izslēgts ekrāns.\n\nMēģiniet viegli pieskarties, iestatot pirksta nospiedumu."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Izslēgt ekrānu"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Turpināt iestatīšanu"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Pieskarieties, lai izslēgtu ekrānu"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Izslēgt ekrānu"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Vai apstiprināt pirksta nospiedumu?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Jūs nospiedāt barošanas pogu — tādējādi parasti tiek izslēgts ekrāns.\n\nMēģiniet viegli pieskarties, lai apstiprinātu pirksta nospiedumu."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Izslēgt ekrānu"</string>
@@ -1406,16 +1406,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Pieskarieties, lai iestatītu."</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Atlasiet, lai iestatītu."</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Iespējams, jums būs atkārtoti jāformatē ierīce. Pieskarieties, lai izņemtu."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Fotoattēlu un satura pārsūtīšanai."</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Fotoattēlu, videoklipu, mūzikas un cita satura glabāšanai"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Pārlūkojiet multivides failus."</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problēma saistībā ar <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> nedarbojas."</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Pieskarieties, lai novērstu problēmu."</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> ir bojāta. Atlasiet, lai labotu."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Iespējams, jums būs atkārtoti jāformatē ierīce. Pieskarieties, lai izņemtu."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Neatbalstīts datu nesējs (<xliff:g id="NAME">%s</xliff:g>)"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"atrasts: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> nedarbojas."</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Šī ierīce neatbalsta datu nesēju <xliff:g id="NAME">%s</xliff:g>. Pieskarieties, lai iestatītu to atbalstītā formātā."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Pieskarieties, lai iestatītu"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Atlasiet, lai iestatītu atbalstītu formātu multivides krātuvei (<xliff:g id="NAME">%s</xliff:g>)."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Iespējams, jums būs atkārtoti jāformatē ierīce."</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> tika negaidīti izņemta"</string>
@@ -1928,6 +1928,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Reģiona preference"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Ierakstiet valodas nosaukumu"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Ieteiktās"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Ieteiktie"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Visas valodas"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Visi reģioni"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Meklēt"</string>
@@ -2050,7 +2051,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Vai atļaujat lietotnei <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> piekļūt visiem ierīces žurnāliem?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Atļaut vienreizēju piekļuvi"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Neatļaut"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Ierīces žurnālos tiek reģistrēti ierīces procesi un notikumi. Lietotņu izstrādātāji var izmantot šos žurnālus, lai atrastu un novērstu problēmas savās lietotnēs.\n\nDažos žurnālos var būt ietverta sensitīva informācija, tāpēc atļaujiet tikai uzticamām lietotnēm piekļūt visiem ierīces žurnāliem. \n\nJa neatļausiet šai lietotnei piekļūt visiem ierīces žurnāliem, lietotnes izstrādātājs joprojām varēs piekļūt pašas lietotnes žurnāliem. Jūsu ierīces ražotājs, iespējams, joprojām varēs piekļūt noteiktiem žurnāliem vai informācijai jūsu ierīcē. Uzziniet vairāk."</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Ierīces žurnālos tiek reģistrēti ierīces procesi un notikumi. Lietotņu izstrādātāji var izmantot šos žurnālus, lai atrastu un izlabotu problēmas savās lietotnēs.\n\nDažos žurnālos var būt ietverta sensitīva informācija, tāpēc atļaujiet tikai uzticamām lietotnēm piekļūt visiem ierīces žurnāliem. \n\nJa neatļausiet šai lietotnei piekļūt visiem ierīces žurnāliem, lietotnes izstrādātājs joprojām varēs piekļūt pašas lietotnes žurnāliem. Iespējams, ierīces ražotājs joprojām varēs piekļūt noteiktiem žurnāliem vai informācijai jūsu ierīcē."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Vairs nerādīt"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Lietotne <xliff:g id="APP_0">%1$s</xliff:g> vēlas rādīt lietotnes <xliff:g id="APP_2">%2$s</xliff:g> sadaļas"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Rediģēt"</string>
@@ -2291,5 +2292,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Pārbaudiet aktīvās lietotnes"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nevar piekļūt tālruņa kamerai no jūsu ierīces (<xliff:g id="DEVICE">%1$s</xliff:g>)."</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Nevar piekļūt planšetdatora kamerai no jūsu ierīces (<xliff:g id="DEVICE">%1$s</xliff:g>)."</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Straumēšanas laikā nevar piekļūt šim saturam. Mēģiniet tam piekļūt savā tālrunī."</string>
<string name="system_locale_title" msgid="711882686834677268">"Sistēmas noklusējums"</string>
</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 0aeec6d..2439bd5 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Операцијата со отпечаток се откажа."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Корисникот ја откажа потврдата со отпечаток."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Премногу обиди. Обидете се повторно подоцна."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Премногу обиди. Сензорот за отпечатоци е оневозможен."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Обидете се повторно."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Не се запишани отпечатоци."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Уредов нема сензор за отпечатоци."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Се подготвува <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Се стартуваат апликациите."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Подигањето завршува."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Дали да продолжи поставувањето?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Го притиснавте копчето за вклучување — така обично се исклучува екранот.\n\nДопрете лесно додека го поставувате отпечатокот."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Исклучи го екранот"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Продолжи"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Допрете за да го исклучите екранот"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Исклучи го екранот"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Да продолжи потврдувањето на отпечаток?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Го притиснавте копчето за вклучување — така обично се исклучува екранот.\n\nДопрете лесно за да го потврдите отпечатокот."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Исклучи го екранот"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Допрете за поставување"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Изберете за поставување"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Можеби ќе треба да го преформатирате уредот. Допрете за отстранување."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"За пренесување фотографии и аудио/видео содржини"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"За складирање фотографии, видеа, музика и друго"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Прелистајте ги датотеките на надворешниот уред"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Проблем со <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> не работи"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Допрете за да го поправите ова"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> е оштетена. Изберете за поправање."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Можеби ќе треба да го преформатирате уредот. Допрете за отстранување."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Неподдржана <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Уредот откри <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> не работи"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Уредот не ја поддржува оваа <xliff:g id="NAME">%s</xliff:g>. Допрете за поставување во поддржан формат."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Допрете за поставување."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Допрете за поставување на <xliff:g id="NAME">%s</xliff:g> во поддржан формат."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Можеби ќе треба да го преформатирате уредот"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> неочекувано е отстранета"</string>
@@ -1567,8 +1567,8 @@
<string name="action_bar_home_description_format" msgid="5087107531331621803">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="4346835454749569826">"%1$s, %2$s, %3$s"</string>
<string name="storage_internal" msgid="8490227947584914460">"Внатрешен споделен капацитет"</string>
- <string name="storage_sd_card" msgid="3404740277075331881">"СД картичка"</string>
- <string name="storage_sd_card_label" msgid="7526153141147470509">"<xliff:g id="MANUFACTURER">%s</xliff:g> СД-картичка"</string>
+ <string name="storage_sd_card" msgid="3404740277075331881">"SD-картичка"</string>
+ <string name="storage_sd_card_label" msgid="7526153141147470509">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD-картичка"</string>
<string name="storage_usb_drive" msgid="448030813201444573">"USB-меморија"</string>
<string name="storage_usb_drive_label" msgid="6631740655876540521">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB-меморија"</string>
<string name="storage_usb" msgid="2391213347883616886">"USB меморија"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Претпочитувања за регион"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Внесете име на јазик"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Предложени"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Предложени"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Сите јазици"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Сите региони"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Пребарај"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Да се дозволи <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> да пристапува до целата евиденција на уредот?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Дозволи еднократен пристап"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Не дозволувај"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Евиденцијата на уредот снима што се случува со вашиот уред. Апликациите можат да ја користат евиденцијата за да наоѓаат и поправаат проблеми.\n\nНекоја евиденција може да содржи чувствителни податоци, па затоа дозволувајте само апликации на кои им верувате да пристапуваат до целата евиденција на уредот. \n\nАко не ѝ дозволите на апликацијава да пристапува до сите евиденции на уредот, сепак ќе може да пристапува до сопствената евиденција. Производителот на вашиот уред можеби сепак ќе може да пристапува до некои евиденции или податоци на уредот. Дознајте повеќе"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Дневниците за евиденција на уредот снимаат што се случува на вашиот уред. Апликациите може да ги користат овие дневници за евиденција за да наоѓаат и поправаат проблеми.\n\nНекои дневници за евиденција може да содржат чувствителни податоци, па затоа дозволете им пристап до сите дневници за евиденција на уредот само на апликациите во кои имате доверба. \n\nАко не ѝ дозволите на апликацијава да пристапува до сите дневници за евиденција на уредот, таа сепак ќе може да пристапува до сопствените дневници за евиденција. Производителот на вашиот уред можеби сепак ќе може да пристапува до некои дневници за евиденција или податоци на уредот."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Не прикажувај повторно"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> сака да прикажува делови од <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Измени"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Проверете ги активните апликации"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Не може да се пристапи до камерата на вашиот телефон од <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Не може да се пристапи до камерата на вашиот таблет од <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"До ова не може да се пристапи при стриминг. Наместо тоа, пробајте на вашиот телефон."</string>
<string name="system_locale_title" msgid="711882686834677268">"Стандардно за системот"</string>
</resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 08cc1fe..cb6903f 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ഫിംഗർപ്രിന്റ് പ്രവർത്തനം റദ്ദാക്കി."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ഉപയോക്താവ് റദ്ദാക്കിയ ഫിംഗർപ്രിന്റ് പ്രവർത്തനം."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"നിരവധി തവണ ശ്രമിച്ചു. പിന്നീട് വീണ്ടും ശ്രമിക്കുക."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"നിരവധി തവണ ശ്രമിച്ചതിനാൽ, ഫിംഗർപ്രിന്റ് സെൻസർ പ്രവർത്തനരഹിതമായി."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"വീണ്ടും ശ്രമിക്കൂ."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"വിരലടയാളങ്ങൾ എൻറോൾ ചെയ്തിട്ടില്ല."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ഈ ഉപകരണത്തിൽ ഫിംഗർപ്രിന്റ് സെൻസറില്ല."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> തയ്യാറാക്കുന്നു."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"അപ്ലിക്കേഷനുകൾ ആരംഭിക്കുന്നു."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"ബൂട്ട് ചെയ്യൽ പൂർത്തിയാകുന്നു."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"സജ്ജീകരണം തുടരണോ?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"നിങ്ങൾ പവർ ബട്ടൺ അമർത്തി — സാധാരണയായി ഇത് സ്ക്രീൻ ഓഫാകുന്നതിന് കാരണമാകും.\n\nനിങ്ങളുടെ ഫിംഗർപ്രിന്റ് സജ്ജീകരിക്കുമ്പോൾ മൃദുവായി ടാപ്പ് ചെയ്ത് നോക്കുക."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"സ്ക്രീൻ ഓഫാക്കുക"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"സജ്ജീകരണം തുടരുക"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"സ്ക്രീൻ ഓഫാക്കാൻ ടാപ്പ് ചെയ്യുക"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"സ്ക്രീൻ ഓഫാക്കുക"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"ഫിംഗർപ്രിന്റ് പരിശോധിച്ചുറപ്പിക്കൽ തുടരണോ?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"നിങ്ങൾ പവർ ബട്ടൺ അമർത്തി — സാധാരണയായി ഇത് സ്ക്രീൻ ഓഫാകുന്നതിന് കാരണമാകും.\n\nനിങ്ങളുടെ ഫിംഗർപ്രിന്റ് പരിശോധിച്ചുറപ്പിക്കാൻ മൃദുവായി ടാപ്പ് ചെയ്ത് നോക്കുക."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"സ്ക്രീൻ ഓഫാക്കുക"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"സജ്ജമാക്കാൻ ടാപ്പ് ചെയ്യുക"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"സജ്ജീകരിക്കാൻ തിരഞ്ഞെടുക്കുക"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"ഉപകരണം വീണ്ടും ഫോർമാറ്റ് ചെയ്യേണ്ടി വന്നേക്കാം. പുറത്തെടുക്കാൻ ടാപ്പ് ചെയ്യുക."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ഫോട്ടോകളും മീഡിയയും ട്രാൻസ്ഫർ ചെയ്യാൻ"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ഫോട്ടോകളും വീഡിയോകളും സംഗീതവും മറ്റും സംഭരിക്കുന്നതിന്"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"മീഡിയാ ഫയലുകൾ ബ്രൗസ് ചെയ്യുക"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g>-ൽ പ്രശ്നം"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> പ്രവർത്തിക്കുന്നില്ല"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"പരിഹരിക്കാൻ ടാപ്പ് ചെയ്യുക"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> കേടായി. പരിഹരിക്കാൻ തിരഞ്ഞെടുക്കുക."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"ഉപകരണം വീണ്ടും ഫോർമാറ്റ് ചെയ്യേണ്ടി വന്നേക്കാം. പുറത്തെടുക്കാൻ ടാപ്പ് ചെയ്യുക."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"പിന്തുണയില്ലാത്ത <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> കണ്ടെത്തി"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> പ്രവർത്തിക്കുന്നില്ല"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ഈ ഉപകരണം <xliff:g id="NAME">%s</xliff:g> പിന്തുണയ്ക്കുന്നതല്ല. പിന്തുണയുള്ള ഫോർമാറ്റിൽ സജ്ജമാക്കുന്നതിന് ടാപ്പുചെയ്യുക."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"സജ്ജീകരിക്കാൻ ടാപ്പ് ചെയ്യുക."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"പിന്തുണയ്ക്കുന്ന ഫോർമാറ്റിൽ <xliff:g id="NAME">%s</xliff:g> സജ്ജീകരിക്കാൻ തിരഞ്ഞെടുക്കുക."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"ഉപകരണം വീണ്ടും ഫോർമാറ്റ് ചെയ്യേണ്ടി വന്നേക്കാം"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> അപ്രതീക്ഷിതമായി നീക്കംചെയ്തു"</string>
@@ -1424,7 +1424,7 @@
<string name="ext_media_unmounting_notification_title" msgid="4147986383917892162">"<xliff:g id="NAME">%s</xliff:g> ഒഴിവാക്കുന്നു"</string>
<string name="ext_media_unmounting_notification_message" msgid="5717036261538754203">"നീക്കം ചെയ്യരുത്"</string>
<string name="ext_media_init_action" msgid="2312974060585056709">"സജ്ജമാക്കുക"</string>
- <string name="ext_media_unmount_action" msgid="966992232088442745">"നിരസിക്കുക"</string>
+ <string name="ext_media_unmount_action" msgid="966992232088442745">"ഒഴിവാക്കുക"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"അടുത്തറിയുക"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"ഔട്ട്പുട്ട് മാറുക"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> കാണുന്നില്ല"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"മേഖലാ മുൻഗണന"</string>
<string name="search_language_hint" msgid="7004225294308793583">"ഭാഷ ടൈപ്പ് ചെയ്യുക"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"നിര്ദ്ദേശിച്ചത്"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"നിർദ്ദേശിച്ചവ"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"എല്ലാ ഭാഷകളും"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"എല്ലാ പ്രദേശങ്ങളും"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"തിരയുക"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"എല്ലാ ഉപകരണ ലോഗുകളും ആക്സസ് ചെയ്യാൻ <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> എന്നതിനെ അനുവദിക്കണോ?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"ഒറ്റത്തവണ ആക്സസ് അനുവദിക്കുക"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"അനുവദിക്കരുത്"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"നിങ്ങളുടെ ഉപകരണത്തിൽ എന്തൊക്കെയാണ് സംഭവിക്കുന്നതെന്ന് ഉപകരണ ലോഗുകൾ റെക്കോർഡ് ചെയ്യുന്നു. പ്രശ്നങ്ങൾ കണ്ടെത്തി പരിഹരിക്കുന്നതിന് ആപ്പുകൾക്ക് ഈ ലോഗുകൾ ഉപയോഗിക്കാൻ കഴിയും.\n\nചില ലോഗുകളിൽ സൂക്ഷ്മമായി കൈകാര്യം ചെയ്യേണ്ട വിവരങ്ങൾ അടങ്ങിയിരിക്കാൻ സാധ്യതയുള്ളതിനാൽ, നിങ്ങൾക്ക് വിശ്വാസമുള്ള ആപ്പുകൾക്ക് മാത്രമേ എല്ലാ ഉപകരണ ലോഗുകളും ആക്സസ് ചെയ്യാൻ അനുമതി നൽകാവൂ. \n\nഎല്ലാ ഉപകരണ ലോഗുകളും ആക്സസ് ചെയ്യാൻ നിങ്ങൾ ഈ ആപ്പിനെ അനുവദിക്കുന്നില്ലെങ്കിൽ പോലും, ആപ്പിന് അതിന്റെ സ്വന്തം ലോഗുകൾ ആക്സസ് ചെയ്യാനാകും. നിങ്ങളുടെ ഉപകരണ നിർമ്മാതാവിനും നിങ്ങളുടെ ഉപകരണത്തിലെ ചില ലോഗുകളോ വിവരങ്ങളോ തുടർന്നും ആക്സസ് ചെയ്യാനായേക്കും. കൂടുതലറിയുക"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"ഉപകരണ ലോഗുകൾ നിങ്ങളുടെ ഉപകരണത്തിൽ എന്തൊക്കെയാണ് സംഭവിക്കുന്നതെന്ന് റെക്കോർഡ് ചെയ്യുന്നു. പ്രശ്നങ്ങൾ കണ്ടെത്തി പരിഹരിക്കുന്നതിന് ആപ്പുകൾക്ക് ഈ ലോഗുകൾ ഉപയോഗിക്കാൻ കഴിയും.\n\nചില ലോഗുകളിൽ സൂക്ഷ്മമായി കൈകാര്യം ചെയ്യേണ്ട വിവരങ്ങൾ അടങ്ങിയിരിക്കാൻ സാധ്യതയുള്ളതിനാൽ, എല്ലാ ഉപകരണ ലോഗുകളും ആക്സസ് ചെയ്യാനുള്ള അനുമതി നിങ്ങൾക്ക് വിശ്വാസമുള്ള ആപ്പുകൾക്ക് മാത്രം നൽകുക. \n\nഎല്ലാ ഉപകരണ ലോഗുകളും ആക്സസ് ചെയ്യാനുള്ള അനുവാദം നൽകിയില്ലെങ്കിലും, ഈ ആപ്പിന് അതിന്റെ സ്വന്തം ലോഗുകൾ ആക്സസ് ചെയ്യാനാകും. നിങ്ങളുടെ ഉപകരണ നിർമ്മാതാവിന് തുടർന്നും നിങ്ങളുടെ ഉപകരണത്തിലെ ചില ലോഗുകളോ വിവരങ്ങളോ ആക്സസ് ചെയ്യാനായേക്കും."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"വീണ്ടും കാണിക്കരുത്"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_2">%2$s</xliff:g> സ്ലൈസുകൾ കാണിക്കാൻ <xliff:g id="APP_0">%1$s</xliff:g> താൽപ്പര്യപ്പെടുന്നു"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"എഡിറ്റ് ചെയ്യുക"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"സജീവമായ ആപ്പുകൾ പരിശോധിക്കുക"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"നിങ്ങളുടെ <xliff:g id="DEVICE">%1$s</xliff:g> എന്നതിൽ നിന്ന് ഫോണിന്റെ ക്യാമറ ആക്സസ് ചെയ്യാനാകില്ല"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"നിങ്ങളുടെ <xliff:g id="DEVICE">%1$s</xliff:g> എന്നതിൽ നിന്ന് ടാബ്ലെറ്റിന്റെ ക്യാമറ ആക്സസ് ചെയ്യാനാകില്ല"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"സ്ട്രീം ചെയ്യുമ്പോൾ ഇത് ആക്സസ് ചെയ്യാനാകില്ല. പകരം നിങ്ങളുടെ ഫോണിൽ ശ്രമിച്ച് നോക്കൂ."</string>
<string name="system_locale_title" msgid="711882686834677268">"സിസ്റ്റം ഡിഫോൾട്ട്"</string>
</resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 1b4e960..9777619 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Хурууны хээний бүртгэл амжилтгүй боллоо."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Хэрэглэгч хурууны хээний баталгаажуулалтыг цуцалсан байна."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Хэтэрхий олон оролдлоо. Түр хүлээгээд дахин оролдоно уу."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Хэт олон удаа оролдсон тул хурууны хээ мэдрэгчийг идэвхгүй болголоо."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Дахин оролдно уу."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Бүртгүүлсэн хурууны хээ алга."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Энэ төхөөрөмжид хурууны хээ мэдрэгч алга."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Бэлдэж байна <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Апп-г эхлүүлж байна."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Эхлэлийг дуусгаж байна."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Тохируулгыг үргэлжлүүлэх үү?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Та асаах/унтраах товчийг дарсан байна — энэ нь ихэвчлэн дэлгэцийг унтраадаг.\n\nХурууны хээгээ тохируулж байх үедээ зөөлөн товшиж үзнэ үү."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Дэлгэцийг унтраах"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Тохируулгыг үргэлжлүүлэх"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Дэлгэцийг унтраахын тулд товшино уу"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Дэлгэцийг унтраах"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Хурууны хээгээ үргэлжлүүлэн баталгаажуулах уу?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Та асаах/унтраах товчийг дарсан байна — энэ нь ихэвчлэн дэлгэцийг унтраадаг.\n\nХурууны хээгээ баталгаажуулахын тулд зөөлөн товшиж үзнэ үү."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Дэлгэцийг унтраах"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Тохируулахын тулд товшино уу"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Тохируулахын тулд сонгоно уу"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Та төхөөрөмжийг дахин форматлах шаардлагатай байж болзошгүй. Салгахын тулд товшино уу."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Зураг, медиа шилжүүлэхэд зориулсан"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Зураг, видео, хөгжим болон бусад зүйлийг хадгалахад зориулагдсан"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Медиа файлуудыг үзэх"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> алдаатай байна"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ажиллахгүй байна"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Засахын тулд товшино уу"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> эвдэрсэн байна. Засахын тулд сонгоно уу."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Та төхөөрөмжийг дахин форматлах шаардлагатай байж болзошгүй. Салгахын тулд товшино уу."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Дэмжээгүй <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> илэрсэн"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ажиллахгүй байна"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Энэ төхөөрөмж нь <xliff:g id="NAME">%s</xliff:g>-г дэмждэггүй. Дэмжигдсэн хэлбэршүүлэлтэд тохируулахын тулд товшино уу."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Тохируулахын тулд товшино уу ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"<xliff:g id="NAME">%s</xliff:g>-г дэмжигдсэн форматаар тохируулахын тулд сонгоно уу."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Та төхөөрөмжийг дахин форматлах шаардлагатай байж болзошгүй"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>-ыг гэнэт гаргасан байна"</string>
@@ -1703,7 +1703,7 @@
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Товчлолыг унтраах"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Товчлол ашиглах"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Өнгө хувиргалт"</string>
- <string name="color_correction_feature_name" msgid="3655077237805422597">"Өнгөний засвар"</string>
+ <string name="color_correction_feature_name" msgid="3655077237805422597">"Өнгө тохируулга"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Нэг гарын горим"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Хэт бүүдгэр"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г асаалаа."</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Бүс нутгийн тохиргоо"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Улсын хэлийг бичнэ үү"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Санал болгосон"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Санал болгосон"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Бүх хэл"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Бүх бүс нутаг"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Хайх"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>-д төхөөрөмжийн бүх логт хандахыг зөвшөөрөх үү?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Нэг удаагийн хандалтыг зөвшөөрнө үү"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Бүү зөвшөөр"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Төхөөрөмжийн лог нь таны төхөөрөмж дээр юу болж байгааг бичдэг. Аппууд эдгээр логийг асуудлыг олох болон засахад ашиглах боломжтой.\n\nЗарим лог эмзэг мэдээлэл агуулж байж магадгүй тул та зөвхөн итгэдэг аппууддаа төхөөрөмжийн бүх логт хандахыг зөвшөөрнө үү. \n\nХэрэв та энэ аппад төхөөрөмжийн бүх логт хандахыг зөвшөөрөхгүй бол энэ нь өөрийн логт хандах боломжтой хэвээр байх болно. Tаны төхөөрөмж үйлдвэрлэгч таны төхөөрөмж дээрх зарим лог эсвэл мэдээлэлд хандах боломжтой хэвээр байж магадгүй. Нэмэлт мэдээлэл авах"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Төхөөрөмжийн лог нь таны төхөөрөмж дээр юу болж байгааг бичдэг. Аппууд эдгээр логийг асуудлыг олох болон засахад ашиглах боломжтой.\n\nЗарим лог эмзэг мэдээлэл агуулж байж магадгүй тул та зөвхөн итгэдэг аппууддаа төхөөрөмжийн бүх логт хандахыг зөвшөөрнө үү. \n\nХэрэв та энэ аппад төхөөрөмжийн бүх логт хандахыг зөвшөөрөхгүй бол энэ нь өөрийн логт хандах боломжтой хэвээр байх болно. Tаны төхөөрөмж үйлдвэрлэгч таны төхөөрөмж дээрх зарим лог эсвэл мэдээлэлд хандах боломжтой хэвээр байж магадгүй."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Дахиж бүү харуул"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> <xliff:g id="APP_2">%2$s</xliff:g>-н хэсгүүдийг (slices) харуулах хүсэлтэй байна"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Засах"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Идэвхтэй аппуудыг шалгах"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Таны <xliff:g id="DEVICE">%1$s</xliff:g>-с утасны камерт хандах боломжгүй"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Таны <xliff:g id="DEVICE">%1$s</xliff:g>-с таблетын камерт хандах боломжгүй"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Стримингийн үед үүнд хандах боломжгүй. Оронд нь утас дээрээ туршиж үзнэ үү."</string>
<string name="system_locale_title" msgid="711882686834677268">"Системийн өгөгдмөл"</string>
</resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 1d823fd..a464f84 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"फिंगरप्रिंट ऑपरेशन रद्द झाले."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"वापरकर्त्याने फिंगरप्रिंट ऑपरेशन रद्द केले."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"खूप प्रयत्न केले. नंतर पुन्हा प्रयत्न करा."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"खूप प्रयत्न करून झाले. फिंगरप्रिंट सेन्सर बंद आहे."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"पुन्हा प्रयत्न करा."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"कोणत्याही फिंगरप्रिंटची नोंद झाली नाही"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"या डिव्हाइसमध्ये फिंगरप्रिंट सेन्सर नाही."</string>
@@ -1011,7 +1012,7 @@
<string name="granularity_label_link" msgid="9007852307112046526">"लिंक"</string>
<string name="granularity_label_line" msgid="376204904280620221">"रेखा"</string>
<string name="factorytest_failed" msgid="3190979160945298006">"फॅक्टरी चाचणी अयशस्वी"</string>
- <string name="factorytest_not_system" msgid="5658160199925519869">"FACTORY_TEST क्रिया फक्त /सिस्टम/अॅप मध्ये इंस्टॉल केलेल्या पॅकेजसाठी समर्थित आहे."</string>
+ <string name="factorytest_not_system" msgid="5658160199925519869">"FACTORY_TEST कृती फक्त /सिस्टीम/अॅप मध्ये इंस्टॉल केलेल्या पॅकेजसाठी सपोर्ट आहे."</string>
<string name="factorytest_no_action" msgid="339252838115675515">"FACTORY_TEST क्रिया प्रदान करणारे कोणतेही पॅकेज आढळले नाही."</string>
<string name="factorytest_reboot" msgid="2050147445567257365">"रीबूट करा"</string>
<string name="js_dialog_title" msgid="7464775045615023241">"\"<xliff:g id="TITLE">%s</xliff:g>\" वरील पृष्ठ हे म्हणते:"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> तयार करत आहे."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"अॅप्स सुरू करत आहे."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"बूट समाप्त होत आहे."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"सेट करणे पुढे सुरू ठेवायचे का?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"तुम्ही पॉवर बटण दाबले — हे सहसा स्क्रीन बंद करते.\n\nतुमचे फिंगरप्रिंट सेट करताना हलके टॅप करून पहा."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"स्क्रीन बंद करा"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"सेट करणे सुरू ठेवा"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"स्क्रीन बंद करण्यासाठी टॅप करा"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"स्क्रीन बंद करा"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"फिंगरप्रिंट पडताळणी सुरू ठेवायची का?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"तुम्ही पॉवर बटण दाबले — हे सहसा स्क्रीन बंद करते.\n\nतुमच्या फिंगरप्रिंटची पडताळणी करण्यासाठी हलके टॅप करून पहा."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"स्क्रीन बंद करा"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"सेट करण्यासाठी टॅप करा"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"सेट अप करण्यासाठी निवडा"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"तुम्हाला डिव्हाइस पुन्हा फॉरमॅट करावे लागू शकते. बाहेर काढण्यासाठी टॅप करा."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"फोटो आणि मीडिया स्थानांतरित करण्यासाठी"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"फोटो, व्हिडिओ, संगीत आणि आणखी बरेच काही स्टोअर करण्यासाठी"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"मीडिया फाइल ब्राउझ करा"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> सह समस्या"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> काम करत नाही"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"दुरुस्त करण्यासाठी टॅप करा"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> दूषित आहे. निश्चित करण्यासाठी निवडा."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"तुम्हाला डिव्हाइस पुन्हा फॉरमॅट करावे लागू शकते. बाहेर काढण्यासाठी टॅप करा."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> असमर्थित"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> डिटेक्ट केले"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> काम करत नाही"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"हे डिव्हाइस <xliff:g id="NAME">%s</xliff:g> ला सपोर्ट करत नाही. सपोर्ट असलेल्या फॉरमॅटमध्ये सेट करण्यासाठी टॅप करा."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"सेट करण्यासाठी टॅप करा."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"सपोर्ट असलेल्या फॉरमॅटमध्ये <xliff:g id="NAME">%s</xliff:g> सेट करण्यासाठी निवडा."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"तुम्हाला डिव्हाइस पुन्हा फॉरमॅट करावे लागू शकते"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> अनपेक्षितरित्या काढले"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"प्रदेश प्राधान्य"</string>
<string name="search_language_hint" msgid="7004225294308793583">"भाषा नाव टाइप करा"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"सुचवलेल्या भाषा"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"सुचवलेले"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"सर्व भाषा"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"सर्व प्रदेश"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"शोध"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ला सर्व डिव्हाइस लॉग अॅक्सेस करण्याची अनुमती द्यायची आहे का?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"एक वेळ अॅक्सेसची अनुमती द्या"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"अनुमती देऊ नका"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"तुमच्या डिव्हाइसवर काय होते ते डिव्हाइस लॉग रेकॉर्ड करते. समस्या शोधण्यासाठी आणि त्यांचे निराकरण करण्याकरिता ॲप्स हे लॉग वापरू शकतात.\n\nकाही लॉगमध्ये संवेदनशील माहिती असू शकते, त्यामुळे फक्त तुमचा विश्वास असलेल्या ॲप्सना सर्व डिव्हाइस लॉग अॅक्सेस करण्याची अनुमती द्या. \n\nतुम्ही या ॲपला सर्व डिव्हाइस लॉग अॅक्सेस करण्याची अनुमती न दिल्यास, ते तरीही त्याचा स्वतःचा लॉग अॅक्सेस करू शकते. तुमच्या डिव्हाइसचा उत्पादक तरीही काही लॉग किंवा तुमच्या डिव्हाइसवरील माहिती अॅक्सेस करू शकतो. अधिक जाणून घ्या"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"तुमच्या डिव्हाइसवर काय होते ते डिव्हाइस लॉग रेकॉर्ड करते. समस्या शोधण्यासाठी आणि त्यांचे निराकरण करण्याकरिता ॲप्स हे लॉग वापरू शकतात.\n\nकाही लॉगमध्ये संवेदनशील माहिती असू शकते, त्यामुळे फक्त तुमचा विश्वास असलेल्या ॲप्सना सर्व डिव्हाइस लॉग अॅक्सेस करण्याची अनुमती द्या. \n\nतुम्ही या ॲपला सर्व डिव्हाइस लॉग अॅक्सेस करण्याची अनुमती न दिल्यास, ते तरीही त्याचा स्वतःचा लॉग अॅक्सेस करू शकते. तुमच्या डिव्हाइसचा उत्पादक तरीही काही लॉग किंवा तुमच्या डिव्हाइसवरील माहिती अॅक्सेस करू शकतो."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"पुन्हा दाखवू नका"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> ला <xliff:g id="APP_2">%2$s</xliff:g> चे तुकडे दाखवायचे आहेत"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"संपादित करा"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ॲक्टिव्ह ॲप्स पहा"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"तुमच्या <xliff:g id="DEVICE">%1$s</xliff:g> वरून फोनचा कॅमेरा अॅक्सेस करू शकत नाही"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"तुमच्या <xliff:g id="DEVICE">%1$s</xliff:g> वरून टॅबलेटचा कॅमेरा अॅक्सेस करू शकत नाही"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"स्ट्रीम करताना हे अॅक्सेस केले जाऊ शकत नाही. त्याऐवजी तुमच्या फोनवर अॅक्सेस करून पहा."</string>
<string name="system_locale_title" msgid="711882686834677268">"सिस्टीम डीफॉल्ट"</string>
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 69d2ddb..c9d9cad 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -301,7 +301,7 @@
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"mengakses kenalan anda"</string>
<string name="permgrouplab_location" msgid="1858277002233964394">"Lokasi"</string>
<string name="permgroupdesc_location" msgid="1995955142118450685">"mengakses lokasi peranti ini"</string>
- <string name="permgrouplab_calendar" msgid="6426860926123033230">"Kalendar"</string>
+ <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
<string name="permgroupdesc_calendar" msgid="6762751063361489379">"mengakses kalendar"</string>
<string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
<string name="permgroupdesc_sms" msgid="5726462398070064542">"menghantar dan melihat mesej SMS"</string>
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Pengendalian cap jari dibatalkan."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Pengendalian cap jari dibatalkan oleh pengguna."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Terlalu banyak percubaan. Cuba sebentar lagi."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Terlalu banyak percubaan. Penderia cap jari dilumpuhkan."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Cuba lagi."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Tiada cap jari didaftarkan."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Peranti ini tiada penderia cap jari."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Menyediakan <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Memulakan apl."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"But akhir."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Teruskan persediaan?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Anda menekan butang kuasa — tindakan ini biasanya mematikan skrin.\n\nCuba ketik dengan perlahan semasa menetapkan cap jari anda."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Matikan skrin"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Teruskan persediaan"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Ketik untuk mematikan skrin"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Matikan skrin"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Terus mengesahkan cap jari anda?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Anda menekan butang kuasa — tindakan ini biasanya mematikan skrin.\n\nCuba ketik dengan perlahan untuk mengesahkan cap jari anda."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Matikan skrin"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Ketik untuk menyediakan"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Pilih untuk penyediaan"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Anda mungkin perlu memformatkan semula peranti. Ketik untuk mengeluarkan media."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Untuk memindahkan foto dan media"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Untuk menyimpan foto, video, muzik dan banyak lagi"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Semak imbas fail media"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Isu dengan <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> tidak berfungsi"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Ketik untuk menyelesaikan masalah"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> rosak. Pilih untuk baiki."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Anda mungkin perlu memformatkan semula peranti. Ketik untuk mengeluarkan media."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> tidak disokong"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> dikesan"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> tidak berfungsi"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Peranti ini tidak menyokong <xliff:g id="NAME">%s</xliff:g> ini. Ketik untuk menyediakannya dalam format yang disokong."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Ketik untuk membuat persediaan."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Pilih untuk menyediakan <xliff:g id="NAME">%s</xliff:g> dalam format yang disokong."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Anda mungkin perlu memformatkan semula peranti"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ditanggalkan tanpa dijangka"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Pilihan wilayah"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Taipkan nama bahasa"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Dicadangkan"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Dicadangkan"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Semua bahasa"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Semua rantau"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Cari"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Benarkan <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> mengakses semua log peranti?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Benarkan akses satu kali"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Jangan benarkan"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Log peranti merekodkan perkara yang berlaku pada peranti anda. Apl dapat menggunakan log ini untuk menemukan dan membetulkan isu.\n\nSesetengah log mungkin mengandungi maklumat sensitif, jadi benarkan apl yang anda percaya sahaja untuk mengakses semua log peranti. \n\nJika anda tidak membenarkan apl ini mengakses semua log peranti, apl masih boleh mengakses log sendiri. Pengilang peranti anda mungkin masih boleh mengakses sesetengah log atau maklumat pada peranti anda. Ketahui lebih lanjut"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Log peranti merekodkan perkara yang berlaku pada peranti anda. Apl dapat menggunakan log ini untuk menemukan dan membetulkan isu.\n\nSesetengah log mungkin mengandungi maklumat sensitif, jadi benarkan apl yang anda percaya sahaja untuk mengakses semua log peranti. \n\nJika anda tidak membenarkan apl ini mengakses semua log peranti, apl masih boleh mengakses log sendiri. Pengilang peranti anda mungkin masih dapat mengakses sesetengah log atau maklumat pada peranti anda."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Jangan tunjuk lagi"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> mahu menunjukkan <xliff:g id="APP_2">%2$s</xliff:g> hirisan"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Edit"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Semak apl aktif"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Tidak dapat mengakses kamera telefon daripada <xliff:g id="DEVICE">%1$s</xliff:g> anda"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Tidak dapat mengakses kamera tablet daripada <xliff:g id="DEVICE">%1$s</xliff:g> anda"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Kandungan ini tidak boleh diakses semasa penstriman. Cuba pada telefon anda."</string>
<string name="system_locale_title" msgid="711882686834677268">"Lalai sistem"</string>
</resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 06688b8..160ede0 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -266,7 +266,7 @@
<string name="global_action_settings" msgid="4671878836947494217">"ဆက်တင်များ"</string>
<string name="global_action_assist" msgid="2517047220311505805">"အကူအညီ"</string>
<string name="global_action_voice_assist" msgid="6655788068555086695">"အသံ အကူအညီ"</string>
- <string name="global_action_lockdown" msgid="2475471405907902963">"ချိတ်ပိတ်ရန်"</string>
+ <string name="global_action_lockdown" msgid="2475471405907902963">"လော့ခ်ဒေါင်း"</string>
<string name="status_bar_notification_info_overflow" msgid="3330152558746563475">"၉၉၉+"</string>
<string name="notification_hidden_text" msgid="2835519769868187223">"အကြောင်းကြားချက်အသစ်"</string>
<string name="notification_channel_virtual_keyboard" msgid="6465975799223304567">"ပကတိအသွင်ကီးဘုတ်"</string>
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"လက်ဗွေယူခြင်း ပယ်ဖျက်လိုက်သည်။"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"လက်ဗွေဖြင့် အထောက်အထားစိစစ်ခြင်းကို အသုံးပြုသူက ပယ်ဖျက်ထားသည်။"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"ကြိုးစာမှု အကြိမ်များနေ၏။ နောက်မှ ထပ်မံကြိုးစားပါ။"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"အကြိမ်အရေအတွက် အလွန်များနေပါပြီ။ လက်ဗွေအာရုံခံကိရိယာ ပိတ်ထားပါသည်။"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ပြန်ကြိုးစားပါ"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"မည်သည့် လက်ဗွေကိုမျှ ထည့်သွင်းမထားပါ။"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ဤစက်တွင် လက်ဗွေအာရုံခံကိရိယာ မရှိပါ။"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> အားပြင်ဆင်နေသည်။"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"အက်ပ်များကို စတင်နေ"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"လုပ်ငန်းစနစ်ထည့်သွင်း၍ ပြန်လည်စတင်ရန် ပြီးပါပြီ"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"ဆက်လက်၍ စနစ်ထည့်သွင်းလိုပါသလား။"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ဖွင့်ပိတ်ခလုတ်ကို သင်နှိပ်ခဲ့သည် — ၎င်းက ပုံမှန်အားဖြင့် စခရင်ကို ပိတ်စေသည်။\n\nသင့်လက်ဗွေကို ထည့်သွင်းသောအခါ ဖွဖွတို့ကြည့်ပါ။"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"စခရင် ပိတ်ရန်"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"စနစ်ဆက်ထည့်သွင်းရန်"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ဖန်သားပြင်ပိတ်ရန် တို့ပါ"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ဖန်သားပြင် ပိတ်ရန်"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"သင့်လက်ဗွေကို ဆက်၍ အတည်ပြုမလား။"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"ဖွင့်ပိတ်ခလုတ်ကို သင်နှိပ်ခဲ့သည် — ၎င်းက ပုံမှန်အားဖြင့် စခရင်ကို ပိတ်စေသည်။\n\nသင့်လက်ဗွေကို အတည်ပြုရန် ဖွဖွတို့ကြည့်ပါ။"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"စခရင် ပိတ်ရန်"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"စနစ်ထည့်သွင်းရန် တို့ပါ"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"စနစ်ထည့်သွင်းရန် ရွေးပါ"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"စက်ကို ပြန်လည်ဖော်မက်လုပ်ရန် လိုအပ်နိုင်သည်။ ပယ်ရန် တို့ပါ။"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ဓာတ်ပုံနှင့် မီဒီယာများ လွှဲပြောင်းရန်အတွက်"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ဓာတ်ပုံ၊ ဗီဒီယို၊ သီချင်းစသည်တို့ သိမ်းရန်အတွက်"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"မီဒီယာဖိုင်များကို ရှာကြည့်ပါ"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> တွင် ပြဿနာရှိနေသည်"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> အလုပ်မလုပ်ပါ"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"ပြင်ဆင်ရန်အတွက် ထိလိုက်ပါ"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> ပျက်နေပါသည်။ ပြင်ရန် ရွေးချယ်ပါ။"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"စက်ကို ပြန်လည်ဖော်မက်လုပ်ရန် လိုအပ်နိုင်သည်။ ပယ်ရန် တို့ပါ။"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"ပံ့ပိုးထားခြင်း မရှိသော <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> တွေ့ပါသည်"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> အလုပ်မလုပ်ပါ"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ဤစက်ပစ္စည်းတွင် <xliff:g id="NAME">%s</xliff:g> ကိုအသုံးပြု၍မရပါ။ အသုံးပြု၍ရသော စနစ်ပုံစံသို့သတ်မှတ်ရန် တို့ပါ။"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"စနစ်ထည့်သွင်းရန် တို့ပါ ။"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"<xliff:g id="NAME">%s</xliff:g> ကို ပံ့ပိုးထားသောဖော်မက်ဖြင့် စနစ်ထည့်သွင်းရန် ရွေးပါ။"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"စက်ကို ပြန်လည်ဖော်မက်လုပ်ရန် လိုအပ်နိုင်သည်"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> မမျှော်လင့်ဘဲ ဖယ်ရှားခဲ့သည်"</string>
@@ -1424,11 +1424,11 @@
<string name="ext_media_unmounting_notification_title" msgid="4147986383917892162">"<xliff:g id="NAME">%s</xliff:g> ကို ထုတ်နေသည်"</string>
<string name="ext_media_unmounting_notification_message" msgid="5717036261538754203">"မဖယ်ရှားပါနှင့်"</string>
<string name="ext_media_init_action" msgid="2312974060585056709">"သတ်မှတ်ရန်"</string>
- <string name="ext_media_unmount_action" msgid="966992232088442745">"ထုတ်မည်"</string>
+ <string name="ext_media_unmount_action" msgid="966992232088442745">"ထုတ်ရန်"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"စူးစမ်းရန်"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"မီဒီယာအထွက် ပြောင်းရန်"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> ပျောက်နေသည်"</string>
- <string name="ext_media_missing_message" msgid="4408988706227922909">"စက်ပစ္စည်းကို ထပ်မံထည့်သွင်းပါ"</string>
+ <string name="ext_media_missing_message" msgid="4408988706227922909">"ကတ်ကို ထပ်မံထည့်သွင်းပါ"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"<xliff:g id="NAME">%s</xliff:g> ရွှေ့နေစဉ်"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"ဒေတာများ ရွှေ့နေစဉ်"</string>
<string name="ext_media_move_success_title" msgid="4901763082647316767">"အကြောင်းအရာ လွှဲပြောင်းပြီးပါပြီ"</string>
@@ -1438,7 +1438,7 @@
<string name="ext_media_status_removed" msgid="241223931135751691">"ဖယ်ရှာပြီး"</string>
<string name="ext_media_status_unmounted" msgid="8145812017295835941">"ဖယ်ထုတ်ပြီး၏"</string>
<string name="ext_media_status_checking" msgid="159013362442090347">"စစ်ဆေးနေပါသည်…"</string>
- <string name="ext_media_status_mounted" msgid="3459448555811203459">"အသင့့်ဖြစ်နေ"</string>
+ <string name="ext_media_status_mounted" msgid="3459448555811203459">"အသင့်ဖြစ်ပြီ"</string>
<string name="ext_media_status_mounted_ro" msgid="1974809199760086956">"ဖတ်ရန်အတွက်သာ"</string>
<string name="ext_media_status_bad_removal" msgid="508448566481406245">"လုံခြုံမှုမရှိစွာ ဖယ်ရှားခဲ့၏"</string>
<string name="ext_media_status_unmountable" msgid="7043574843541087748">"ပျက်စီးသွား၏"</string>
@@ -1857,8 +1857,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"သင်၏ စီမံခန့်ခွဲသူက အပ်ဒိတ်လုပ်ထားသည်"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"သင်၏ စီမံခန့်ခွဲသူက ဖျက်လိုက်ပါပြီ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"‘ဘက်ထရီ အားထိန်း’ က ‘မှောင်သည့် အပြင်အဆင်’ ကို ဖွင့်ပြီး နောက်ခံလုပ်ဆောင်ချက်၊ ပြသမှုဆိုင်ရာ အထူးပြုလုပ်ချက်အချို့၊ ဝန်ဆောင်မှုအချို့နှင့် ကွန်ရက်ချိတ်ဆက်မှုအချို့တို့ကို ကန့်သတ်သည် သို့မဟုတ် ပိတ်သည်။"</string>
- <string name="battery_saver_description" msgid="8518809702138617167">"‘ဘက်ထရီ အားထိန်း’ က ‘မှောင်သည့် အပြင်အဆင်’ ကို ဖွင့်ပြီး နောက်ခံလုပ်ဆောင်ချက်၊ ပြသမှုဆိုင်ရာ အထူးပြုလုပ်ချက်အချို့၊ ဝန်ဆောင်မှုအချို့နှင့် ကွန်ရက်ချိတ်ဆက်မှုအချို့တို့ကို ကန့်သတ်သည် သို့မဟုတ် ပိတ်သည်။"</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"‘ဘက်ထရီ အားထိန်း’ က ‘အမှောင်နောက်ခံ’ ကို ဖွင့်ပြီး နောက်ခံလုပ်ဆောင်ချက်၊ ပြသမှုဆိုင်ရာ အထူးပြုလုပ်ချက်အချို့၊ ဝန်ဆောင်မှုအချို့နှင့် ကွန်ရက်ချိတ်ဆက်မှုအချို့တို့ကို ကန့်သတ်သည် သို့မဟုတ် ပိတ်သည်။"</string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"‘ဘက်ထရီ အားထိန်း’ က ‘အမှောင်နောက်ခံ’ ကို ဖွင့်ပြီး နောက်ခံလုပ်ဆောင်ချက်၊ ပြသမှုဆိုင်ရာ အထူးပြုလုပ်ချက်အချို့၊ ဝန်ဆောင်မှုအချို့နှင့် ကွန်ရက်ချိတ်ဆက်မှုအချို့တို့ကို ကန့်သတ်သည် သို့မဟုတ် ပိတ်သည်။"</string>
<string name="data_saver_description" msgid="4995164271550590517">"ဒေတာအသုံးလျှော့ချနိုင်ရန်အတွက် အက်ပ်များကို နောက်ခံတွင် ဒေတာပို့ခြင်းနှင့် လက်ခံခြင်းမပြုရန် \'ဒေတာချွေတာမှု\' စနစ်က တားဆီးထားပါသည်။ ယခုအက်ပ်ဖြင့် ဒေတာအသုံးပြုနိုင်သော်လည်း အကြိမ်လျှော့၍သုံးရပါမည်။ ဥပမာ၊ သင်က မတို့မချင်း ပုံများပေါ်လာမည် မဟုတ်ပါ။"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"ဒေတာချွေတာမှုစနစ် ဖွင့်မလား။"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"ဖွင့်ရန်"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"ဒေသရွေးချယ်မှု"</string>
<string name="search_language_hint" msgid="7004225294308793583">"ဘာသာစကားအမည် ထည့်ပါ"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"အကြံပြုထားသည်"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"အကြံပြုထားသည်"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"ဘာသာစကားအားလုံး"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"ဒေသအားလုံး"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"ရှာဖွေရန်"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ကို စက်မှတ်တမ်းအားလုံး သုံးခွင့်ပြုမလား။"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"တစ်ခါသုံး ဝင်ခွင့်ပေးရန်"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"ခွင့်မပြုပါ"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"သင့်စက်ရှိ အဖြစ်အပျက်များကို စက်မှတ်တမ်းများက မှတ်တမ်းတင်သည်။ အက်ပ်များက ပြဿနာများ ရှာဖွေပြီးဖြေရှင်းရန် ဤမှတ်တမ်းများကို သုံးနိုင်သည်။\n\nအချို့မှတ်တမ်းများတွင် သတိထားရမည့်အချက်အလက်များ ပါဝင်နိုင်သဖြင့် စက်မှတ်တမ်းအားလုံးကို ယုံကြည်ရသည့် အက်ပ်များကိုသာ သုံးခွင့်ပြုပါ။ \n\nဤအက်ပ်ကို စက်မှတ်တမ်းအားလုံး သုံးခွင့်မပြုသော်လည်း ၎င်းက ၎င်း၏ကိုယ်ပိုင်မှတ်တမ်းကို သုံးနိုင်ဆဲဖြစ်သည်။ သင့်စက်ရှိ အချို့မှတ်တမ်းများ (သို့) အချက်အလက်များကို သင့်စက်ထုတ်လုပ်သူက သုံးနိုင်ပါသေးသည်။ ပိုမိုလေ့လာရန်"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"သင့်စက်ရှိ အဖြစ်အပျက်များကို စက်မှတ်တမ်းများက မှတ်တမ်းတင်သည်။ အက်ပ်များက ပြဿနာများ ရှာဖွေပြီးဖြေရှင်းရန် ဤမှတ်တမ်းများကို သုံးနိုင်သည်။\n\nအချို့မှတ်တမ်းများတွင် သတိထားရမည့်အချက်အလက်များ ပါဝင်နိုင်သဖြင့် စက်မှတ်တမ်းအားလုံးကို ယုံကြည်ရသည့် အက်ပ်များကိုသာ သုံးခွင့်ပြုပါ။ \n\nဤအက်ပ်ကို စက်မှတ်တမ်းအားလုံး သုံးခွင့်မပြုသော်လည်း ၎င်းက ၎င်း၏ကိုယ်ပိုင်မှတ်တမ်းကို သုံးနိုင်ဆဲဖြစ်သည်။ သင့်စက်ရှိ အချို့မှတ်တမ်းများ (သို့) အချက်အလက်များကို သင့်စက်ထုတ်လုပ်သူက သုံးနိုင်ပါသေးသည်။"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"နောက်ထပ်မပြပါနှင့်"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> သည် <xliff:g id="APP_2">%2$s</xliff:g> ၏အချပ်များကို ပြသလိုသည်"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"တည်းဖြတ်ရန်"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ပွင့်နေသည့်အက်ပ်များ စစ်ဆေးရန်"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"သင်၏ <xliff:g id="DEVICE">%1$s</xliff:g> မှ ဖုန်းကင်မရာကို သုံး၍မရပါ"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"သင်၏ <xliff:g id="DEVICE">%1$s</xliff:g> မှ တက်ဘလက်ကင်မရာကို သုံး၍မရပါ"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"တိုက်ရိုက်လွှင့်နေစဉ် ၎င်းကို မသုံးနိုင်ပါ။ ၎င်းအစား ဖုန်းတွင် စမ်းကြည့်ပါ။"</string>
<string name="system_locale_title" msgid="711882686834677268">"စနစ်မူရင်း"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 99b6d74..c0eb64c 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -139,7 +139,7 @@
<string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="8383917598312067365">"Wifi-anrop | <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="wfcSpnFormat_spn_vowifi" msgid="6865214948822061486">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
<string name="wfcSpnFormat_wifi_calling" msgid="6178935388378661755">"Wifi-anrop"</string>
- <string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"Wi-Fi"</string>
+ <string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"Wifi"</string>
<string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"Wifi-anrop"</string>
<string name="wfcSpnFormat_vowifi" msgid="8371335230890725606">"VoWifi"</string>
<string name="wifi_calling_off_summary" msgid="5626710010766902560">"Av"</string>
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingeravtrykk-operasjonen ble avbrutt."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingeravtrykk-operasjonen ble avbrutt av brukeren."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"For mange forsøk. Prøv på nytt senere."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"For mange forsøk. Fingeravtrykkssensoren er slått av."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Prøv på nytt."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Ingen fingeravtrykk er registrert."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Denne enheten har ikke fingeravtrykkssensor."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Forbereder <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starter apper."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Ferdigstiller oppstart."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Vil du fortsette konfigureringen?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Du har trykket på av/på-knappen – dette slår vanligvis av skjermen.\n\nPrøv å trykke lett mens du konfigurerer fingeravtrykket ditt."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Slå av skjermen"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Fortsett konfig."</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Trykk for å slå av skjermen"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Slå av skjermen"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Fortsett bekreftelse av fingeravtrykket?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Du har trykket på av/på-knappen – dette slår vanligvis av skjermen.\n\nPrøv å trykke lett for å bekrefte fingeravtrykket ditt."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Slå av skjermen"</string>
@@ -1309,7 +1309,7 @@
<string name="network_switch_metered_toast" msgid="501662047275723743">"Byttet fra <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> til <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
<string-array name="network_switch_type_name">
<item msgid="2255670471736226365">"mobildata"</item>
- <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="5520925862115353992">"Wifi"</item>
<item msgid="1055487873974272842">"Bluetooth"</item>
<item msgid="1616528372438698248">"Ethernet"</item>
<item msgid="9177085807664964627">"VPN"</item>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Trykk for å konfigurere"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Velg for å konfigurere"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Du må muligens reformatere enheten. Trykk for å løse ut."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"For overføring av bilder og medier"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"For lagring av bilder, videoer, musikk med mer"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Bla gjennom mediefiler"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problem med <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> fungerer ikke"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Trykk for å løse problemet"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> er skadet. Velg for å fikse."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Du må muligens reformatere enheten. Trykk for å løse ut."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> som ikke støttes"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> er oppdaget"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> fungerer ikke"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Denne enheten støtter ikke <xliff:g id="NAME">%s</xliff:g>. Trykk for å konfigurere i et støttet format."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Trykk for å konfigurere."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Velg for å konfigurere <xliff:g id="NAME">%s</xliff:g> i et format som støttes."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Du må muligens reformatere enheten"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ble uventet fjernet"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Regionsinnstilling"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Skriv inn språknavn"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Foreslått"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Foreslått"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Alle språk"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Alle områder"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Søk"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Vil du gi <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> tilgang til alle enhetslogger?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Gi éngangstilgang"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Ikke tillat"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Enhetslogger registrerer det som skjer på enheten din. Apper kan bruke disse loggene til å finne og løse problemer.\n\nNoen logger kan inneholde sensitiv informasjon, så du bør bare gi tilgang til alle enhetslogger til apper du stoler på. \n\nHvis du ikke gir denne appen tilgang til alle enhetslogger, har den fremdeles tilgang til sine egne logger. Enhetsprodusenten kan fremdeles ha tilgang til noen logger eller noe informasjon på enheten din. Finn ut mer"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Enhetslogger registrerer det som skjer på enheten din. Apper kan bruke disse loggene til å finne og løse problemer.\n\nNoen logger kan inneholde sensitiv informasjon, så du bør bare gi tilgang til alle enhetslogger til apper du stoler på. \n\nHvis du ikke gir denne appen tilgang til alle enhetslogger, har den fortsatt tilgang til sine egne logger. Enhetsprodusenten kan fortsatt ha tilgang til visse logger eller noe informasjon på enheten din."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ikke vis igjen"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> vil vise <xliff:g id="APP_2">%2$s</xliff:g>-utsnitt"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Endre"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Sjekk aktive apper"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Det er ikke mulig å få tilgang til telefonkameraet fra <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Det er ikke mulig å få tilgang til kameraet på nettbrettet fra <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Dette er ikke tilgjengelig under strømming. Prøv på telefonen i stedet."</string>
<string name="system_locale_title" msgid="711882686834677268">"Systemstandard"</string>
</resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 594807d..1a40845 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -373,7 +373,7 @@
<string name="permdesc_sendSms" msgid="6757089798435130769">"एपलाई SMS सन्देशहरू पठाउन अनुमति दिन्छ। यसले अप्रत्यासित चार्जहरूको परिणाम दिन सक्दछ। खराब एपहरूले तपाईंको पुष्टि बिना सन्देशहरू पठाएर तपाईंको पैसा खर्च गराउन सक्दछ।"</string>
<string name="permlab_readSms" msgid="5164176626258800297">"तपाईंका टेक्स्ट म्यासेजहरू (SMS वा MMS) पढ्नुहोस्"</string>
<string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"यस एपले तपाईंको ट्याब्लेटमा भण्डारण गरिएका सबै SMS (पाठ) सन्देशहरू पढ्न सक्छ।"</string>
- <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"यस एपले तपाईंको Android टिभी डिभाइसमा भण्डार गरिएका सबै SMS.(पाठ) सन्देशहरू पढ्न सक्छ।"</string>
+ <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"यस एपले तपाईंको Android टिभी डिभाइसमा भण्डारण गरिएका सबै SMS.(पाठ) सन्देशहरू पढ्न सक्छ।"</string>
<string name="permdesc_readSms" product="default" msgid="774753371111699782">"यस एपले तपाईंको फोनमा भण्डारण गरिएका सबै SMS (पाठ) सन्देशहरू पढ्न सक्छ।"</string>
<string name="permlab_receiveWapPush" msgid="4223747702856929056">"टेक्स्ट म्यासेजहरू (WAP) प्राप्त गर्नुहोस्"</string>
<string name="permdesc_receiveWapPush" msgid="1638677888301778457">"WAP सन्देशहरू प्राप्त गर्न र प्रशोधन गर्न एपलाई अनुमति दिन्छ। यो अनुमतिमा मोनिटर गर्ने वा तपाईँलाई पठाइएका म्यासेजहरू तपाईँलाई नदेखाई मेट्ने क्षमता समावेश हुन्छ।"</string>
@@ -412,9 +412,9 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"एपलाई प्रसारण समाप्त भइसकेपछि पनि रहिरहने स्टिकी प्रसारणहरू पठाउने अनुमति दिन्छ। यो सुविधाको अत्यधिक प्रयोगले धेरै मेमोरी प्रयोग हुने भएकाले तपाईंको Android टिभी यन्त्र सुस्त वा अस्थिर हुन सक्छ।"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"औपचारिक प्रसारणलाई पठाउनको लागि एक एपलाई अनुमति दिन्छ, जुन प्रसारण समाप्त भएपछि बाँकी रहन्छ। अत्यधिक प्रयोगले धेरै मेमोरी प्रयोग गरेको कारणले फोनलाई ढिलो र अस्थिर बनाउन सक्छ।"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"तपाईँका सम्पर्कहरू पढ्नुहोस्"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"एपलाई तपाईंको ट्याब्लेटमा भण्डार गरिएका सम्पर्क ठेगानाहरूसँग सम्बन्धित डेटा पढ्ने अनुमति दिन्छ। एपहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको ट्याब्लेटमा भण्डार गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका एपहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले एपहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सेभ गर्न दिने भएकाले हानिकारक एपहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
- <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"एपलाई तपाईंको Android टिभी डिभाइसमा भण्डारण गरिएका सम्पर्क ठेगानासम्बन्धी डेटा पढ्न अनुमति दिन्छ। एपहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको Android टिभी डिभाइसमा भण्डार गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका एपहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले एपहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सेभ गर्न दिने भएकाले हानिकारक एपहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
- <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"एपलाई तपाईंको फोनमा भण्डार गरिएका सम्पर्क ठेगानाहरूसँग सम्बन्धित डेटा पढ्ने अनुमति दिन्छ। एपहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको फोनमा भण्डार गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका एपहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले एपहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सेभ गर्न दिने भएकाले हानिकारक एपहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"एपलाई तपाईंको ट्याब्लेटमा भण्डारण गरिएका सम्पर्क ठेगानाहरूसँग सम्बन्धित डेटा पढ्ने अनुमति दिन्छ। एपहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको ट्याब्लेटमा भण्डारण गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका एपहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले एपहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सेभ गर्न दिने भएकाले हानिकारक एपहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"एपलाई तपाईंको Android टिभी डिभाइसमा भण्डारण गरिएका सम्पर्क ठेगानासम्बन्धी डेटा पढ्न अनुमति दिन्छ। एपहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको Android टिभी डिभाइसमा भण्डारण गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका एपहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले एपहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सेभ गर्न दिने भएकाले हानिकारक एपहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"एपलाई तपाईंको फोनमा भण्डारण गरिएका सम्पर्क ठेगानाहरूसँग सम्बन्धित डेटा पढ्ने अनुमति दिन्छ। एपहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको फोनमा भण्डारण गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका एपहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले एपहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सेभ गर्न दिने भएकाले हानिकारक एपहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"तपाईँका सम्पर्कहरू परिवर्तन गर्नुहोस्"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"एपलाई तपाईंको ट्याब्लेटमा भण्डारण गरिएका सम्पर्क ठेगानासम्बन्धी डेटा परिमार्जन गर्न अनुमति दिन्छ। यो अनुमतिले एपलाई सम्पर्क ठेगानासम्बन्धी डेटा मेटाउन अनुमति दिन्छ।"</string>
<string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"एपलाई तपाईंको Android टिभी डिभाइसमा भण्डारण गरिएका सम्पर्क ठेगानासम्बन्धी डेटा परिमार्जन गर्न अनुमति दिन्छ। यो अनुमतिले एपलाई सम्पर्क ठेगानासम्बन्धी डेटा मेटाउन अनुमति दिन्छ।"</string>
@@ -431,7 +431,7 @@
<string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"यसले यो एप ब्याकग्राउन्डमा चलेका बेला यसलाई हृदयको गति, शरीरको तापक्रम तथा रगतमा रहेको अक्सिजनको प्रतिशत जस्ता बडी सेन्सरसम्बन्धी डेटा हेर्ने तथा प्रयोग गर्ने अनुमति दिन्छ।"</string>
<string name="permlab_readCalendar" msgid="6408654259475396200">"पात्रोका कार्यक्रम र विवरणहरू पढ्ने"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"यस एपले तपाईंको ट्याब्लेटमा भण्डारण गरिएका पात्रो सम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान प्रदान वा सुरक्षित गर्न सक्छ।"</string>
- <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"यस एपले तपाईंको Android टिभी डिभाइसमा भण्डार गरिएका पात्रोसम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान प्रदान वा सुरक्षित गर्न सक्छ।"</string>
+ <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"यस एपले तपाईंको Android टिभी डिभाइसमा भण्डारण गरिएका पात्रोसम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान प्रदान वा सुरक्षित गर्न सक्छ।"</string>
<string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"यस एपले तपाईंको फोनमा भण्डारण गरिएका पात्रो सम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान प्रदान वा सुरक्षित गर्न सक्छ।"</string>
<string name="permlab_writeCalendar" msgid="6422137308329578076">"पात्रो घटनाहरू थप्नुहोस् वा परिमार्जन गर्नुहोस् र मालिकको ज्ञान बिना नै पाहुनाहरूलाई इमेल पठाउनुहोस्"</string>
<string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"यस एपले तपाईंको ट्याब्लेटमा पात्रोका कार्यक्रमहरू थप्न, हटाउन वा परिवर्तन गर्न सक्छ। यस एपले पात्रोका मालिकहरू मार्फत आएको जस्तो लाग्ने सन्देशहरू पठाउन वा तिनीहरूका मालिकहरूलाई सूचित नगरिकन कार्यक्रमहरू परिवर्तन गर्न सक्छ।"</string>
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"फिंगरप्रिन्ट सञ्चालन रद्द गरियो।"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"प्रयोगकर्ताले फिंगरप्रिन्टसम्बन्धी कारबाही रद्द गर्नुभयो।"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"धेरै प्रयासहरू। केहि समय पछि पुन: प्रयास गर्नुहोला"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"अत्यन्त धेरै प्रयासहरू। फिंगरप्रिन्ट सेन्सरलाई असक्षम पारियो।"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"पुन: प्रयास गर्नुहोला।"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"कुनै पनि फिंगरप्रिन्ट दर्ता गरिएको छैन।"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"यो डिभाइसमा कुनै पनि फिंगरप्रिन्ट सेन्सर छैन।"</string>
@@ -1045,7 +1046,7 @@
<string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"ब्राउजरले भ्रमण गरेको सबै URL हरूको इतिहास र ब्राउजरका सबै बुकमार्कहरू पढ्नको लागि एपलाई अनुमति दिन्छ। नोट: यो अनुमतिलाई तेस्रो पक्ष ब्राउजरहरूद्वारा वा वेब ब्राउज गर्ने क्षमताद्वारा बलपूर्वक गराउन सकिँदैन।"</string>
<string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"वेब बुकमार्कहरू र इतिहास लेख्नुहोस्"</string>
<string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"एपलाई तपाईंको ट्याब्लेटमा भण्डार गरिएको ब्राउजरको इतिहास वा बुकमार्कहरू परिमार्जन गर्न अनुमति दिन्छ। यसले एपलाई ब्राजर डेटा मेटाउन वा परिमार्जन गर्न अनुमति दिन सक्दछ। टिप्पणी: यो अनुमति वेब ब्राउज गर्ने क्षमताहरूको साथ तेस्रो-पार्टी ब्राउजर वा अन्य अनुप्रयोगहरूद्वारा लागू गरिएको होइन।"</string>
- <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"एपलाई तपाईंको Android टिभी डिभाइसमा भण्डार गरिएका ब्राउजरको इतिहास र पुस्तक चिन्हहरू परिमार्जन गर्ने अनुमति दिन्छ। यसले एपलाई ब्राउजरको डेटा मेटाउने वा परिमार्जन गर्ने अनुमति दिन सक्छ। ध्यान दिनुहोस्: तेस्रो पक्षीय ब्राउजर वा वेब ब्राउज गर्ने सुविधा प्रदान गर्ने अन्य एपहरूले यो अनुमति लागू गर्न सक्दैनन्।"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"एपलाई तपाईंको Android टिभी डिभाइसमा भण्डारण गरिएका ब्राउजरको इतिहास र पुस्तक चिन्हहरू परिमार्जन गर्ने अनुमति दिन्छ। यसले एपलाई ब्राउजरको डेटा मेटाउने वा परिमार्जन गर्ने अनुमति दिन सक्छ। ध्यान दिनुहोस्: तेस्रो पक्षीय ब्राउजर वा वेब ब्राउज गर्ने सुविधा प्रदान गर्ने अन्य एपहरूले यो अनुमति लागू गर्न सक्दैनन्।"</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"तपाईँको फोनमा भण्डारण भएको ब्राउजरको इतिहास वा बुकमार्कहरू परिवर्तन गर्नको लागि एपलाई अनुमति दिन्छ। यसले सायद ब्राउजर डेटालाई मेट्न वा परिवर्तन गर्नको लागि एपलाई अनुमति दिन्छ। नोट: वेब ब्राउज गर्ने क्षमतासहितका अन्य एपहरू वा तेस्रो- पक्ष ब्राउजरद्वारा सायद यस अनुमतिलाई लागु गर्न सकिंदैन।"</string>
<string name="permlab_setAlarm" msgid="1158001610254173567">"एउटा आलर्म सेट गर्नुहोस्"</string>
<string name="permdesc_setAlarm" msgid="2185033720060109640">"स्थापना गरिएको सङ्केत घडी एपमा सङ्केत समय मिलाउन एपलाई अनुमति दिन्छ। केही सङ्केत घडी एपहरूले यो सुविधा कार्यान्वयन नगर्न सक्छन्।"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> तयारी गर्दै।"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"सुरुवात एपहरू।"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"बुट पुरा हुँदै।"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"सेटअप गर्ने प्रक्रिया जारी राख्ने हो?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"तपाईंले पावर बटन थिच्नुभयो — सामान्यतया स्क्रिन अफ गर्न यो बटन थिच्ने गरिन्छ।\n\nफिंगरप्रिन्ट सेटअप भइन्जेल हल्का तरिकाले यो बटन ट्याप गर्नुहोस्।"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"स्क्रिन अफ गर्नुहोस्"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"सेटअप जारी राख्नुस्"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"स्क्रिन अफ गर्न ट्याप गर्नुहोस्"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"स्क्रिन अफ गर्नुहोस्"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"फिंगरप्रिन्ट पुष्टि गर्ने क्रम जारी राख्ने हो?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"तपाईंले पावर बटन थिच्नुभयो — सामान्यतया स्क्रिन अफ गर्न यो बटन थिच्ने गरिन्छ।\n\nतपाईं आफ्नो फिंगरप्रिन्ट पुष्टि गर्न चाहनुहुन्छ भने हल्का तरिकाले यो बटन ट्याप गरी हेर्नुहोस्।"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"स्क्रिन अफ गर्नुहोस्"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"सेटअप गर्न ट्याप गर्नुहोस्"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"सेटअप गर्न चयन गर्नुहोस्"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"तपाईंले यो डिभाइस पुनः फर्म्याट गर्नु पर्ने हुन सक्छ। यो डिभाइस हटाउन ट्याप गर्नुहोस्।"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"फोटोहरू र मिडिया स्थानान्तरणका लागि"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"फोटो, भिडियो, सङ्गीत र थप सामग्री भण्डारण गर्न"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"मिडिया फाइलहरू ब्राउज गर्नुहोस्"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> मा समस्या देखियो"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ले काम गरिरहेको छैन"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"समस्या समाधान गर्न ट्याप गर्नुहोस्"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> बिग्रेको छ। समाधान गर्न चयन गर्नुहोस्।"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"तपाईंले यो डिभाइस पुनः फर्म्याट गर्नु पर्ने हुन सक्छ। यो डिभाइस हटाउन ट्याप गर्नुहोस्।"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"असमर्थित <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> पत्ता लाग्यो"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ले काम गरिरहेको छैन"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"यस यन्त्रले यस <xliff:g id="NAME">%s</xliff:g> लाई समर्थन गर्दैन। एक समर्थित ढाँचामा सेटअप गर्न ट्याप गर्नुहोस्।"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"सेटअप गर्न ट्याप गर्नुहोस् ।"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"<xliff:g id="NAME">%s</xliff:g> प्रयोग गर्न मिल्ने फर्म्याटमा सेटअप गर्न चयन गर्नुहोस्।"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"तपाईंले यो डिभाइस पुनः फर्म्याट गर्नु पर्ने हुन सक्छ"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> अप्रत्याशित रूपमा निकालियो"</string>
@@ -1428,7 +1428,7 @@
<string name="ext_media_browse_action" msgid="344865351947079139">"अन्वेषण गर्नुहोस्"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"आउटपुट बदल्नुहोस्"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> हराइरहेको"</string>
- <string name="ext_media_missing_message" msgid="4408988706227922909">"यन्त्र फेरि घुसाउनुहोस्"</string>
+ <string name="ext_media_missing_message" msgid="4408988706227922909">"डिभाइस फेरि हाल्नुहोस्"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"<xliff:g id="NAME">%s</xliff:g> सार्दै"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"डेटा सार्दै..."</string>
<string name="ext_media_move_success_title" msgid="4901763082647316767">"सामग्री स्थानान्तरण गरियो"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"क्षेत्रको प्राथमिकता"</string>
<string name="search_language_hint" msgid="7004225294308793583">"भाषाको नाम टाइप गर्नुहोस्"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"सिफारिस गरिएको"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"सिफारिस गरिएको"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"सम्पूर्ण भाषाहरू"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"सबै क्षेत्रहरू"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"खोज"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> लाई डिभाइसका सबै लग हेर्ने अनुमति दिने हो?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"एक पटक प्रयोग गर्ने अनुमति दिनुहोस्"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"अनुमति नदिनुहोस्"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"डिभाइसका लगले तपाईंको डिभाइसमा भएका विभिन्न गतिविधिको अभिलेख राख्छ। एपहरू यी लगका आधारमा समस्या पत्ता लगाउन र तिनको समाधान गर्न सक्छन्।\n\nकेही लगहरूमा संवेदनशील जानकारी समावेश हुन सक्ने भएकाले आफूले भरोसा गर्ने एपलाई मात्र डिभाइसका सबै लग हेर्ने अनुमति दिनुहोस्। \n\nतपाईंले यो एपलाई डिभाइसका सबै लग हेर्ने अनुमति दिनुभएन भने पनि यसले आफ्नै लग भने हेर्न सक्छ। तपाईंको डिभाइसको उत्पादकले पनि तपाईंको डिभाइसमा भएका केही लग वा जानकारी हेर्न सक्ने सम्भावना हुन्छ। थप जान्नुहोस्"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"डिभाइसका लगले तपाईंको डिभाइसमा भएका विभिन्न गतिविधिको अभिलेख राख्छ। एपहरू यी लगका आधारमा समस्या पत्ता लगाउन र तिनको समाधान गर्न सक्छन्।\n\nकेही लगहरूमा संवेदनशील जानकारी समावेश हुन सक्ने भएकाले आफूले भरोसा गर्ने एपलाई मात्र डिभाइसका सबै लग हेर्ने अनुमति दिनुहोस्। \n\nतपाईंले यो एपलाई डिभाइसका सबै लग हेर्ने अनुमति दिनुभएन भने पनि यसले आफ्नै लग भने हेर्न सक्छ। तपाईंको डिभाइसको उत्पादकले पनि तपाईंको डिभाइसमा भएका केही लग वा जानकारी हेर्न सक्ने सम्भावना हुन्छ।"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"फेरि नदेखाइयोस्"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> ले <xliff:g id="APP_2">%2$s</xliff:g> का स्लाइसहरू देखाउन चाहन्छ"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"सम्पादन गर्नुहोस्"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"कुन कुन एप सक्रिय छ भन्ने कुरा जाँच्नुहोस्"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"तपाईंको <xliff:g id="DEVICE">%1$s</xliff:g> मार्फत फोनको क्यामेरा प्रयोग गर्न मिल्दैन"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"तपाईंको <xliff:g id="DEVICE">%1$s</xliff:g> मार्फत ट्याब्लेटको क्यामेरा प्रयोग गर्न मिल्दैन"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"स्ट्रिम गरिरहेका बेला यो सामग्री हेर्न तथा प्रयोग गर्न मिल्दैन। बरु आफ्नो फोनमार्फत सो सामग्री हेर्ने तथा प्रयोग गर्ने प्रयास गर्नुहोस्।"</string>
<string name="system_locale_title" msgid="711882686834677268">"सिस्टम डिफल्ट"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 8ead9026..ad2bd53 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Vingerafdrukbewerking geannuleerd."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Vingerafdrukverificatie geannuleerd door gebruiker."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Te veel pogingen. Probeer het later opnieuw."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Te veel pogingen. Vingerafdruksensor staat uit."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Probeer het opnieuw."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Geen vingerafdrukken geregistreerd."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Dit apparaat heeft geen vingerafdruksensor."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> voorbereiden."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Apps starten."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Opstarten afronden."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Doorgaan met instellen?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Je hebt op de aan/uit-knop gedrukt. Zo zet je meestal het scherm uit.\n\nRaak de knop voorzichtig aan terwijl je je vingerafdruk instelt."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Scherm uitzetten"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Doorgaan met instellen"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tik om het scherm uit te zetten"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Scherm uitzetten"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Doorgaan met verificatie van je vingerafdruk?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Je hebt op de aan/uit-knop gedrukt. Zo zet je meestal het scherm uit.\n\nRaak de knop voorzichtig aan om je vingerafdruk te verifiëren."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Scherm uitzetten"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Tik om in te stellen"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Selecteer om in te stellen"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Je moet het apparaat misschien opnieuw formatteren. Tik om het uit te werpen."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Voor overzetten van foto\'s en media"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Voor de opslag van foto\'s, video\'s, muziek en meer"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Browsen door mediabestanden"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Probleem met <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> werkt niet"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Tik om het probleem op te lossen"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> is beschadigd. Selecteer om te herstellen."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Je moet het apparaat misschien opnieuw formatteren. Tik om het uit te werpen."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> niet ondersteund"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> waargenomen"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> werkt niet"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Dit apparaat biedt geen ondersteuning voor deze <xliff:g id="NAME">%s</xliff:g>. Tik om in te stellen in een ondersteunde indeling."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Tik om in te stellen."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Selecteer om <xliff:g id="NAME">%s</xliff:g> in te stellen in een ondersteunde indeling."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Je moet het apparaat misschien opnieuw formatteren"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> is onverwacht verwijderd"</string>
@@ -1428,7 +1428,7 @@
<string name="ext_media_browse_action" msgid="344865351947079139">"Verkennen"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Uitvoer wijzigen"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> ontbreekt"</string>
- <string name="ext_media_missing_message" msgid="4408988706227922909">"Voer apparaat opnieuw in"</string>
+ <string name="ext_media_missing_message" msgid="4408988706227922909">"Voer het apparaat opnieuw in"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"<xliff:g id="NAME">%s</xliff:g> verplaatsen"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"Gegevens verplaatsen"</string>
<string name="ext_media_move_success_title" msgid="4901763082647316767">"Contentoverdracht is voltooid"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Regiovoorkeur"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Typ de naam van een taal"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Voorgesteld"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Voorgesteld"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Alle talen"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Alle regio\'s"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Zoeken"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> toegang geven tot alle apparaatlogboeken?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Eenmalige toegang toestaan"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Niet toestaan"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Apparaatlogboeken leggen vast wat er op je apparaat gebeurt. Apps kunnen deze logboeken gebruiken om problemen op te sporen en te verhelpen.\n\nSommige logboeken kunnen gevoelige informatie bevatten, dus geef alleen apps die je vertrouwt toegang tot alle apparaatlogboeken. \n\nAls je deze app geen toegang tot alle apparaatlogboeken geeft, heeft de app nog wel toegang tot de eigen logboeken. De fabrikant van je apparaat heeft misschien nog steeds toegang tot bepaalde logboeken of informatie op je apparaat. Meer informatie"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Apparaatlogboeken leggen vast wat er op je apparaat gebeurt. Apps kunnen deze logboeken gebruiken om problemen op te sporen en te verhelpen.\n\nSommige logboeken kunnen gevoelige informatie bevatten, dus geef alleen apps die je vertrouwt toegang tot alle apparaatlogboeken. \n\nAls je deze app geen toegang tot alle apparaatlogboeken geeft, heeft de app nog wel toegang tot de eigen logboeken. De fabrikant van je apparaat heeft misschien nog steeds toegang tot bepaalde logboeken of informatie op je apparaat."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Niet opnieuw tonen"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> wil segmenten van <xliff:g id="APP_2">%2$s</xliff:g> tonen"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Bewerken"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Actieve apps checken"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Kan geen toegang tot de camera van de telefoon krijgen vanaf je <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Kan geen toegang tot de camera van de tablet krijgen vanaf je <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Je hebt hier geen toegang toe tijdens streaming. Probeer het in plaats daarvan op je telefoon."</string>
<string name="system_locale_title" msgid="711882686834677268">"Systeemstandaard"</string>
</resources>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 07eee35..f0b60b6 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -142,7 +142,7 @@
<string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"ୱାଇ-ଫାଇ"</string>
<string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"ୱାଇଫାଇ କଲିଂ"</string>
<string name="wfcSpnFormat_vowifi" msgid="8371335230890725606">"VoWifi"</string>
- <string name="wifi_calling_off_summary" msgid="5626710010766902560">"ବନ୍ଦ"</string>
+ <string name="wifi_calling_off_summary" msgid="5626710010766902560">"ବନ୍ଦ ଅଛି"</string>
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"ୱାଇ-ଫାଇ ମାଧ୍ୟମରେ କଲ୍ କରନ୍ତୁ"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"ମୋବାଇଲ ନେଟ୍ୱର୍କ ମାଧ୍ୟମରେ କଲ୍ କରନ୍ତୁ"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"କେବଳ ୱାଇ-ଫାଇ"</string>
@@ -185,14 +185,14 @@
<string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"ଆପଣଙ୍କ ୱର୍କ ପ୍ରୋଫାଇଲ୍ ଆଡମିନଙ୍କ ଦ୍ୱାରା"</string>
<string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"<xliff:g id="MANAGING_DOMAIN">%s</xliff:g> ଅନୁଯାୟୀ"</string>
<string name="work_profile_deleted" msgid="5891181538182009328">"ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଡିଲିଟ୍ ହେଲା"</string>
- <string name="work_profile_deleted_details" msgid="3773706828364418016">"ଆଡମିନ୍ ଆପ୍ ନାହିଁ କିମ୍ବା ଭୁଲ ଅଛି। ଫଳସ୍ୱରୂପ, ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଏବଂ ସମ୍ବନ୍ଧୀୟ ଡାଟା ଡିଲିଟ୍ କରାଯାଇଛି। ସହାୟତା ପାଇଁ ଆପଣଙ୍କ ଆଡମିନଙ୍କୁ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="work_profile_deleted_details" msgid="3773706828364418016">"ଆଡମିନ ଆପ ନାହିଁ କିମ୍ବା ଭୁଲ ଅଛି। ଫଳସ୍ୱରୂପ, ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲ ଏବଂ ସମ୍ବନ୍ଧୀୟ ଡାଟା ଡିଲିଟ କରାଯାଇଛି। ସହାୟତା ପାଇଁ ଆପଣଙ୍କ ଆଡମିନଙ୍କୁ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"ଏହି ଡିଭାଇସରେ ଆପଣଙ୍କ ୱର୍କ ପ୍ରୋଫାଇଲ୍ ଆଉ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"ବହୁତ ଥର ଭୁଲ ପାସ୍ୱର୍ଡ ଲେଖିଛନ୍ତି"</string>
<string name="device_ownership_relinquished" msgid="4080886992183195724">"ବ୍ୟକ୍ତିଗତ ବ୍ୟବହାର ପାଇଁ ଆଡ୍ମିନ୍ ଡିଭାଇସ୍କୁ ଅଲଗା କରିଛନ୍ତି"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"ଡିଭାଇସକୁ ପରିଚାଳନା କରାଯାଉଛି"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"ଆପଣଙ୍କ ସଂସ୍ଥା ଏହି ଡିଭାଇସକୁ ପରିଚାଳନା କରନ୍ତି ଏବଂ ନେଟୱର୍କ ଟ୍ରାଫିକ୍ ନୀରିକ୍ଷଣ କରନ୍ତି। ବିବରଣୀ ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
<string name="location_changed_notification_title" msgid="3620158742816699316">"ଆପଗୁଡ଼ିକ ଆପଣଙ୍କ ଲୋକେସନକୁ ଆକ୍ସେସ୍ କରିପାରିବ"</string>
- <string name="location_changed_notification_text" msgid="7158423339982706912">"ଅଧିକ ଜାଣିବାକୁ ଆପଣଙ୍କ IT ଆଡମିନଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ"</string>
+ <string name="location_changed_notification_text" msgid="7158423339982706912">"ଅଧିକ ଜାଣିବାକୁ ଆପଣଙ୍କ IT ଆଡମିନଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ"</string>
<string name="geofencing_service" msgid="3826902410740315456">"ଜିଓଫେନସିଂ ସେବା"</string>
<string name="country_detector" msgid="7023275114706088854">"କଣ୍ଟ୍ରି ଡିଟେକ୍ଟର୍"</string>
<string name="location_service" msgid="2439187616018455546">"ଲୋକେସନ୍ ସର୍ଭିସ୍"</string>
@@ -203,7 +203,7 @@
<string name="device_policy_manager_service" msgid="5085762851388850332">"ଡିଭାଇସ ନୀତି ପରିଚାଳକ ସେବା"</string>
<string name="music_recognition_manager_service" msgid="7481956037950276359">"ମ୍ୟୁଜିକ୍ ଚିହ୍ନଟକରଣ ପରିଚାଳକ ସେବା"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"ଆପଣଙ୍କ ଡିଭାଇସ୍ ବର୍ତ୍ତମାନ ଲିଭାଯିବ"</string>
- <string name="factory_reset_message" msgid="2657049595153992213">"ଆଡମିନ୍ ଆପ୍ ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ। ଆପଣଙ୍କ ଡିଭାଇସ୍ର ସମସ୍ତ ଡାଟାକୁ ବର୍ତ୍ତମାନ ଲିଭାଇଦିଆଯିବ। \n\nଯଦି ଆପଣଙ୍କର କୌଣସି ପ୍ରଶ୍ନ ରହିଥାଏ, ଆପଣଙ୍କ ସଂସ୍ଥାର ଆଡମିନ୍ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="factory_reset_message" msgid="2657049595153992213">"ଆଡମିନ ଆପ ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ। ଆପଣଙ୍କ ଡିଭାଇସର ସମସ୍ତ ଡାଟାକୁ ବର୍ତ୍ତମାନ ଲିଭାଇଦିଆଯିବ। \n\nଯଦି ଆପଣଙ୍କର କୌଣସି ପ୍ରଶ୍ନ ଅଛି, ଆପଣଙ୍କ ସଂସ୍ଥାର ଆଡମିନଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ଦ୍ଵାରା ପ୍ରିଣ୍ଟିଙ୍ଗ ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="personal_apps_suspension_title" msgid="7561416677884286600">"ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଚାଲୁ କରନ୍ତୁ"</string>
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"ଆପଣ ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଚାଲୁ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଆପଣଙ୍କର ବ୍ୟକ୍ତିଗତ ଆପ୍ସ ବ୍ଲକ୍ କରାଯାଇଛି"</string>
@@ -216,8 +216,8 @@
<string name="silent_mode" msgid="8796112363642579333">"ସାଇଲେଣ୍ଟ ମୋଡ୍"</string>
<string name="turn_on_radio" msgid="2961717788170634233">"ୱେୟାରଲେସ୍କୁ ଚାଲୁ କରନ୍ତୁ"</string>
<string name="turn_off_radio" msgid="7222573978109933360">"ୱେୟାରଲେସ୍କୁ ବନ୍ଦ କରନ୍ତୁ"</string>
- <string name="screen_lock" msgid="2072642720826409809">"ସ୍କ୍ରୀନ୍ ଲକ୍"</string>
- <string name="power_off" msgid="4111692782492232778">"ପାୱାର୍ ବନ୍ଦ"</string>
+ <string name="screen_lock" msgid="2072642720826409809">"ସ୍କ୍ରିନ ଲକ"</string>
+ <string name="power_off" msgid="4111692782492232778">"ପାୱାର ବନ୍ଦ ଅଛି"</string>
<string name="silent_mode_silent" msgid="5079789070221150912">"ରିଙ୍ଗର୍ ଅଫ୍ ଅଛି"</string>
<string name="silent_mode_vibrate" msgid="8821830448369552678">"ରିଙ୍ଗର୍ କମ୍ପନ"</string>
<string name="silent_mode_ring" msgid="6039011004781526678">"ରିଙ୍ଗର୍ ଚାଲୁ ଅଛି"</string>
@@ -240,8 +240,8 @@
<string name="global_actions" product="tablet" msgid="4412132498517933867">"ଟାବଲେଟ ବିକଳ୍ପ"</string>
<string name="global_actions" product="tv" msgid="3871763739487450369">"Android TVର ବିକଳ୍ପଗୁଡ଼ିକ"</string>
<string name="global_actions" product="default" msgid="6410072189971495460">"ଫୋନ ବିକଳ୍ପ"</string>
- <string name="global_action_lock" msgid="6949357274257655383">"ସ୍କ୍ରୀନ୍ ଲକ୍"</string>
- <string name="global_action_power_off" msgid="4404936470711393203">"ପାୱାର୍ ବନ୍ଦ"</string>
+ <string name="global_action_lock" msgid="6949357274257655383">"ସ୍କ୍ରିନ ଲକ"</string>
+ <string name="global_action_power_off" msgid="4404936470711393203">"ପାୱାର ବନ୍ଦ ଅଛି"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"ପାୱାର"</string>
<string name="global_action_restart" msgid="4678451019561687074">"ରିଷ୍ଟାର୍ଟ କରନ୍ତୁ"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"ଜରୁରୀକାଳୀନ"</string>
@@ -297,11 +297,11 @@
<string name="android_system_label" msgid="5974767339591067210">"Android ସିଷ୍ଟମ୍"</string>
<string name="user_owner_label" msgid="8628726904184471211">"ବ୍ୟକ୍ତିଗତ ପ୍ରୋଫାଇଲ୍କୁ ଫେରିଆସନ୍ତୁ"</string>
<string name="managed_profile_label" msgid="7316778766973512382">"କାର୍ଯ୍ୟ ପ୍ରୋଫାଇଲ୍କୁ ଯାଆନ୍ତୁ"</string>
- <string name="permgrouplab_contacts" msgid="4254143639307316920">"ଯୋଗାଯୋଗ"</string>
+ <string name="permgrouplab_contacts" msgid="4254143639307316920">"କଣ୍ଟାକ୍ଟ"</string>
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"ଆପଣଙ୍କ ଯୋଗାଯୋଗ ଆକ୍ସେସ୍ କରେ"</string>
- <string name="permgrouplab_location" msgid="1858277002233964394">"ଲୋକେସନ୍"</string>
+ <string name="permgrouplab_location" msgid="1858277002233964394">"ଲୋକେସନ"</string>
<string name="permgroupdesc_location" msgid="1995955142118450685">"ଏହି ଡିଭାଇସ୍ର ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରେ"</string>
- <string name="permgrouplab_calendar" msgid="6426860926123033230">"କ୍ୟାଲେଣ୍ଡର୍"</string>
+ <string name="permgrouplab_calendar" msgid="6426860926123033230">"କ୍ୟାଲେଣ୍ଡର"</string>
<string name="permgroupdesc_calendar" msgid="6762751063361489379">"ଆପଣଙ୍କ କ୍ୟାଲେଣ୍ଡର୍ ଆକ୍ସେସ୍ କରେ"</string>
<string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
<string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ମେସେଜ୍ ପଠାନ୍ତୁ ଓ ଦେଖନ୍ତୁ"</string>
@@ -311,7 +311,7 @@
<string name="permgroupdesc_readMediaAural" msgid="7565467343667089595">"ଆପଣଙ୍କ ଡିଭାଇସରେ ମ୍ୟୁଜିକ ଏବଂ ଅଡିଓକୁ ଆକ୍ସେସ କରନ୍ତୁ"</string>
<string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"ଫଟୋ ଏବଂ ଭିଡିଓଗୁଡ଼ିକ"</string>
<string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"ଆପଣଙ୍କ ଡିଭାଇସରେ ଫଟୋ ଏବଂ ଭିଡିଓଗୁଡ଼ିକୁ ଆକ୍ସେସ କରନ୍ତୁ"</string>
- <string name="permgrouplab_microphone" msgid="2480597427667420076">"ମାଇକ୍ରୋଫୋନ୍"</string>
+ <string name="permgrouplab_microphone" msgid="2480597427667420076">"ମାଇକ୍ରୋଫୋନ"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"ଅଡିଓ ରେକର୍ଡ କରେ"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"ଶାରୀରିକ କାର୍ଯ୍ୟକଳାପ"</string>
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ଆପଣଙ୍କ ଶାରୀରିକ କାର୍ଯ୍ୟକଳାପ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
@@ -319,9 +319,9 @@
<string name="permgroupdesc_camera" msgid="7585150538459320326">"ଫଟୋ ନିଏ ଓ ଭିଡିଓ ରେକର୍ଡ କରେ"</string>
<string name="permgrouplab_nearby_devices" msgid="5529147543651181991">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକ"</string>
<string name="permgroupdesc_nearby_devices" msgid="3213561597116913508">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକୁ ଖୋଜି ସଂଯୋଗ କରନ୍ତୁ"</string>
- <string name="permgrouplab_calllog" msgid="7926834372073550288">"କଲ୍ ଲଗ୍"</string>
+ <string name="permgrouplab_calllog" msgid="7926834372073550288">"କଲ ଲଗ"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ଫୋନ୍ କଲ୍ ଲଗ୍ ପଢ଼ନ୍ତୁ ଓ ଲେଖନ୍ତୁ"</string>
- <string name="permgrouplab_phone" msgid="570318944091926620">"ଫୋନ୍"</string>
+ <string name="permgrouplab_phone" msgid="570318944091926620">"ଫୋନ"</string>
<string name="permgroupdesc_phone" msgid="270048070781478204">"ଫୋନ୍ କଲ୍ କରେ ଏବଂ ପରିଚାଳନା କରେ"</string>
<string name="permgrouplab_sensors" msgid="9134046949784064495">"ବଡି ସେନ୍ସର୍"</string>
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"ଆପଣଙ୍କ ଗୁରୁତପୂର୍ଣ୍ଣ ସଂକେତଗୁଡ଼ିକ ବିଷୟରେ ସେନ୍ସର୍ ଡାଟା ଆକ୍ସେସ୍ କରେ"</string>
@@ -412,13 +412,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ଷ୍ଟିକି ବ୍ରଡକାଷ୍ଟ୍ ପଠାଇବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ, ଯାହା ବ୍ରଡକାଷ୍ଟ୍ ଶେଷ ହେବାପରେ ରହିଥାଏ। ଅତ୍ୟଧିକ ବ୍ୟବହାର ଦ୍ୱାରା ଅଧିକ ମେମୋରୀ ବ୍ୟବହାର ହୋଇ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍କୁ ଧୀର କିମ୍ବା ଅସ୍ଥିର କରିପାରେ।"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ଷ୍ଟିକୀ ବ୍ରଡ୍କାଷ୍ଟ ପଠାଇବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ, ଯାହା ବ୍ରଡ୍କାଷ୍ଟ ଶେଷ ହେବାପରେ ରହିଥାଏ। ଅତିରିକ୍ତ ବ୍ୟବହାର ଦ୍ୱାରା ଅଧିକ ମେମୋରୀ ବ୍ୟବହାର ହୋଇ ଫୋନ୍କୁ ମନ୍ଥର କିମ୍ବା ଅସ୍ଥିର କରିପାରେ।"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"ଆପଣଙ୍କ ଯୋଗାଯୋଗ ପଢ଼ନ୍ତୁ"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"ଏହା ଆପଣଙ୍କ ଟାବ୍ଲେଟ୍ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗଗୁଡ଼ିକ ବିଷୟରେ ଡାଟା ପଢ଼ିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣଙ୍କର ଟାବ୍ଲେଟ୍ରେ ଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକ ଯେଉଁଥିରେ ଯୋଗାଯୋଗଗୁଡ଼ିକ ତିଆରି ହୋଇଛି, ସେଗୁଡ଼ିକୁ ଆପ୍ସର ଆକ୍ସେସ୍ ରହିବ। ଆପଣ ଇନ୍ଷ୍ଟଲ୍ କରିଥିବା ଆପ୍ସ ମାଧ୍ୟମରେ ତିଆରି କରାଯାଇଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକୁ ଏହା ସାମିଲ କରିପାରେ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ସେଭ୍ କରିବାକୁ ଦିଏ ଏବଂ ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ଅଜାଣତରେ ଯୋଗାଯୋଗ ଡାଟା ସେୟାର୍ କରିପାରେ।"</string>
- <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"ଏହା ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ପଢ଼ିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ରେ ଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକ ଯେଉଁଥିରେ ଯୋଗାଯୋଗଗୁଡ଼ିକ ତିଆରି ହୋଇଛି, ସେଗୁଡ଼ିକୁ ମଧ୍ୟ ଆପ୍ସର ଆକ୍ସେସ୍ ରହିବ। ଆପଣ ଇନ୍ଷ୍ଟଲ୍ କରିଥିବା ଆପ୍ସ ମାଧ୍ୟମରେ ତିଆରି କରାଯାଇଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକୁ ଏହା ସାମିଲ କରିପାରେ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ସେଭ୍ କରିବାକୁ ଦିଏ ଏବଂ ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ଅଜାଣତରେ ଯୋଗାଯୋଗ ଡାଟା ସେୟାର୍ କରିପାରେ।"</string>
- <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ଏହା ଆପଣଙ୍କ ଫୋନ୍ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗଗୁଡ଼ିକ ବିଷୟରେ ଡାଟା ପଢ଼ିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣଙ୍କର ଫୋନ୍ରେ ଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକ ଯେଉଁଥିରେ ଯୋଗାଯୋଗଗୁଡ଼ିକ ତିଆରି ହୋଇଛି, ସେଗୁଡ଼ିକୁ ଆପ୍ସର ଆକ୍ସେସ୍ ରହିବ। ଆପଣ ଇନ୍ଷ୍ଟଲ୍ କରିଥିବା ଆପ୍ସ ମାଧ୍ୟମରେ ତିଆରି କରାଯାଇଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକୁ ଏହା ସାମିଲ କରିପାରେ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ସେଭ୍ କରିବାକୁ ଦିଏ ଏବଂ ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ଅଜାଣତରେ ଯୋଗାଯୋଗ ଡାଟା ସେୟାର୍ କରିପାରେ।"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"ଏହା ଆପଣଙ୍କ ଟାବଲେଟରେ ଷ୍ଟୋର କରାଯାଇଥିବା କଣ୍ଟାକ୍ଟଗୁଡ଼ିକ ବିଷୟରେ ଡାଟା ପଢ଼ିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣଙ୍କର ଟାବଲେଟରେ ଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକ ଯେଉଁଥିରେ କଣ୍ଟାକ୍ଟଗୁଡ଼ିକ ତିଆରି ହୋଇଛି, ସେଗୁଡ଼ିକୁ ଆପ୍ସର ଆକ୍ସେସ ରହିବ। ଆପଣ ଇନଷ୍ଟଲ କରିଥିବା ଆପ୍ସ ମାଧ୍ୟମରେ ତିଆରି କରାଯାଇଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକୁ ଏହା ସାମିଲ କରିପାରେ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର କଣ୍ଟାକ୍ଟ ଡାଟା ସେଭ କରିବାକୁ ଦିଏ ଏବଂ ହାନୀକରକ ଆପ ଆପଣଙ୍କ ଅଜାଣତରେ କଣ୍ଟାକ୍ଟ ଡାଟା ସେୟାର କରିପାରେ।"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"ଏହା ଆପଣଙ୍କ Android TV ଡିଭାଇସରେ ଷ୍ଟୋର କରାଯାଇଥିବା କଣ୍ଟାକ୍ଟ ବିଷୟରେ ଡାଟା ପଢ଼ିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣଙ୍କର Android TV ଡିଭାଇସରେ ଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକ ଯେଉଁଥିରେ କଣ୍ଟାକ୍ଟଗୁଡ଼ିକ ତିଆରି ହୋଇଛି, ସେଗୁଡ଼ିକୁ ମଧ୍ୟ ଆପ୍ସର ଆକ୍ସେସ ରହିବ। ଆପଣ ଇନଷ୍ଟଲ କରିଥିବା ଆପ୍ସ ମାଧ୍ୟମରେ ତିଆରି କରାଯାଇଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକୁ ଏହା ସାମିଲ କରିପାରେ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର କଣ୍ଟାକ୍ଟ ଡାଟା ସେଭ କରିବାକୁ ଦିଏ ଏବଂ ହାନୀକାରକ ଆପ ଆପଣଙ୍କ ଅଜାଣତରେ କଣ୍ଟାକ୍ଟ ଡାଟା ସେୟାର କରିପାରେ।"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ଏହା ଆପଣଙ୍କ ଫୋନରେ ଷ୍ଟୋର କରାଯାଇଥିବା କଣ୍ଟାକ୍ଟଗୁଡ଼ିକ ବିଷୟରେ ଡାଟା ପଢ଼ିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣଙ୍କର ଫୋନରେ ଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକ ଯେଉଁଥିରେ କଣ୍ଟାକ୍ଟଗୁଡ଼ିକ ତିଆରି ହୋଇଛି, ସେଗୁଡ଼ିକୁ ଆପ୍ସର ଆକ୍ସେସ ରହିବ। ଆପଣ ଇନଷ୍ଟଲ କରିଥିବା ଆପ୍ସ ମାଧ୍ୟମରେ ତିଆରି କରାଯାଇଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକୁ ଏହା ସାମିଲ କରିପାରେ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର କଣ୍ଟାକ୍ଟ ଡାଟା ସେଭ କରିବାକୁ ଦିଏ ଏବଂ ହାନୀକାରକ ଆପ ଆପଣଙ୍କ ଅଜାଣତରେ କଣ୍ଟାକ୍ଟ ଡାଟା ସେୟାର କରିପାରେ।"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"ନିଜ ଯୋଗାଯୋଗ ସଂଶୋଧନ କରନ୍ତୁ"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"ଏହା ଆପଣଙ୍କ ଟାବ୍ଲେଟ୍ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ସଂଶୋଧନ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ଡିଲିଟ୍ କରିବାକୁ ଦିଏ।"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"ଏହା ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ସଂଶୋଧନ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ଡିଲିଟ୍ କରିବାକୁ ଦିଏ।"</string>
- <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"ଏହା ଆପଣଙ୍କ ଫୋନ୍ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ଡିଲିଟ୍ କରିବାକୁ ଦିଏ।"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"ଏହା ଆପଣଙ୍କ ଟାବଲେଟରେ ଷ୍ଟୋର କରାଯାଇଥିବା କଣ୍ଟାକ୍ଟ ବିଷୟରେ ଡାଟା ସଂଶୋଧନ କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର କଣ୍ଟାକ୍ଟ ଡାଟା ଡିଲିଟ କରିବାକୁ ଦିଏ।"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"ଏହା ଆପଣଙ୍କ Android TV ଡିଭାଇସରେ ଷ୍ଟୋର କରାଯାଇଥିବା କଣ୍ଟାକ୍ଟ ବିଷୟରେ ଡାଟା ସଂଶୋଧନ କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର କଣ୍ଟାକ୍ଟ ଡାଟା ଡିଲିଟ କରିବାକୁ ଦିଏ।"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"ଏହା ଆପଣଙ୍କ ଫୋନରେ ଷ୍ଟୋର କରାଯାଇଥିବା କଣ୍ଟାକ୍ଟ ବିଷୟରେ ଡାଟା ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର କଣ୍ଟାକ୍ଟ ଡାଟା ଡିଲିଟ କରିବାକୁ ଦିଏ।"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"କଲ୍ ଲଗ୍ ପଢ଼ନ୍ତୁ"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"ଏହି ଆପ୍ ଆପଣଙ୍କ କଲ୍ ହିଷ୍ଟୋରୀ ପଢ଼ିପାରେ।"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"କଲ୍ ଲଗ୍ ଲେଖନ୍ତୁ"</string>
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ଟିପଚିହ୍ନ କାର୍ଯ୍ୟ ବାତିଲ୍ କରାଗଲା।"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ଉପଯୋଗକର୍ତ୍ତା ଟିପଚିହ୍ନ କାର୍ଯ୍ୟ ବାତିଲ୍ କରିଛନ୍ତି।"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"ବହୁତ ପ୍ରୟାସ କରାଗଲା। ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"ବହୁଥର ପ୍ରୟାସ କରିଛନ୍ତି। ଟିପଚିହ୍ନ ସେନ୍ସର୍ ଅକ୍ଷମ କରାଯାଇଛି।"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"କୌଣସି ଆଙ୍ଗୁଠି ଚିହ୍ନ ପଞ୍ଜୀକୃତ ହୋଇନାହିଁ।"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ଏହି ଡିଭାଇସ୍ରେ ଟିପଚିହ୍ନ ସେନ୍ସର୍ ନାହିଁ।"</string>
@@ -796,7 +797,7 @@
<item msgid="7740243458912727194">"ମୋବାଇଲ୍"</item>
<item msgid="8526146065496663766">"ୱାର୍କ"</item>
<item msgid="8150904584178569699">"ୱାର୍କ ଫ୍ୟାକ୍ସ"</item>
- <item msgid="4537253139152229577">"ହୋମ୍ ଫାକ୍ସ"</item>
+ <item msgid="4537253139152229577">"ହୋମ ଫାକ୍ସ"</item>
<item msgid="6751245029698664340">"ପେଜର୍"</item>
<item msgid="1692790665884224905">"ଅନ୍ୟାନ୍ୟ"</item>
<item msgid="6216981255272016212">"କଷ୍ଟମ୍"</item>
@@ -808,7 +809,7 @@
<item msgid="3233938986670468328">"କଷ୍ଟମ୍"</item>
</string-array>
<string-array name="postalAddressTypes">
- <item msgid="3861463339764243038">"ମୂଳପୃଷ୍ଠା"</item>
+ <item msgid="3861463339764243038">"ହୋମ"</item>
<item msgid="5472578890164979109">"ୱାର୍କ"</item>
<item msgid="5718921296646594739">"ଅନ୍ୟାନ୍ୟ"</item>
<item msgid="5523122236731783179">"କଷ୍ଟମ୍"</item>
@@ -835,11 +836,11 @@
<item msgid="8293711853624033835">"Jabber"</item>
</string-array>
<string name="phoneTypeCustom" msgid="5120365721260686814">"କଷ୍ଟମ୍"</string>
- <string name="phoneTypeHome" msgid="3880132427643623588">"ମୂଳପୃଷ୍ଠା"</string>
+ <string name="phoneTypeHome" msgid="3880132427643623588">"ହୋମ"</string>
<string name="phoneTypeMobile" msgid="1178852541462086735">"ମୋବାଇଲ୍"</string>
<string name="phoneTypeWork" msgid="6604967163358864607">"ୱାର୍କ"</string>
<string name="phoneTypeFaxWork" msgid="6757519896109439123">"ୱାର୍କ ଫାକ୍ସ"</string>
- <string name="phoneTypeFaxHome" msgid="6678559953115904345">"ହୋମ୍ ଫାକ୍ସ"</string>
+ <string name="phoneTypeFaxHome" msgid="6678559953115904345">"ହୋମ ଫାକ୍ସ"</string>
<string name="phoneTypePager" msgid="576402072263522767">"ପେଜର୍"</string>
<string name="phoneTypeOther" msgid="6918196243648754715">"ଅନ୍ୟାନ୍ୟ"</string>
<string name="phoneTypeCallback" msgid="3455781500844157767">"କଲବ୍ୟାକ୍"</string>
@@ -901,10 +902,10 @@
<string name="relationTypeSister" msgid="3721676005094140671">"ଭଉଣୀ"</string>
<string name="relationTypeSpouse" msgid="6916682664436031703">"ସ୍ଵାମୀ ବା ସ୍ତ୍ରୀ"</string>
<string name="sipAddressTypeCustom" msgid="6283889809842649336">"କଷ୍ଟମ୍"</string>
- <string name="sipAddressTypeHome" msgid="5918441930656878367">"ଘର"</string>
+ <string name="sipAddressTypeHome" msgid="5918441930656878367">"ହୋମ"</string>
<string name="sipAddressTypeWork" msgid="7873967986701216770">"ୱାର୍କ"</string>
<string name="sipAddressTypeOther" msgid="6317012577345187275">"ଅନ୍ୟାନ୍ୟ"</string>
- <string name="quick_contacts_not_available" msgid="1262709196045052223">"ଏହି ଯୋଗାଯୋଗ ଦେଖିବାକୁ କୌଣସି ଆପ୍ଲିକେଶନ୍ ମିଳିଲା ନାହିଁ।"</string>
+ <string name="quick_contacts_not_available" msgid="1262709196045052223">"ଏହି କଣ୍ଟାକ୍ଟ ଦେଖିବାକୁ କୌଣସି ଆପ୍ଲିକେସନ ମିଳିଲା ନାହିଁ।"</string>
<string name="keyguard_password_enter_pin_code" msgid="6401406801060956153">"PIN କୋଡ୍ ଟାଇପ୍ କରନ୍ତୁ"</string>
<string name="keyguard_password_enter_puk_code" msgid="3112256684547584093">"PUK ଓ ନୂଆ PIN କୋଡ୍ ଟାଇପ୍ କରନ୍ତୁ"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="2825313071899938305">"PUK କୋଡ୍"</string>
@@ -934,7 +935,7 @@
<string name="lockscreen_missing_sim_instructions" msgid="8473601862688263903">"ଏକ SIM କାର୍ଡ ଭର୍ତ୍ତି କରନ୍ତୁ।"</string>
<string name="lockscreen_missing_sim_instructions_long" msgid="3664999892038416334">"SIM କାର୍ଡ ନାହିଁ କିମ୍ବା ଖରାପ ଅଛି। SIM କାର୍ଡ ଭର୍ତ୍ତି କରନ୍ତୁ।"</string>
<string name="lockscreen_permanent_disabled_sim_message_short" msgid="3812893366715730539">"SIM କାର୍ଡଟି ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ।"</string>
- <string name="lockscreen_permanent_disabled_sim_instructions" msgid="4358929052509450807">"ଆପଣଙ୍କ SIM କାର୍ଡକୁ ସ୍ଥାୟୀ ରୂପେ ଅକ୍ଷମ କରିଦିଆଯାଇଛି।\n ଅନ୍ୟ SIM କାର୍ଡ ପାଇଁ ଆପଣଙ୍କ ୱାୟରଲେସ୍ ସେବା ପ୍ରଦାନକାରୀଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions" msgid="4358929052509450807">"ଆପଣଙ୍କ SIM କାର୍ଡକୁ ସ୍ଥାୟୀ ରୂପେ ଅକ୍ଷମ କରିଦିଆଯାଇଛି।\n ଅନ୍ୟ SIM କାର୍ଡ ପାଇଁ ଆପଣଙ୍କ ୱାୟରଲେସ ସେବା ପ୍ରଦାନକାରୀଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="lockscreen_transport_prev_description" msgid="2879469521751181478">"ପୂର୍ବବର୍ତ୍ତୀ ଟ୍ରାକ୍"</string>
<string name="lockscreen_transport_next_description" msgid="2931509904881099919">"ପରବର୍ତ୍ତୀ ଟ୍ରାକ୍"</string>
<string name="lockscreen_transport_pause_description" msgid="6705284702135372494">"ପଜ୍ କରନ୍ତୁ"</string>
@@ -945,7 +946,7 @@
<string name="emergency_calls_only" msgid="3057351206678279851">"କେବଳ ଜରୁରୀକାଳୀନ କଲ୍"</string>
<string name="lockscreen_network_locked_message" msgid="2814046965899249635">"ନେଟ୍ୱର୍କକୁ ଲକ୍ କରାଯାଇଛି"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"SIM କାର୍ଡଟିରେ PUK ଲକ୍ ହୋଇଯାଇଛି।"</string>
- <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"ୟୁଜର୍ ଗାଇଡ୍ ଦେଖନ୍ତୁ କିମ୍ବା ଗ୍ରାହକ ସେବା କେନ୍ଦ୍ର ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"ୟୁଜର ଗାଇଡ ଦେଖନ୍ତୁ କିମ୍ବା ଗ୍ରାହକ ସେବା କେନ୍ଦ୍ର ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="lockscreen_sim_locked_message" msgid="3160196135801185938">"SIM କାର୍ଡ ଲକ୍ ହୋଇଯାଇଛି"</string>
<string name="lockscreen_sim_unlock_progress_dialog_message" msgid="2286497117428409709">"SIM କାର୍ଡକୁ ଅନଲକ୍ କରାଯାଉଛି…"</string>
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"ଆପଣଙ୍କ ଅନଲକ୍ ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
@@ -1164,8 +1165,8 @@
<string name="no" msgid="5122037903299899715">"ବାତିଲ କରନ୍ତୁ"</string>
<string name="dialog_alert_title" msgid="651856561974090712">"ଧ୍ୟାନଦିଅନ୍ତୁ"</string>
<string name="loading" msgid="3138021523725055037">"ଲୋଡ୍ କରାଯାଉଛି…"</string>
- <string name="capital_on" msgid="2770685323900821829">"ଚାଲୁ"</string>
- <string name="capital_off" msgid="7443704171014626777">"ବନ୍ଦ"</string>
+ <string name="capital_on" msgid="2770685323900821829">"ଚାଲୁ ଅଛି"</string>
+ <string name="capital_off" msgid="7443704171014626777">"ବନ୍ଦ ଅଛି"</string>
<string name="checked" msgid="9179896827054513119">"ଯାଞ୍ଚ ହୋଇଛି"</string>
<string name="not_checked" msgid="7972320087569023342">"ଯାଞ୍ଚ ହୋଇନାହିଁ"</string>
<string name="selected" msgid="6614607926197755875">"ଚୟନ କରାଯାଇଛି"</string>
@@ -1191,8 +1192,8 @@
<string name="whichSendToApplication" msgid="77101541959464018">"ଏହା ଜରିଆରେ ପଠାନ୍ତୁ"</string>
<string name="whichSendToApplicationNamed" msgid="3385686512014670003">"%1$s ଜରିଆରେ ପଠାନ୍ତୁ"</string>
<string name="whichSendToApplicationLabel" msgid="3543240188816513303">"ପଠାନ୍ତୁ"</string>
- <string name="whichHomeApplication" msgid="8276350727038396616">"ହୋମ୍ ଆପ୍ ଚୟନ କରନ୍ତୁ"</string>
- <string name="whichHomeApplicationNamed" msgid="5855990024847433794">"ହୋମ୍ ରୂପରେ %1$s ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="whichHomeApplication" msgid="8276350727038396616">"ଏକ ହୋମ ଆପ ଚୟନ କରନ୍ତୁ"</string>
+ <string name="whichHomeApplicationNamed" msgid="5855990024847433794">"ହୋମ ରୂପରେ %1$s ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="whichHomeApplicationLabel" msgid="8907334282202933959">"ଇମେଜ୍ କ୍ୟାପଚର୍ କରନ୍ତୁ"</string>
<string name="whichImageCaptureApplication" msgid="2737413019463215284">"ଏହା ସହ ଇମେଜ୍ କ୍ୟାପଚର୍ କରନ୍ତୁ"</string>
<string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"%1$s ସହ ଇମେଜ୍ କ୍ୟାପଚର୍ କରନ୍ତୁ"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> ପ୍ରସ୍ତୁତ କରାଯାଉଛି।"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ଆପ୍ ଆରମ୍ଭ କରାଯାଉଛି।"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"ବୁଟ୍ ସମାପ୍ତ କରୁଛି।"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"ସେଟଅପ କରିବା ଜାରି ରଖିବେ?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ଆପଣ ପାୱାର ବଟନ ଦବାଇଛନ୍ତି — ଏହା ସାଧାରଣତଃ ଆପଣଙ୍କ ସ୍କ୍ରିନକୁ ବନ୍ଦ କରିଥାଏ।\n\nଆପଣଙ୍କ ଟିପଚିହ୍ନ ସେଟ ଅପ କରିବା ସମୟରେ ଧୀରେ ଟାପ କରିବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"ସ୍କ୍ରିନ ବନ୍ଦ କରନ୍ତୁ"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"ସେଟଅପ କରିବା ଜାରି ରଖ"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ସ୍କ୍ରିନ ବନ୍ଦ କରିବା ପାଇଁ ଟାପ କରନ୍ତୁ"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ସ୍କ୍ରିନ ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"ଆପଣଙ୍କ ଟିପଚିହ୍ନ ଯାଞ୍ଚ କରିବା ଜାରି ରଖିବେ?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"ଆପଣ ପାୱାର ବଟନ ଦବାଇଛନ୍ତି — ଏହା ସାଧାରଣତଃ ଆପଣଙ୍କ ସ୍କ୍ରିନକୁ ବନ୍ଦ କରିଥାଏ।\n\nଆପଣଙ୍କ ଟିପଚିହ୍ନ ଯାଞ୍ଚ କରିବା ପାଇଁ ଧୀରେ ଟାପ କରିବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ସ୍କ୍ରିନ ବନ୍ଦ କରନ୍ତୁ"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"ସେଟଅପ୍ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"ସେଟ୍ ଅପ୍ କରିବାକୁ ଚୟନ କରନ୍ତୁ"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"ଆପଣଙ୍କୁ ପୁଣି ଡିଭାଇସ୍ ଫର୍ମାଟ୍ କରିବାକୁ ପଡ଼ିପାରେ। ବାହାର କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ଫଟୋ ଓ ମିଡିଆ ସ୍ଥାନାନ୍ତର କରାଯିବା ପାଇଁ"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ଫଟୋ, ଭିଡିଓ, ମ୍ୟୁଜିକ ଏବଂ ଆହୁରି ଅନେକ କିଛି ଷ୍ଟୋର କରିବା ପାଇଁ"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"ମିଡିଆ ଫାଇଲଗୁଡ଼ିକୁ ବ୍ରାଉଜ୍ କରନ୍ତୁ"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> ସହ ସମସ୍ୟା"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> କାମ କରୁନାହିଁ"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"ଠିକ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> ଖରାପ ହୋଇଯାଇଛି। ଠିକ୍ କରିବାକୁ ଚୟନ କରନ୍ତୁ।"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"ଆପଣଙ୍କୁ ପୁଣି ଡିଭାଇସ୍ ଫର୍ମାଟ୍ କରିବାକୁ ପଡ଼ିପାରେ। ବାହାର କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> ସପୋର୍ଟ କରୁନାହିଁ"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> ଚିହ୍ନଟ କରାଯାଇଛି"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> କାମ କରୁନାହିଁ"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ଏହି ଡିଭାଇସ୍ ଏହି <xliff:g id="NAME">%s</xliff:g>କୁ ସପୋର୍ଟ କରେନାହିଁ। ଗୋଟିଏ ସପୋର୍ଟ କରୁଥିବା ଫର୍ମାଟ୍ରେ ସେଟ୍ ଅପ୍ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"ସେଟ ଅପ କରିବା ପାଇଁ ଟାପ କରନ୍ତୁ।"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"<xliff:g id="NAME">%s</xliff:g>କୁ ଏକ ସମର୍ଥିତ ଫର୍ମାଟରେ ସେଟ୍ ଅପ୍ କରିବାକୁ ଚୟନ କରନ୍ତୁ।"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"ଆପଣଙ୍କୁ ପୁଣି ଡିଭାଇସ୍ ଫର୍ମାଟ୍ କରିବାକୁ ପଡ଼ିପାରେ"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>କୁ ହଠାତ୍ କାଢ଼ିଦିଆଗଲା"</string>
@@ -1469,7 +1469,7 @@
<string name="ime_action_previous" msgid="6548799326860401611">"ପୂର୍ବବର୍ତ୍ତୀ"</string>
<string name="ime_action_default" msgid="8265027027659800121">"କାମ କରନ୍ତୁ"</string>
<string name="dial_number_using" msgid="6060769078933953531">"<xliff:g id="NUMBER">%s</xliff:g>ବ୍ୟବହାର କରି\n ଡାଏଲ୍ କରନ୍ତୁ"</string>
- <string name="create_contact_using" msgid="6200708808003692594">"<xliff:g id="NUMBER">%s</xliff:g>ବ୍ୟବହାର କରି\n ଯୋଗାଯୋଗ ତିଆରି କରନ୍ତୁ"</string>
+ <string name="create_contact_using" msgid="6200708808003692594">"<xliff:g id="NUMBER">%s</xliff:g>ବ୍ୟବହାର କରି\n କଣ୍ଟାକ୍ଟ ତିଆରି କରନ୍ତୁ"</string>
<string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"ବର୍ତ୍ତମାନ ଓ ଭବିଷ୍ୟତରେ ଆପଣଙ୍କ ଆକାଉଣ୍ଟ ଆକ୍ସେସ୍ କରିବାକୁ ନିମ୍ନରୁ ଗୋଟିଏ କିମ୍ବା ଅଧିକ ଆପ୍ ଅନୁମତି ଅନୁରୋଧ କରନ୍ତି।"</string>
<string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"ଆପଣ ଏହି ଅନୁରୋଧକୁ ଅନୁମତି ଦେବାକୁ ଚାହାଁନ୍ତି କି?"</string>
<string name="grant_permissions_header_text" msgid="3420736827804657201">"ଆକ୍ସେସ୍ ଅନୁରୋଧ"</string>
@@ -1561,7 +1561,7 @@
<string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ସହ ସେୟାର୍ କରନ୍ତୁ"</string>
<string name="content_description_sliding_handle" msgid="982510275422590757">"ହ୍ୟାଣ୍ଡେଲ୍ ସ୍ଲାଇଡ୍ କରାଯାଉଛି। ସ୍ପର୍ଶ କରି ଧରିରଖନ୍ତୁ।"</string>
<string name="description_target_unlock_tablet" msgid="7431571180065859551">"ଅନଲକ୍ କରିବାକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ।"</string>
- <string name="action_bar_home_description" msgid="1501655419158631974">"ହୋମ୍ ପେଜ୍କୁ ନେଭିଗେଟ୍ କରନ୍ତୁ"</string>
+ <string name="action_bar_home_description" msgid="1501655419158631974">"ହୋମକୁ ନେଭିଗେଟ କରନ୍ତୁ"</string>
<string name="action_bar_up_description" msgid="6611579697195026932">"ଉପରକୁ ନେଭିଗେଟ୍ କରନ୍ତୁ"</string>
<string name="action_menu_overflow_description" msgid="4579536843510088170">"ଅଧିକ ବିକଳ୍ପ"</string>
<string name="action_bar_home_description_format" msgid="5087107531331621803">"%1$s, %2$s"</string>
@@ -1611,12 +1611,12 @@
<string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"%1$s ୱର୍କ ପ୍ରୋଫାଇଲ୍କୁ ସପୋର୍ଟ କରୁନାହିଁ"</string>
<string name="default_audio_route_name" product="tablet" msgid="367936735632195517">"ଟାବଲେଟ୍"</string>
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
- <string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ଫୋନ୍"</string>
+ <string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ଫୋନ"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"ଡକ୍ ସ୍ପିକର୍"</string>
<string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
<string name="default_audio_route_name_headphones" msgid="6954070994792640762">"ହେଡଫୋନ୍"</string>
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
- <string name="default_audio_route_category_name" msgid="5241740395748134483">"ସିଷ୍ଟମ୍"</string>
+ <string name="default_audio_route_category_name" msgid="5241740395748134483">"ସିଷ୍ଟମ"</string>
<string name="bluetooth_a2dp_audio_route_name" msgid="4214648773120426288">"ବ୍ଲୁଟୂଥ୍ ଅଡିଓ"</string>
<string name="wireless_display_route_description" msgid="8297563323032966831">"ୱେୟାର୍ଲେସ୍ ଡିସ୍ପ୍ଲେ"</string>
<string name="media_route_button_content_description" msgid="2299223698196869956">"କାଷ୍ଟ କରନ୍ତୁ"</string>
@@ -1643,7 +1643,7 @@
<string name="kg_sim_pin_instructions" msgid="6479401489471690359">"SIM PIN ଲେଖନ୍ତୁ"</string>
<string name="kg_pin_instructions" msgid="7355933174673539021">"PIN ଲେଖନ୍ତୁ"</string>
<string name="kg_password_instructions" msgid="7179782578809398050">"ପାସ୍ୱର୍ଡ ଲେଖନ୍ତୁ"</string>
- <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM ବର୍ତ୍ତମାନ ଅକ୍ଷମ ଅଟେ। ଜାରି ରଖିବାକୁ PUK କୋଡ୍ ଏଣ୍ଟର୍ କରନ୍ତୁ। ବିବରଣୀ ପାଇଁ ନିଜ କେରିଅର୍ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM ବର୍ତ୍ତମାନ ଅକ୍ଷମ ଅଟେ। ଜାରି ରଖିବାକୁ PUK କୋଡ ଲେଖନ୍ତୁ। ବିବରଣୀ ପାଇଁ ନିଜ କ୍ଯାରିଅରଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"ନିଜ ଇଚ୍ଛାର PIN କୋଡ୍ ଲେଖନ୍ତୁ"</string>
<string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"ନିଜ ଇଚ୍ଛାର PIN କୋଡ୍ ନିଶ୍ଚିତ କରନ୍ତୁ"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"SIM କାର୍ଡ ଅନଲକ୍ କରାଯାଉଛି…"</string>
@@ -1885,7 +1885,7 @@
<string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"ଶୋଇବା"</string>
<string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> କିଛି ସାଉଣ୍ଡକୁ ମ୍ୟୁଟ୍ କରୁଛି"</string>
<string name="system_error_wipe_data" msgid="5910572292172208493">"ଆପଣଙ୍କ ଡିଭାଇସ୍ରେ ଏକ ସମସ୍ୟା ରହିଛି ଏବଂ ଆପଣ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଅସ୍ଥିର ରହିପାରେ।"</string>
- <string name="system_error_manufacturer" msgid="703545241070116315">"ଆପଣଙ୍କ ଡିଭାଇସ୍ରେ ଏକ ସମସ୍ୟା ରହିଛି। ବିବରଣୀ ପାଇଁ ଆପଣଙ୍କ ଉତ୍ପାଦକଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="system_error_manufacturer" msgid="703545241070116315">"ଆପଣଙ୍କ ଡିଭାଇସରେ ଏକ ସମସ୍ୟା ରହିଛି। ବିବରଣୀ ପାଇଁ ଆପଣଙ୍କ ଉତ୍ପାଦକଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="stk_cc_ussd_to_dial" msgid="3139884150741157610">"USSD ଅନୁରୋଧ, ସ୍ଵାଭାବିକ କଲ୍ରେ ପରିବର୍ତ୍ତନ ହେଲା"</string>
<string name="stk_cc_ussd_to_ss" msgid="4826846653052609738">"USSD ଅନୁରୋଧ, SS ଅନୁରୋଧକୁ ପରିବର୍ତ୍ତନ ହେଲା"</string>
<string name="stk_cc_ussd_to_ussd" msgid="8343001461299302472">"ନୂତନ USSD ଅନୁରୋଧରେ ପରିବର୍ତ୍ତନ ହେଲା"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"ପସନ୍ଦର ଅଞ୍ଚଳ"</string>
<string name="search_language_hint" msgid="7004225294308793583">"ଭାଷାର ନାମ ଟାଇପ୍ କରନ୍ତୁ"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"ପ୍ରସ୍ତାବିତ"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"ପ୍ରସ୍ତାବିତ"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"ସମସ୍ତ ଭାଷା"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"ସମସ୍ତ ଅଞ୍ଚଳ"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"ସନ୍ଧାନ କରନ୍ତୁ"</string>
@@ -1934,7 +1935,7 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"ବର୍ତ୍ତମାନ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ଉପଲବ୍ଧ ନାହିଁ। ଏହା <xliff:g id="APP_NAME_1">%2$s</xliff:g> ଦ୍ଵାରା ପରିଚାଳିତ ହେଉଛି।"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ଆପ୍ ଅନପଜ୍ କରନ୍ତୁ"</string>
- <string name="work_mode_off_title" msgid="961171256005852058">"ୱାର୍କ ଆପଗୁଡ଼ିକୁ ଚାଲୁ କରିବେ?"</string>
+ <string name="work_mode_off_title" msgid="961171256005852058">"ୱାର୍କ ଆପ୍ସ ଚାଲୁ କରିବେ?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"ଆପଣଙ୍କ ୱାର୍କ ଆପ୍ ଏବଂ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ ପାଆନ୍ତୁ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ଚାଲୁ କରନ୍ତୁ"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"ଆପ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
@@ -1957,7 +1958,7 @@
<string name="app_streaming_blocked_message_for_settings_dialog" product="tv" msgid="820334666354451145">"ଏହାକୁ ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରେ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ Android TV ଡିଭାଇସରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="app_streaming_blocked_message_for_settings_dialog" product="tablet" msgid="3286849551133045896">"ଏହାକୁ ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରେ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ ଟାବଲେଟରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"ଏହାକୁ ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରେ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ ଫୋନରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ଏହି ଆପ୍କୁ Androidର ପୁରୁଣା ଭର୍ସନ୍ ପାଇଁ ନିର୍ମାଣ କରାଯାଇଥିଲା ଏବଂ ଠିକ୍ ଭାବେ କାମ କରିନପାରେ। ଏହାପାଇଁ ଅପଡେଟ୍ ଅଛି କି ନାହିଁ ଯାଞ୍ଚ କରନ୍ତୁ କିମ୍ବା ଡେଭେଲପର୍ଙ୍କ ସହିତ ସମ୍ପର୍କ କରନ୍ତୁ।"</string>
+ <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ଏହି ଆପକୁ Androidର ପୁରୁଣା ସଂସ୍କରଣ ପାଇଁ ନିର୍ମାଣ କରାଯାଇଥିଲା ଏବଂ ଠିକ୍ ଭାବେ କାମ କରିନପାରେ। ଏଥିପାଇଁ ଅପଡେଟ ଅଛି କି ନାହିଁ ଯାଞ୍ଚ କରନ୍ତୁ କିମ୍ବା ଡେଭେଲପରଙ୍କ ସହିତ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ଅପଡେଟ୍ ପାଇଁ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
<string name="new_sms_notification_title" msgid="6528758221319927107">"ଆପଣଙ୍କ ପାଖରେ ନୂଆ ମେସେଜ୍ ରହିଛି"</string>
<string name="new_sms_notification_content" msgid="3197949934153460639">"ଦେଖିବା ପାଇଁ SMS ଆପ୍ ଖୋଲନ୍ତୁ"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"ସମସ୍ତ ଡିଭାଇସ ଲଗକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"ଗୋଟିଏ-ଥର ଆକ୍ସେସ ପାଇଁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"ଆପଣଙ୍କ ଡିଭାଇସରେ ଯାହା ହୁଏ ତାହା ଡିଭାଇସ ଲଗଗୁଡ଼ିକ ରେକର୍ଡ କରେ। ସମସ୍ୟାଗୁଡ଼ିକୁ ଖୋଜି ସମାଧାନ କରିବାକୁ ଆପ୍ସ ଏହି ଲଗଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିପାରିବ।\n\nକିଛି ଲଗରେ ସମ୍ବେଦନଶୀଳ ସୂଚନା ଥାଇପାରେ, ତେଣୁ ସମସ୍ତ ଡିଭାଇସ ଲଗକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଆପଣ ବିଶ୍ୱାସ କରୁଥିବା ଆପ୍ସକୁ ହିଁ ଅନୁମତି ଦିଅନ୍ତୁ। \n\nଯଦି ଆପଣ ସମସ୍ତ ଡିଭାଇସ ଲଗକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଏହି ଆପକୁ ଅନୁମତି ଦିଅନ୍ତି ନାହିଁ, ତେବେ ବି ଏହା ନିଜର ଡିଭାଇସ ଲଗଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିପାରିବ। ଆପଣଙ୍କ ଡିଭାଇସର ନିର୍ମାତା ଏବେ ବି ଆପଣଙ୍କର ଡିଭାଇସରେ କିଛି ଲଗ କିମ୍ବା ସୂଚନାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ସକ୍ଷମ ହୋଇପାରନ୍ତି। ଅଧିକ ଜାଣନ୍ତୁ"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"ଆପଣଙ୍କ ଡିଭାଇସରେ ଯାହା ହୁଏ ତାହା ଡିଭାଇସ ଲଗଗୁଡ଼ିକ ରେକର୍ଡ କରେ। ସମସ୍ୟାଗୁଡ଼ିକୁ ଖୋଜି ସମାଧାନ କରିବାକୁ ଆପ୍ସ ଏହି ଲଗଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିପାରିବ।\n\nକିଛି ଲଗରେ ସମ୍ବେଦନଶୀଳ ସୂଚନା ଥାଇପାରେ, ତେଣୁ ସମସ୍ତ ଡିଭାଇସ ଲଗକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଆପଣ ବିଶ୍ୱାସ କରୁଥିବା ଆପ୍ସକୁ ହିଁ ଅନୁମତି ଦିଅନ୍ତୁ। \n\nଯଦି ଆପଣ ସମସ୍ତ ଡିଭାଇସ ଲଗକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଏହି ଆପକୁ ଅନୁମତି ଦିଅନ୍ତି ନାହିଁ, ତେବେ ବି ଏହା ନିଜର ଡିଭାଇସ ଲଗଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିପାରିବ। ଆପଣଙ୍କ ଡିଭାଇସର ନିର୍ମାତା ଏବେ ବି ଆପଣଙ୍କର ଡିଭାଇସରେ କିଛି ଲଗ କିମ୍ବା ସୂଚନାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ସକ୍ଷମ ହୋଇପାରନ୍ତି।"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"ପୁଣି ଦେଖାନ୍ତୁ ନାହିଁ"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g>, <xliff:g id="APP_2">%2$s</xliff:g> ସ୍ଲାଇସ୍କୁ ଦେଖାଇବା ପାଇଁ ଚାହେଁ"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"ଏଡିଟ କରନ୍ତୁ"</string>
@@ -2065,10 +2066,10 @@
<string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13ଠାରୁ, ଆପଣ ଇନଷ୍ଟଲ କରୁଥିବା ଆପ୍ସ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ପଠାଇବା ପାଇଁ ଆପଣଙ୍କ ଅନୁମତି ଆବଶ୍ୟକ କରେ। ପୂର୍ବରୁ ଥିବା ଆପ୍ସ ପାଇଁ ଏହି ଅନୁମତିକୁ ପରିବର୍ତ୍ତନ କରିବାକୁ ଟାପ କରନ୍ତୁ।"</string>
<string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"ମୋତେ ପରେ ରିମାଇଣ୍ଡ କର"</string>
<string name="review_notification_settings_dismiss" msgid="4160916504616428294">"ଖାରଜ କରନ୍ତୁ"</string>
- <string name="notification_app_name_system" msgid="3045196791746735601">"ସିଷ୍ଟମ୍"</string>
+ <string name="notification_app_name_system" msgid="3045196791746735601">"ସିଷ୍ଟମ"</string>
<string name="notification_app_name_settings" msgid="9088548800899952531">"ସେଟିଂସ୍"</string>
<string name="notification_appops_camera_active" msgid="8177643089272352083">"କ୍ୟାମେରା"</string>
- <string name="notification_appops_microphone_active" msgid="581333393214739332">"ମାଇକ୍ରୋଫୋନ୍"</string>
+ <string name="notification_appops_microphone_active" msgid="581333393214739332">"ମାଇକ୍ରୋଫୋନ"</string>
<string name="notification_appops_overlay_active" msgid="5571732753262836481">"ଆପଣଙ୍କ ସ୍କ୍ରୀନ୍ ଉପରେ ଥିବା ଅନ୍ୟ ଆପ୍ ଉପରେ ଦେଖାଦେବ"</string>
<string name="notification_feedback_indicator" msgid="663476517711323016">"ମତାମତ ଦିଅନ୍ତୁ"</string>
<string name="notification_feedback_indicator_alerted" msgid="6552871804121942099">"ଏହି ବିଜ୍ଞପ୍ତିକୁ ଡିଫଲ୍ଟ ଭାବେ ପ୍ରମୋଟ୍ କରାଯାଇଛି। ମତାମତ ପ୍ରଦାନ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
@@ -2080,7 +2081,7 @@
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ଠିକ୍ ଅଛି"</string>
<string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
- <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12ରେ Android ଆଡେପ୍ଟିଭ୍ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଉନ୍ନତ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକରେ ପରିବର୍ତ୍ତନ କରାଯାଇଛି। ଏହି ଫିଚର୍ ପ୍ରସ୍ତାବିତ କାର୍ଯ୍ୟ ଏବଂ ପ୍ରତ୍ୟୁତ୍ତରଗୁଡ଼ିକୁ ଦେଖାଏ ଏବଂ ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ବ୍ୟବସ୍ଥିତ କରେ।\n\nଉନ୍ନତ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଯୋଗାଯୋଗ ନାମ ଏବଂ ମେସେଜଗୁଡ଼ିକ ପରି ବ୍ୟକ୍ତିଗତ ସୂଚନା ସମେତ ବିଜ୍ଞପ୍ତିର ବିଷୟବସ୍ତୁକୁ ଆକ୍ସେସ୍ କରିପାରିବ। ଏହି ଫିଚର୍ ଫୋନ୍ କଲଗୁଡ଼ିକର ଉତ୍ତର ଦେବା ଏବଂ \'ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\'କୁ ନିୟନ୍ତ୍ରଣ କରିବା ପରି, ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ମଧ୍ୟ ଖାରଜ କରିପାରିବ କିମ୍ବା ସେଗୁଡ଼ିକର ଉତ୍ତର ଦେଇପାରିବ।"</string>
+ <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12ରେ Android ଆଡେପ୍ଟିଭ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଉନ୍ନତ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକରେ ପରିବର୍ତ୍ତନ କରାଯାଇଛି। ଏହି ଫିଚର ପ୍ରସ୍ତାବିତ କାର୍ଯ୍ୟ ଏବଂ ପ୍ରତ୍ୟୁତ୍ତରଗୁଡ଼ିକୁ ଦେଖାଏ ଏବଂ ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ବ୍ୟବସ୍ଥିତ କରେ।\n\nଉନ୍ନତ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ କଣ୍ଟାକ୍ଟ ନାମ ଏବଂ ମେସେଜଗୁଡ଼ିକ ପରି ବ୍ୟକ୍ତିଗତ ସୂଚନା ସମେତ ବିଜ୍ଞପ୍ତିର ବିଷୟବସ୍ତୁକୁ ଆକ୍ସେସ କରିପାରିବ। ଏହି ଫିଚର ଫୋନ କଲଗୁଡ଼ିକର ଉତ୍ତର ଦେବା ଏବଂ \'ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\'କୁ ନିୟନ୍ତ୍ରଣ କରିବା ପରି, ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ମଧ୍ୟ ଖାରଜ କରିପାରିବ କିମ୍ବା ସେଗୁଡ଼ିକର ଉତ୍ତର ଦେଇପାରିବ।"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ନିୟମିତ ମୋଡ୍ ସୂଚନା ବିଜ୍ଞପ୍ତି"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ସାଧାରଣ ଭାବରେ ଚାର୍ଜ୍ କରିବା ପୂର୍ବରୁ ବ୍ୟାଟେରୀ ସରିଯାଇପାରେ"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ବ୍ୟାଟେରୀର ସମୟକୁ ବଢ଼ାଇବା ପାଇଁ ବ୍ୟଟେରୀ ସେଭର୍କୁ କାର୍ଯ୍ୟକାରୀ କରାଯାଇଛି"</string>
@@ -2113,7 +2114,7 @@
<string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ଏହାକୁ ସେୟାର୍ କରିବା ପାଇଁ କୌଣସି ସୁପାରିଶ କରାଯାଇଥିବା ଲୋକ ନାହାଁନ୍ତି"</string>
<string name="chooser_all_apps_button_label" msgid="3230427756238666328">"ଆପ୍ସ ତାଲିକା"</string>
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"ଏହି ଆପ୍କୁ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ କିନ୍ତୁ ଏହି USB ଡିଭାଇସ୍ ଜରିଆରେ ଅଡିଓ କ୍ୟାପ୍ଚର୍ କରିପାରିବ।"</string>
- <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"ମୂଳପୃଷ୍ଠା"</string>
+ <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"ହୋମ"</string>
<string name="accessibility_system_action_back_label" msgid="4205361367345537608">"ପଛକୁ ଫେରନ୍ତୁ"</string>
<string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"ବର୍ତ୍ତମାନର ଆପ୍ଗୁଡ଼ିକ"</string>
<string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଖୋଲନ୍ତୁ"</string>
@@ -2178,7 +2179,7 @@
<string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"PUK ଲେଖନ୍ତୁ"</string>
<string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"PUK ଲେଖନ୍ତୁ"</string>
<string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"SPN ଅନଲକ୍ PIN"</string>
- <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"SP ଇକ୍ୟୁଭେଲେଣ୍ଟ ହୋମ୍ PLMN ଅନଲକ୍ PIN"</string>
+ <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"SP ଇକ୍ୟୁଭେଲେଣ୍ଟ ହୋମ PLMN ଅନଲକ PIN"</string>
<string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCID ଅନଲକ୍ PIN"</string>
<string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"IMPI ଅନଲକ୍ PIN"</string>
<string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"ନେଟୱାର୍କ ସବସେଟର ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ PIN"</string>
@@ -2198,7 +2199,7 @@
<string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"RUIM ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
<string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"RUIM କର୍ପୋରେଟ୍ ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
<string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"SPN ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
- <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP ଇକ୍ୟୁଭେଲେଣ୍ଟ ହୋମ୍ PLMN ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+ <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP ଇକ୍ୟୁଭେଲେଣ୍ଟ ହୋମ PLMN ଅନଲକ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
<string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
<string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPI ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
<string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"ନେଟୱାର୍କ ସବସେଟର ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
@@ -2232,7 +2233,7 @@
<string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
<string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
<string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
- <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP ଇକ୍ୟୁଭେଲେଣ୍ଟ ହୋମ୍ PLMN ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+ <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP ଇକ୍ୟୁଭେଲେଣ୍ଟ ହୋମ PLMN ଅନଲକ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
<string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
<string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
<string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"ନେଟୱାର୍କ ସବସେଟର ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
@@ -2259,7 +2260,7 @@
<string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
<string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
<string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"SPN ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
- <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"SP ଇକ୍ୟୁଭେଲେଣ୍ଟ ହୋମ୍ PLMN ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+ <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"SP ଇକ୍ୟୁଭେଲେଣ୍ଟ ହୋମ PLMN ଅନଲକ କରିବା ସଫଳ ହୋଇଛି।"</string>
<string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"ICCID ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
<string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"IMPI ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
<string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"ନେଟୱାର୍କ ସବସେଟର ସେବା ପ୍ରଦାନକାରୀକୁ ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
@@ -2271,10 +2272,10 @@
<string name="window_magnification_prompt_content" msgid="8159173903032344891">"ଆପଣ ଏବେ ଆପଣଙ୍କ ସ୍କ୍ରିନର ଅଂଶକୁ ମ୍ୟାଗ୍ନିଫାଏ କରିପାରିବେ"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ସେଟିଂସରେ ଚାଲୁ କରନ୍ତୁ"</string>
<string name="dismiss_action" msgid="1728820550388704784">"ଖାରଜ କରନ୍ତୁ"</string>
- <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"ଡିଭାଇସର ମାଇକ୍ରୋଫୋନକୁ ଅନବ୍ଲକ୍ କରନ୍ତୁ"</string>
- <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"ଡିଭାଇସର କ୍ୟାମେରାକୁ ଅନବ୍ଲକ୍ କରନ୍ତୁ"</string>
+ <string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"ଡିଭାଇସର ମାଇକ୍ରୋଫୋନକୁ ଅନବ୍ଲକ କରନ୍ତୁ"</string>
+ <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"ଡିଭାଇସର କ୍ୟାମେରାକୁ ଅନବ୍ଲକ କରନ୍ତୁ"</string>
<string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"<b><xliff:g id="APP">%s</xliff:g></b> ଏବଂ ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ"</string>
- <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"ଅନବ୍ଲକ୍ କରନ୍ତୁ"</string>
+ <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"ଅନବ୍ଲକ କରନ୍ତୁ"</string>
<string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ସେନ୍ସର୍ ଗୋପନୀୟତା"</string>
<string name="splash_screen_view_icon_description" msgid="180638751260598187">"ଆପ୍ଲିକେସନ୍ ଆଇକନ୍"</string>
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ଆପ୍ଲିକେସନ୍ ବ୍ରାଣ୍ଡିଂ ଛବି"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ସକ୍ରିୟ ଆପଗୁଡ଼ିକୁ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରୁ ଫୋନର କ୍ୟାମେରାକୁ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରୁ ଟାବଲେଟର କ୍ୟାମେରାକୁ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"ଷ୍ଟ୍ରିମ କରିବା ସମୟରେ ଏହାକୁ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ ଫୋନରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="system_locale_title" msgid="711882686834677268">"ସିଷ୍ଟମ ଡିଫଲ୍ଟ"</string>
</resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 593235e..53a7807 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਓਪਰੇਸ਼ਨ ਰੱਦ ਕੀਤਾ ਗਿਆ।"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਓਪਰੇਸ਼ਨ ਵਰਤੋਂਕਾਰ ਵੱਲੋਂ ਰੱਦ ਕੀਤਾ ਗਿਆ।"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ. ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"ਹੱਦੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ। ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ।"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ਕੋਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਰਜ ਨਹੀਂ ਕੀਤੇ ਗਏ।"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ਇਸ ਡੀਵਾਈਸ ਵਿੱਚ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨਹੀਂ ਹੈ।"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> ਤਿਆਰ ਕਰ ਰਿਹਾ ਹੈ।"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ਐਪਸ ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ।"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"ਬੂਟ ਪੂਰਾ ਕਰ ਰਿਹਾ ਹੈ।"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"ਕੀ ਸੈੱਟਅੱਪ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ਤੁਸੀਂ ਪਾਵਰ ਬਟਨ ਨੂੰ ਦਬਾਇਆ ਹੈ — ਇਹ ਆਮ ਤੌਰ \'ਤੇ ਸਕ੍ਰੀਨ ਨੂੰ ਬੰਦ ਕਰ ਦਿੰਦਾ ਹੈ।\n\nਆਪਣੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸੈੱਟਅੱਪ ਕਰਦੇ ਸਮੇਂ ਹਲਕਾ ਜਿਹਾ ਟੈਪ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"ਸਕ੍ਰੀਨ ਬੰਦ ਕਰੋ"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"ਸੈੱਟਅੱਪ ਜਾਰੀ ਰੱਖੋ"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ਸਕ੍ਰੀਨ ਬੰਦ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ਸਕ੍ਰੀਨ ਬੰਦ ਕਰੋ"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"ਕੀ ਆਪਣੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"ਤੁਸੀਂ ਪਾਵਰ ਬਟਨ ਨੂੰ ਦਬਾਇਆ ਹੈ — ਇਹ ਆਮ ਤੌਰ \'ਤੇ ਸਕ੍ਰੀਨ ਨੂੰ ਬੰਦ ਕਰ ਦਿੰਦਾ ਹੈ।\n\nਆਪਣੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਹਲਕਾ ਜਿਹਾ ਟੈਪ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ਸਕ੍ਰੀਨ ਬੰਦ ਕਰੋ"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"ਸੈੱਟਅੱਪ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"ਸੈੱਟਅੱਪ ਕਰਨ ਲਈ ਚੁਣੋ"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"ਤੁਹਾਨੂੰ ਡੀਵਾਈਸ ਨੂੰ ਮੁੜ-ਫਾਰਮੈਟ ਕਰਨ ਦੀ ਲੋੜ ਪੈ ਸਕਦੀ ਹੈ। ਕੱਢਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ ਨੂੰ ਟ੍ਰਾਂਸਫ਼ਰ ਕਰਨ ਲਈ"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ਫ਼ੋਟੋਆਂ, ਵੀਡੀਓ, ਸੰਗੀਤ ਅਤੇ ਹੋਰ ਚੀਜ਼ਾਂ ਨੂੰ ਸਟੋਰ ਕਰਨ ਲਈ"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"ਮੀਡੀਆ ਫ਼ਾਈਲਾਂ ਨੂੰ ਬ੍ਰਾਊਜ਼ ਕਰੋ"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> ਵਿੱਚ ਸਮੱਸਿਆ ਆਈ"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ਕੰਮ ਨਹੀਂ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"ਠੀਕ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> ਖਰਾਬ ਹੈ। ਠੀਕ ਕਰਨ ਲਈ ਚੁਣੋ।"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"ਤੁਹਾਨੂੰ ਡੀਵਾਈਸ ਨੂੰ ਮੁੜ-ਫਾਰਮੈਟ ਕਰਨ ਦੀ ਲੋੜ ਪੈ ਸਕਦੀ ਹੈ। ਕੱਢਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"ਅਸਮਰਥਿਤ <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> ਦੀ ਪਛਾਣ ਕੀਤੀ ਗਈ"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ਕੰਮ ਨਹੀਂ ਕਰ ਰਿਹਾ ਹੈ"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ਇਹ ਡੀਵਾਈਸ ਇਸ <xliff:g id="NAME">%s</xliff:g> ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ ਹੈ। ਕਿਸੇ ਸਮਰਥਿਤ ਫਾਰਮੈਟ ਵਿੱਚ ਸਥਾਪਤ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"ਸੈੱਟਅੱਪ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"ਕਿਸੇ ਸਮਰਥਿਤ ਫਾਰਮੈਟ ਵਿੱਚ <xliff:g id="NAME">%s</xliff:g> ਦਾ ਸੈੱਟਅੱਪ ਕਰਨ ਲਈ ਚੁਣੋ।"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"ਤੁਹਾਨੂੰ ਡੀਵਾਈਸ ਨੂੰ ਮੁੜ-ਫਾਰਮੈਟ ਕਰਨ ਦੀ ਲੋੜ ਪੈ ਸਕਦੀ ਹੈ"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ਨੂੰ ਅਚਨਚੇਤ ਹਟਾਇਆ ਗਿਆ"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"ਖੇਤਰ ਤਰਜੀਹ"</string>
<string name="search_language_hint" msgid="7004225294308793583">"ਭਾਸ਼ਾ ਦਾ ਨਾਮ ਟਾਈਪ ਕਰੋ"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"ਸੁਝਾਈਆਂ ਗਈਆਂ"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"ਸੁਝਾਈਆਂ ਗਈਆਂ"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"ਸਾਰੀਆਂ ਭਾਸ਼ਾਵਾਂ"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"ਸਾਰੇ ਖੇਤਰ"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"ਖੋਜੋ"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"ਕੀ <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ਨੂੰ ਸਾਰੇ ਡੀਵਾਈਸ ਲੌਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"ਇੱਕ-ਵਾਰ ਲਈ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"ਆਗਿਆ ਨਾ ਦਿਓ"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"ਡੀਵਾਈਸ ਲੌਗਾਂ ਵਿੱਚ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀਆਂ ਕਾਰਵਾਈਆਂ ਰਿਕਾਰਡ ਹੁੰਦੀਆਂ ਹਨ। ਐਪਾਂ ਸਮੱਸਿਆਵਾਂ ਨੂੰ ਲੱਭਣ ਅਤੇ ਉਨ੍ਹਾਂ ਦਾ ਹੱਲ ਕਰਨ ਲਈ ਇਨ੍ਹਾਂ ਲੌਗਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੀਆਂ ਹਨ।\n\nਕੁਝ ਲੌਗਾਂ ਵਿੱਚ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੋ ਸਕਦੀ ਹੈ, ਇਸ ਲਈ ਸਿਰਫ਼ ਆਪਣੀਆਂ ਭਰੋਸੇਯੋਗ ਐਪਾਂ ਨੂੰ ਹੀ ਸਾਰੇ ਡੀਵਾਈਸ ਲੌਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ। \n\nਜੇ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਸਾਰੇ ਡੀਵਾਈਸ ਲੌਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਨਹੀਂ ਦਿੰਦੇ ਹੋ, ਤਾਂ ਇਹ ਹਾਲੇ ਵੀ ਆਪਣੇ ਲੌਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ। ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਨਿਰਮਾਤਾ ਹਾਲੇ ਵੀ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਮੌਜੂਦ ਕੁਝ ਲੌਗਾਂ ਜਾਂ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦਾ ਹੈ। ਹੋਰ ਜਾਣੋ"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"ਡੀਵਾਈਸ ਲੌਗਾਂ ਵਿੱਚ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀਆਂ ਕਾਰਵਾਈਆਂ ਰਿਕਾਰਡ ਹੁੰਦੀਆਂ ਹਨ। ਐਪਾਂ ਸਮੱਸਿਆਵਾਂ ਨੂੰ ਲੱਭਣ ਅਤੇ ਉਨ੍ਹਾਂ ਦਾ ਹੱਲ ਕਰਨ ਲਈ ਇਨ੍ਹਾਂ ਲੌਗਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੀਆਂ ਹਨ।\n\nਕੁਝ ਲੌਗਾਂ ਵਿੱਚ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੋ ਸਕਦੀ ਹੈ, ਇਸ ਲਈ ਸਿਰਫ਼ ਆਪਣੀਆਂ ਭਰੋਸੇਯੋਗ ਐਪਾਂ ਨੂੰ ਹੀ ਸਾਰੇ ਡੀਵਾਈਸ ਲੌਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ। \n\nਜੇ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਸਾਰੇ ਡੀਵਾਈਸ ਲੌਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਨਹੀਂ ਦਿੰਦੇ ਹੋ, ਤਾਂ ਇਹ ਹਾਲੇ ਵੀ ਆਪਣੇ ਲੌਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ। ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਨਿਰਮਾਤਾ ਹਾਲੇ ਵੀ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਮੌਜੂਦ ਕੁਝ ਲੌਗਾਂ ਜਾਂ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦਾ ਹੈ।"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"ਦੁਬਾਰਾ ਨਾ ਦਿਖਾਓ"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> ਦੀ <xliff:g id="APP_2">%2$s</xliff:g> ਦੇ ਹਿੱਸੇ ਦਿਖਾਉਣ ਦੀ ਇੱਛਾ ਹੈ"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"ਸੰਪਾਦਨ ਕਰੋ"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ਕਿਰਿਆਸ਼ੀਲ ਐਪਾਂ ਦੀ ਜਾਂਚ ਕਰੋ"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"ਤੁਹਾਡੇ <xliff:g id="DEVICE">%1$s</xliff:g> ਤੋਂ ਫ਼ੋਨ ਦੇ ਕੈਮਰੇ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"ਤੁਹਾਡੇ <xliff:g id="DEVICE">%1$s</xliff:g> ਤੋਂ ਟੈਬਲੈੱਟ ਦੇ ਕੈਮਰੇ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"ਸਟ੍ਰੀਮਿੰਗ ਦੌਰਾਨ ਇਸ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਇਸਦੀ ਬਜਾਏ ਆਪਣੇ ਫ਼ੋਨ \'ਤੇ ਵਰਤ ਕੇ ਦੇਖੋ।"</string>
<string name="system_locale_title" msgid="711882686834677268">"ਸਿਸਟਮ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 025b0c2..3866273 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -610,7 +610,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Odczyt odcisku palca został anulowany."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Odczyt odcisku palca został anulowany przez użytkownika."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Zbyt wiele prób. Spróbuj ponownie później."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Zbyt wiele prób. Czytnik linii papilarnych został wyłączony."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Spróbuj ponownie."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nie zarejestrowano odcisków palców."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"To urządzenie nie jest wyposażone w czytnik linii papilarnych."</string>
@@ -1251,10 +1252,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Przygotowuję aplikację <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Uruchamianie aplikacji."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Kończenie uruchamiania."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Kontynuować konfigurowanie?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Naciśnięto przycisk zasilania — zwykle powoduje to wyłączenie ekranu.\n\nKlikaj delikatnie podczas konfigurowania odcisku palca."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Wyłącz ekran"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Konfiguruj dalej"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Kliknij, aby wyłączyć ekran"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Wyłącz ekran"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Kontynuować weryfikację odcisku palca?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Naciśnięto przycisk zasilania — zwykle powoduje to wyłączenie ekranu.\n\nKliknij delikatnie, aby zweryfikować odcisk palca."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Wyłącz ekran"</string>
@@ -1407,16 +1407,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Kliknij, by skonfigurować"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Wybierz, aby skonfigurować"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Może być konieczne ponowne sformatowanie urządzenia. Kliknij, by je odłączyć."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Do przenoszenia zdjęć i multimediów"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Przechowywanie zdjęć, filmów, muzyki i innych treści"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Przeglądaj pliki multimediów"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Wystąpił problem z: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> nie działa"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Kliknij, by naprawić"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Nośnik <xliff:g id="NAME">%s</xliff:g> jest uszkodzony. Wybierz, by rozwiązać problem."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Może być konieczne ponowne sformatowanie urządzenia. Kliknij, by je odłączyć."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Nośnik <xliff:g id="NAME">%s</xliff:g> nieobsługiwany"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Wykryto nośnik <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> nie działa"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"To urządzenie nie obsługuje <xliff:g id="NAME">%s</xliff:g>. Kliknij, by użyć obsługiwanego formatu."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Kliknij, aby skonfigurować."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Wybierz, aby skonfigurować nośnik <xliff:g id="NAME">%s</xliff:g> w obsługiwanym formacie."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Może być konieczne ponowne sformatowanie urządzenia"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>: nieoczekiwane wyjęcie"</string>
@@ -1929,6 +1929,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Ustawienie regionu"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Wpisz nazwę języka"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Sugerowane"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Sugerowane"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Wszystkie języki"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Wszystkie kraje"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Szukaj"</string>
@@ -2051,7 +2052,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Zezwolić aplikacji <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> na dostęp do wszystkich dzienników urządzenia?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Zezwól na jednorazowy dostęp"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Nie zezwalaj"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Dzienniki urządzenia zapisują, co dzieje się na urządzeniu. Aplikacje mogą ich używać do wykrywania i rozwiązywania problemów.\n\nNiektóre dzienniki mogą zawierać poufne dane, dlatego na dostęp do wszystkich dzienników zezwalaj tylko aplikacjom, którym ufasz. \n\nNawet jeśli nie zezwolisz tej aplikacji na dostęp do wszystkich dzienników na urządzeniu, będzie miała dostęp do własnych. Producent urządzenia nadal będzie mógł korzystać z niektórych dzienników na urządzeniu. Więcej informacji"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Dzienniki urządzenia zapisują, co dzieje się na urządzeniu. Aplikacje mogą ich używać do wykrywania i rozwiązywania problemów.\n\nNiektóre dzienniki mogą zawierać poufne dane, dlatego na dostęp do wszystkich dzienników zezwalaj tylko aplikacjom, którym ufasz. \n\nNawet jeśli nie zezwolisz tej aplikacji na dostęp do wszystkich dzienników na urządzeniu, będzie mogła korzystać z własnych. Producent urządzenia nadal będzie mógł używać niektórych dzienników na urządzeniu."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Nie pokazuj ponownie"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Aplikacja <xliff:g id="APP_0">%1$s</xliff:g> chce pokazywać wycinki z aplikacji <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Edytuj"</string>
@@ -2292,5 +2293,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Sprawdź aktywne aplikacje"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nie można korzystać z aparatu telefonu na urządzeniu <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Nie można korzystać z aparatu tabletu na urządzeniu <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Nie można z tego skorzystać podczas strumieniowania. Użyj telefonu."</string>
<string name="system_locale_title" msgid="711882686834677268">"Ustawienie domyślne systemu"</string>
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 0dc380b7..cf57755 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operação de impressão digital cancelada."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operação de impressão digital cancelada pelo usuário."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Excesso de tentativas. Tente novamente mais tarde."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Excesso de tentativas. Sensor de impressão digital desativado."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Tente novamente."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nenhuma impressão digital registrada."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo não tem um sensor de impressão digital."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando apps."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Concluindo a inicialização."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Continuar a configuração?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Você pressionou o botão liga/desliga. Normalmente, essa ação desliga a tela.\n\nToque levemente na tela durante a configuração da impressão digital."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Desligar a tela"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Continuar configuração"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toque para desligar a tela"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Desligar a tela"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continuar a verificação da digital?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Você pressionou o botão liga/desliga. Normalmente, essa ação desliga a tela.\n\nToque levemente na tela para verificar sua impressão digital."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Desligar a tela"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Toque para configurar"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Selecione para configurar"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Pode ser necessário reformatar o dispositivo. Toque para ejetá-lo."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Para transferir fotos e mídia"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Para armazenamento de fotos, vídeos, músicas e muito mais"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Procure arquivos de mídia"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Ocorreu um problema com o <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> não está funcionando"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Toque para corrigir"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"O <xliff:g id="NAME">%s</xliff:g> está corrompido. Selecione para corrigir."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Pode ser necessário reformatar o dispositivo. Toque para ejetá-lo."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> não compatível"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> detectado"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> não está funcionando"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Este dispositivo não é compatível com esse <xliff:g id="NAME">%s</xliff:g>. Toque para configurar em um formato compatível."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Toque para configurar."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Selecione para configurar <xliff:g id="NAME">%s</xliff:g> em um formato compatível."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Pode ser necessário reformatar o dispositivo"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> foi removido inesperadamente"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Preferência de região"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Digitar nome do idioma"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Sugeridos"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Sugestões"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Todos os idiomas"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Todas as regiões"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Pesquisa"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Permitir que o app <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> acesse todos os registros do dispositivo?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Permitir o acesso único"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Não permitir"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Os registros do dispositivo gravam o que acontece nele. Os apps podem usar esses registros para encontrar e corrigir problemas.\n\nAlguns registros podem conter informações sensíveis, então autorize apenas os apps em que você confia a acessar os registros. \n\nSe você não permitir que esse app acesse todos os registros do dispositivo, ele ainda vai poder acessar os próprios. O fabricante do dispositivo também pode ter acesso a alguns registros ou informações. Saiba mais"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Os registros do dispositivo gravam o que acontece nele. Os apps podem usar esses registros para encontrar e corrigir problemas.\n\nAlguns registros podem conter informações sensíveis, então autorize o acesso a eles apenas para os apps em que você confia. \n\nSe você não permitir que esse app acesse todos os registros do dispositivo, ele ainda vai poder acessar os próprios. O fabricante do dispositivo também pode ter acesso a alguns registros ou informações."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Não mostrar novamente"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> quer mostrar partes do app <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Editar"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Verificar apps ativos"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Não é possível acessar a câmera do smartphone pelo <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Não é possível acessar a câmera do tablet pelo <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Não é possível acessar esse conteúdo durante o streaming. Tente pelo smartphone."</string>
<string name="system_locale_title" msgid="711882686834677268">"Padrão do sistema"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index aa21dcc..00d9aa2 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operação de impressão digital cancelada."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operação de impressão digital cancelada pelo utilizador."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Demasiadas tentativas. Tente novamente mais tarde."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Demasiadas tentativas. Sensor de impressões digitais desativado."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Tente novamente."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nenhuma impressão digital registada."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo não tem sensor de impressões digitais."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"A preparar o <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"A iniciar aplicações"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"A concluir o arranque."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Continuar a configuração?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Premiu o botão ligar/desligar. Geralmente, esta ação desliga o ecrã.\n\nExperimente tocar levemente ao configurar a sua impressão digital."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Desligar ecrã"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Continuar configur."</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toque para desligar o ecrã"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Desligar ecrã"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continuar a validar a impressão digital?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Premiu o botão ligar/desligar. Geralmente, esta ação desliga o ecrã.\n\nExperimente tocar levemente para validar a sua impressão digital."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Desligar ecrã"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Toque para configurar."</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Selecione para configurar"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Poderá ser necessário reformatar o dispositivo. Toque para o ejetar."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Transf. fotos, conteúdos multimédia."</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Para armazenar fotos, vídeos, música e muito mais"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Procure ficheiros multimédia"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Ocorreu um problema com o <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> não está a funcionar."</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Toque para corrigir."</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"O(a) <xliff:g id="NAME">%s</xliff:g> está danificado(a). Selecione para corrigir."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Poderá ser necessário reformatar o dispositivo. Toque para o ejetar."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> não suportado"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> detetado"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> não está a funcionar."</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Este dispositivo não é compatível com este <xliff:g id="NAME">%s</xliff:g>. Toque para o configurar num formato compatível."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Toque para configurar."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Selecione para configurar o(a) <xliff:g id="NAME">%s</xliff:g> num formato suportado."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Poderá ser necessário reformatar o dispositivo."</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> foi removido inesperadamente"</string>
@@ -1428,7 +1428,7 @@
<string name="ext_media_browse_action" msgid="344865351947079139">"Explorar"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Saída do interruptor"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> em falta"</string>
- <string name="ext_media_missing_message" msgid="4408988706227922909">"Volte a inserir o dispositivo."</string>
+ <string name="ext_media_missing_message" msgid="4408988706227922909">"Volte a inserir o dispositivo"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"A mover <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"A mover dados"</string>
<string name="ext_media_move_success_title" msgid="4901763082647316767">"Transf. de conteúdo concluída"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Preferência de região"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Intr. nome do idioma"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Sugeridos"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Sugeridas"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Todos os idiomas"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Todas as regiões"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Pesquisa"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Permitir que a app <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> aceda a todos os registos do dispositivo?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Permitir acesso único"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Não permitir"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Os registos do dispositivo documentam o que ocorre no seu dispositivo. As apps podem usar esses registos para detetar e corrigir problemas.\n\nAlguns registos podem conter informações confidenciais, pelo que o acesso a todos os registos do dispositivo deve apenas ser permitido às apps nas quais confia. \n\nSe não permitir o acesso desta app a todos os registos do dispositivo, a mesma pode ainda assim aceder aos próprios registos. O fabricante do dispositivo pode continuar a aceder a alguns registos ou informações no seu dispositivo. Saiba mais"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Os registos do dispositivo documentam o que ocorre no seu dispositivo. As apps podem usar esses registos para detetar e corrigir problemas.\n\nAlguns registos podem conter informações confidenciais e, por isso, o acesso a todos os registos do dispositivo deve apenas ser permitido às apps nas quais confia. \n\nSe não permitir o acesso desta app a todos os registos do dispositivo, esta pode ainda assim aceder aos próprios registos. O fabricante do dispositivo pode continuar a aceder a alguns registos ou informações no seu dispositivo."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Não mostrar de novo"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"A app <xliff:g id="APP_0">%1$s</xliff:g> pretende mostrar partes da app <xliff:g id="APP_2">%2$s</xliff:g>."</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Editar"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Verificar apps ativas"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Não é possível aceder à câmara do telemóvel a partir do dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Não é possível aceder à câmara do tablet a partir do dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Não é possível aceder a isto durante o streaming. Em alternativa, experimente no telemóvel."</string>
<string name="system_locale_title" msgid="711882686834677268">"Predefinição do sistema"</string>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 0dc380b7..cf57755 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operação de impressão digital cancelada."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operação de impressão digital cancelada pelo usuário."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Excesso de tentativas. Tente novamente mais tarde."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Excesso de tentativas. Sensor de impressão digital desativado."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Tente novamente."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nenhuma impressão digital registrada."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo não tem um sensor de impressão digital."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando apps."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Concluindo a inicialização."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Continuar a configuração?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Você pressionou o botão liga/desliga. Normalmente, essa ação desliga a tela.\n\nToque levemente na tela durante a configuração da impressão digital."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Desligar a tela"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Continuar configuração"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toque para desligar a tela"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Desligar a tela"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continuar a verificação da digital?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Você pressionou o botão liga/desliga. Normalmente, essa ação desliga a tela.\n\nToque levemente na tela para verificar sua impressão digital."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Desligar a tela"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Toque para configurar"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Selecione para configurar"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Pode ser necessário reformatar o dispositivo. Toque para ejetá-lo."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Para transferir fotos e mídia"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Para armazenamento de fotos, vídeos, músicas e muito mais"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Procure arquivos de mídia"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Ocorreu um problema com o <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> não está funcionando"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Toque para corrigir"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"O <xliff:g id="NAME">%s</xliff:g> está corrompido. Selecione para corrigir."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Pode ser necessário reformatar o dispositivo. Toque para ejetá-lo."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> não compatível"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> detectado"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> não está funcionando"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Este dispositivo não é compatível com esse <xliff:g id="NAME">%s</xliff:g>. Toque para configurar em um formato compatível."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Toque para configurar."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Selecione para configurar <xliff:g id="NAME">%s</xliff:g> em um formato compatível."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Pode ser necessário reformatar o dispositivo"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> foi removido inesperadamente"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Preferência de região"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Digitar nome do idioma"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Sugeridos"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Sugestões"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Todos os idiomas"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Todas as regiões"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Pesquisa"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Permitir que o app <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> acesse todos os registros do dispositivo?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Permitir o acesso único"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Não permitir"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Os registros do dispositivo gravam o que acontece nele. Os apps podem usar esses registros para encontrar e corrigir problemas.\n\nAlguns registros podem conter informações sensíveis, então autorize apenas os apps em que você confia a acessar os registros. \n\nSe você não permitir que esse app acesse todos os registros do dispositivo, ele ainda vai poder acessar os próprios. O fabricante do dispositivo também pode ter acesso a alguns registros ou informações. Saiba mais"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Os registros do dispositivo gravam o que acontece nele. Os apps podem usar esses registros para encontrar e corrigir problemas.\n\nAlguns registros podem conter informações sensíveis, então autorize o acesso a eles apenas para os apps em que você confia. \n\nSe você não permitir que esse app acesse todos os registros do dispositivo, ele ainda vai poder acessar os próprios. O fabricante do dispositivo também pode ter acesso a alguns registros ou informações."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Não mostrar novamente"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> quer mostrar partes do app <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Editar"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Verificar apps ativos"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Não é possível acessar a câmera do smartphone pelo <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Não é possível acessar a câmera do tablet pelo <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Não é possível acessar esse conteúdo durante o streaming. Tente pelo smartphone."</string>
<string name="system_locale_title" msgid="711882686834677268">"Padrão do sistema"</string>
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index ae161b6a..b4c2c32 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -609,7 +609,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operațiunea privind amprenta a fost anulată."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operațiunea privind amprenta a fost anulată de utilizator."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Prea multe încercări. Încercați din nou mai târziu."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Prea multe încercări. Senzorul de amprentă este dezactivat."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Încercați din nou."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nu au fost înregistrate amprente."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Dispozitivul nu are senzor de amprentă."</string>
@@ -968,7 +969,7 @@
<string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Pentru a debloca, conectați-vă folosind Contul Google."</string>
<string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"Nume de utilizator (e-mail)"</string>
<string name="lockscreen_glogin_password_hint" msgid="3031027901286812848">"Parolă"</string>
- <string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"Conectați-vă"</string>
+ <string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"Conectează-te"</string>
<string name="lockscreen_glogin_invalid_input" msgid="4369219936865697679">"Nume de utilizator sau parolă nevalide."</string>
<string name="lockscreen_glogin_account_recovery_hint" msgid="1683405808525090649">"Ați uitat numele de utilizator sau parola?\nAccesați "<b>"google.com/accounts/recovery"</b>"."</string>
<string name="lockscreen_glogin_checking_password" msgid="2607271802803381645">"Se verifică..."</string>
@@ -1250,10 +1251,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Se pregătește <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Se pornesc aplicațiile."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Se finalizează pornirea."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Continuați configurarea?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Ați apăsat butonul de pornire. De obicei, această acțiune dezactivează ecranul.\n\nAtingeți ușor când vă configurați amprenta."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Dezactivați ecranul"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Continuați configurarea"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Atinge pentru a dezactiva ecranul"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Dezactivează ecranul"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continuați cu verificarea amprentei?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Ați apăsat butonul de pornire. De obicei, această acțiune dezactivează ecranul.\n\nAtingeți ușor pentru verificarea amprentei."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Dezactivați ecranul"</string>
@@ -1368,7 +1368,7 @@
<string name="adb_active_notification_message" msgid="5617264033476778211">"Atingeți pentru a dezactiva."</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Selectați pentru a dezactiva remedierea erorilor prin USB."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Remedierea erorilor wireless este activă"</string>
- <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Atingeți pentru a dezactiva remedierea erorilor wireless"</string>
+ <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Atinge pentru a dezactiva remedierea erorilor wireless"</string>
<string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Selectați pentru a dezactiva remedierea erorilor wireless."</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Modul Set de testare este activat"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Reveniți la setările din fabrică pentru a dezactiva modul Set de testare."</string>
@@ -1406,16 +1406,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Atingeți pentru a configura"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Selectați pentru a configura"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Poate fi nevoie să reformatați dispozitivul. Atingeți pentru a-l scoate."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Pentru a transfera fotografii și fișiere media"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Pentru stocarea de fotografii, videoclipuri, muzică și altele"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Răsfoiți fișierele media"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problemă cu <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> nu funcționează"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Atingeți pentru a remedia"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> este corupt. Selectați pentru a remedia."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Poate fi nevoie să reformatați dispozitivul. Atingeți pentru a-l scoate."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> necompatibil"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"S-a detectat <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> nu funcționează"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Dispozitivul nu este compatibil cu acest <xliff:g id="NAME">%s</xliff:g>. Atingeți pentru configurare într-un format compatibil."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Atinge pentru a configura"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Selectați pentru a configura <xliff:g id="NAME">%s</xliff:g> într-un format acceptat."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Poate fi nevoie să reformatați dispozitivul"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> scos pe neașteptate"</string>
@@ -1657,7 +1657,7 @@
<string name="kg_login_instructions" msgid="3619844310339066827">"Pentru a debloca, conectați-vă cu Contul dvs. Google."</string>
<string name="kg_login_username_hint" msgid="1765453775467133251">"Nume de utilizator (e-mail)"</string>
<string name="kg_login_password_hint" msgid="3330530727273164402">"Parolă"</string>
- <string name="kg_login_submit_button" msgid="893611277617096870">"Conectați-vă"</string>
+ <string name="kg_login_submit_button" msgid="893611277617096870">"Conectează-te"</string>
<string name="kg_login_invalid_input" msgid="8292367491901220210">"Nume de utilizator sau parolă nevalide."</string>
<string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"Ați uitat numele de utilizator sau parola?\nAccesați "<b>"google.com/accounts/recovery"</b>"."</string>
<string name="kg_login_checking_password" msgid="4676010303243317253">"Se verifică contul…"</string>
@@ -1928,6 +1928,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Regiunea preferată"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Numele limbii"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Sugerate"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Sugerate"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Toate limbile"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Toate regiunile"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Căutați"</string>
@@ -2050,7 +2051,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Permiteți ca <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> să acceseze toate jurnalele dispozitivului?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Permiteți accesul o dată"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Nu permiteți"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Jurnalele dispozitivului înregistrează activitatea de pe dispozitivul dvs. Aplicațiile pot folosi aceste jurnale pentru a identifica și a remedia probleme.\n\nUnele jurnale pot să conțină informații sensibile, prin urmare permiteți accesul la toate jurnalele dispozitivului doar aplicațiilor în care aveți încredere. \n\nDacă nu permiteți accesul aplicației la toate jurnalele dispozitivului, aceasta poate în continuare să acceseze propriile jurnale. Este posibil ca producătorul dispozitivului să acceseze în continuare unele jurnale sau informații de pe dispozitiv. Aflați mai multe"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Jurnalele dispozitivului înregistrează activitatea de pe dispozitivul tău. Aplicațiile pot folosi aceste jurnale pentru a identifica și a remedia probleme.\n\nUnele jurnale pot să conțină informații sensibile, prin urmare permite accesul la toate jurnalele dispozitivului doar aplicațiilor în care ai încredere. \n\nDacă nu permiți accesul aplicației la toate jurnalele dispozitivului, aceasta poate în continuare să acceseze propriile jurnale. Este posibil ca producătorul dispozitivului să acceseze în continuare unele jurnale sau informații de pe dispozitiv."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Nu mai afișa"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> vrea să afișeze porțiuni din <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Editați"</string>
@@ -2291,5 +2292,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Verificați aplicațiile active"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nu se poate accesa camera foto a telefonului de pe <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Nu se poate accesa camera foto a tabletei de pe <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Nu se poate accesa în timpul streamingului. Încearcă pe telefon."</string>
<string name="system_locale_title" msgid="711882686834677268">"Prestabilit de sistem"</string>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 195074c..290fba7 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -610,7 +610,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Операция с отпечатком отменена."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Операция с отпечатком пальца отменена пользователем."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Слишком много попыток. Повторите позже."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Слишком много попыток. Сканер отпечатков пальцев отключен."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Повторите попытку."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Нет отсканированных отпечатков пальцев"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"На этом устройстве нет сканера отпечатков пальцев."</string>
@@ -1251,10 +1252,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Подготовка приложения \"<xliff:g id="APPNAME">%1$s</xliff:g>\"..."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Запуск приложений."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Окончание загрузки..."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Продолжить настройку?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Вы нажали кнопку питания. Обычно это приводит к отключению экрана.\n\nПри добавлении отпечатка пальца слегка прикоснитесь к кнопке."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Отключить экран"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Продолжить настройку"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Нажмите, чтобы отключить экран"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Отключить экран"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Продолжить сканирование отпечатка?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Вы нажали кнопку питания. Обычно это приводит к отключению экрана.\n\nЧтобы отсканировать отпечаток пальца, слегка прикоснитесь к кнопке."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Отключить экран"</string>
@@ -1407,16 +1407,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Нажмите, чтобы настроить."</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Выберите, чтобы настроить."</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Возможно, потребуется отформатировать устройство. Нажмите, чтобы извлечь его."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Для переноса фотографий и других файлов"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Хранение фото, видео, музыки и не только."</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Посмотрите медиафайлы."</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Проблема с накопителем (<xliff:g id="NAME">%s</xliff:g>)"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> не работает"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Нажмите здесь, чтобы исправить."</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Внешний носитель (<xliff:g id="NAME">%s</xliff:g>) поврежден. Выберите, чтобы исправить."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Возможно, потребуется отформатировать устройство. Нажмите, чтобы извлечь его."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> не поддерживается"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Обнаружено: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> не работает"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Устройство не поддерживает этот носитель (<xliff:g id="NAME">%s</xliff:g>). Нажмите, чтобы настроить."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Нажмите, чтобы настроить."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Выберите, чтобы настроить носитель (<xliff:g id="NAME">%s</xliff:g>) в поддерживаемом формате."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Возможно, потребуется отформатировать устройство."</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Карта \"<xliff:g id="NAME">%s</xliff:g>\" извлечена неправильно"</string>
@@ -1429,7 +1429,7 @@
<string name="ext_media_unmount_action" msgid="966992232088442745">"Извлечь"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"Обзор"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Сменить устройство вывода"</string>
- <string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> не найден"</string>
+ <string name="ext_media_missing_title" msgid="3209472091220515046">"Устройство \"<xliff:g id="NAME">%s</xliff:g>\" не найдено"</string>
<string name="ext_media_missing_message" msgid="4408988706227922909">"Подключите накопитель снова."</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"Перенос приложения <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"Перенос данных"</string>
@@ -1929,6 +1929,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Региональные настройки"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Введите название языка"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Рекомендуемые"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Доступные регионы"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Все языки"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Все регионы"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Поиск"</string>
@@ -2051,7 +2052,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Разрешить приложению \"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>\" доступ ко всем журналам устройства?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Разрешить разовый доступ"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Запретить"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"В журналы записывается информация о том, что происходит на устройстве. Приложения могут использовать их, чтобы находить и устранять неполадки.\n\nТак как некоторые журналы могут содержать конфиденциальную информацию, доступ ко всем журналам следует предоставлять только тем приложениям, которым вы доверяете. \n\nЕсли вы не предоставите такой доступ этому приложению, оно по-прежнему сможет просматривать свои журналы. Не исключено, что некоторые журналы или сведения на вашем устройстве будут по-прежнему доступны его производителю. Подробнее"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"В журналы записывается информация о том, что происходит на устройстве. Приложения могут использовать их, чтобы находить и устранять неполадки.\n\nТак как некоторые журналы могут содержать конфиденциальную информацию, доступ ко всем журналам следует предоставлять только тем приложениям, которым вы доверяете. \n\nЕсли вы не предоставите такой доступ этому приложению, оно по-прежнему сможет просматривать свои журналы. Не исключено, что некоторые журналы или сведения на вашем устройстве будут по-прежнему доступны его производителю."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Больше не показывать"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Приложение \"<xliff:g id="APP_0">%1$s</xliff:g>\" запрашивает разрешение на показ фрагментов приложения \"<xliff:g id="APP_2">%2$s</xliff:g>\"."</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Изменить"</string>
@@ -2292,5 +2293,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Проверить активные приложения"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"У устройства \"<xliff:g id="DEVICE">%1$s</xliff:g>\" нет доступа к камере телефона."</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"У устройства \"<xliff:g id="DEVICE">%1$s</xliff:g>\" нет доступа к камере планшета."</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Этот контент недоступен во время трансляции. Используйте телефон."</string>
<string name="system_locale_title" msgid="711882686834677268">"Системные настройки по умолчанию"</string>
</resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index a513aca..9bbdebe 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ඇඟිලි සලකුණු මෙහෙයුම අවලංගු කරන ලදී."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"පරිශීලක විසින් ඇඟිලි සලකුණු මෙහෙයුම අවසන් කරන ලදී."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"උත්සාහයන් ඉතා වැඩි ගණනකි. කරුණාකර පසුව නැවත උත්සාහ කරන්න."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"උත්සාහයන් ඉතා වැඩි ගණනකි. ඇඟිලි සලකුණු සංවේදකය අබල කරන ලදී."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"නැවත උත්සාහ කරන්න."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ඇඟිලි සලකුණු ඇතුළත් කර නොමැත."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"මෙම උපාංගයේ ඇඟිලි සලකුණු සංවේදකයක් නොමැත."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> සූදානම් කරමින්."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"යෙදුම් ආරම්භ කරමින්."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"ඇරඹුම අවසාන කරමින්."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"පිහිටුවීම දිගටම කරන්නද?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ඔබ බල බොත්තම එබුවේය — සාමාන්යයෙන් මෙය තිරය ක්රියාවිරහිත කරයි.\n\nඔබගේ ඇඟිලි සලකුණ පිහිටුවන අතරතුර සැහැල්ලුවෙන් තට්ටු කිරීමට උත්සාහ කරන්න."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"තිරය අක්රිය කරන්න"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"පිහිටුවීම දිගටම කර."</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"තිරය අක්රිය කිරීමට තට්ටු කරන්න"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"තිරය අක්රිය කරන්න"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"ඔබගේ ඇඟිලි සලකුණ සත්යාපනය දිගටම කරන්නද?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"ඔබ බල බොත්තම එබුවේය — සාමාන්යයෙන් මෙය තිරය ක්රියාවිරහිත කරයි.\n\nඔබගේ ඇඟිලි සලකුණ සත්යාපනය කිරීමට සැහැල්ලුවෙන් තට්ටු කිරීමට උත්සාහ කරන්න."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"තිරය අක්රිය කරන්න"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"පිහිටුවීමට තට්ටු කරන්න"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"පිහිටුවීමට තෝරන්න"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"ඔබට උපාංගය නැවත හැඩගැන්වීමට අවශ්ය විය හැකිය. ඉවත් කිරීමට තට්ටු කරන්න."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ඡායාරූප සහ මාධ්ය හුවමාරු කිරීම සඳහා"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ඡායාරූප, වීඩියෝ, සංගීතය සහ තවත් දේ ගබඩා කිරීම සඳහා"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"මාධ්ය ගොනු බ්රවුස් කරන්න"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> සමගින් වන ගැටලුව"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ක්රියා නොකරයි"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"විසඳීමට තට්ටු කරන්න"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> දූෂිතයි. විසඳීමට තට්ටු කරන්න."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"ඔබට උපාංගය නැවත හැඩගැන්වීමට අවශ්ය විය හැකිය. ඉවත් කිරීමට තට්ටු කරන්න."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"සහාය නොදක්වන <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> අනාවරණය කර ඇත"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ක්රියා නොකරයි"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"මෙම උපාංගය මෙම <xliff:g id="NAME">%s</xliff:g> සඳහා සහාය නොදක්වයි. සහාය දක්වන ආකෘතියකින් පිහිටුවීමට තට්ටු කරන්න."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"පිහිටුවීමට තට්ටු කරන්න ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"සහාය දක්වන ආකෘතියකින් <xliff:g id="NAME">%s</xliff:g> පිහිටුවීමට තෝරන්න."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"ඔබට උපාංගය නැවත හැඩගැන්වීමට අවශ්ය විය හැකිය"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> අනපේක්ෂිතව ඉවත් කරන ලදි"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"ප්රදේශ මනාපය"</string>
<string name="search_language_hint" msgid="7004225294308793583">"භාෂා නම ටයිප් කරන්න"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"යෝජිත"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"යෝජිත"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"සියලු භාෂා"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"සියලු ප්රදේශ"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"සෙවීම"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> හට සියලු උපාංග ලොග ප්රවේශ වීමට ඉඩ දෙන්නද?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"එක් වරක් ප්රවේශය ඉඩ දෙන්න"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"ඉඩ නොදෙන්න"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"උපාංග ලොග ඔබගේ උපාංගයේ සිදු වන දේ වාර්තා කරයි. ගැටලු සොයා ගැනීමට සහ විසඳීමට යෙදුම්වලට මෙම ලොග භාවිත කළ හැකිය.\n\nසමහර ලොගවල සංවේදී තොරතුරු අඩංගු විය හැකිය, එබැවින් ඔබ විශ්වාස කරන යෙදුම්වලට පමණක් සියලු උපාංග ලොග වෙත ප්රවේශ වීමට ඉඩ දෙන්න. \n\nඔබ මෙම යෙදුමට සියලු උපාංග ලොග වෙත ප්රවේශ වීමට ඉඩ නොදෙන්නේ නම්, එයට තවමත් එහිම ලොග වෙත ප්රවේශ විය හැකිය. ඔබගේ උපාංග නිෂ්පාදකයාට තවමත් ඔබගේ උපාංගයේ සමහර ලොග හෝ තොරතුරු වෙත ප්රවේශ විය හැකිය. තව දැන ගන්න"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"උපාංග ලොග ඔබේ උපාංගයෙහි සිදු වන දේ වාර්තා කරයි. ගැටලු සොයා ගැනීමට සහ නිරාකරණයට යෙදුම්වලට මෙම ලොග භාවිතා කළ හැක.\n\nසමහර ලොගවල සංවේදී තතු අඩංගු විය හැකි බැවින්, ඔබ විශ්වාස කරන යෙදුම්වලට පමණක් සියලු උපාංග ලොග වෙත ප්රවේශ වීමට ඉඩ දෙන්න. \n\nඔබ මෙම යෙදුමට සියලු උපාංග ලොග වෙත ප්රවේශ වීමට ඉඩ නොදෙන්නේ නම්, එයට තවමත් එහිම ලොග වෙත ප්රවේශ විය හැක. ඔබේ උපාංග නිෂ්පාදකයාට තවමත් ඔබේ උපාංගයෙහි සමහර ලොග හෝ තතු වෙත ප්රවේශ විය හැක."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"නැවත නොපෙන්වන්න"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> හට කොටස් <xliff:g id="APP_2">%2$s</xliff:g>ක් පෙන්වීමට අවශ්යයි"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"සංස්කරණය"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"සක්රිය යෙදුම් පරීක්ෂා කරන්න"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"ඔබගේ <xliff:g id="DEVICE">%1$s</xliff:g> වෙතින් දුරකථනයේ කැමරාවට ප්රවේශ විය නොහැකිය"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"ඔබගේ <xliff:g id="DEVICE">%1$s</xliff:g> වෙතින් ටැබ්ලටයේ කැමරාවට ප්රවේශ විය නොහැකිය"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"ප්රවාහය කරන අතරේ මෙයට ප්රවේශ විය නොහැක. ඒ වෙනුවට ඔබේ දුරකථනයෙහි උත්සාහ කරන්න."</string>
<string name="system_locale_title" msgid="711882686834677268">"පද්ධති පෙරනිමිය"</string>
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 665dd02..aaaf573 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -610,7 +610,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Overenie odtlačku prsta zrušil používateľ."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Príliš veľa pokusov. Skúste to neskôr."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Príliš veľa pokusov. Senzor odtlačkov prstov bol deaktivovaný."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Skúste to znova"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Neregistrovali ste žiadne odtlačky prstov."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Toto zariadenie nemá senzor odtlačkov prstov."</string>
@@ -1251,10 +1252,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Pripravuje sa aplikácia <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Prebieha spúšťanie aplikácií."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Prebieha dokončovanie spúšťania."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Chcete pokračovať v nastavovaní?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Stlačili ste vypínač. Obvykle tým vypnete obrazovku.\n\nPri nastavovaní odtlačku prsta skúste klepnúť jemne."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Vypnúť obrazovku"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Pokračovať v nastav."</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Klepnutím vypnite obrazovku"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Vypnúť obrazovku"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Pokračovať v overovaní odtlačku prsta?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Stlačili ste vypínač. Obvykle tým vypnete obrazovku.\n\nAk chcete overiť odtlačok prsta, skúste klepnúť jemne."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Vypnúť obrazovku"</string>
@@ -1407,16 +1407,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Klepnutím médium nastavte"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Vyberte a nastavte"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Zariadenie možno bude potrebné preformátovať. Klepnutím ho vysuniete."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Na prenos fotiek a médií"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Na ukladanie fotiek, vdieí, hudby a ďalšieho obsahu"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Prehliadajte súbory médií"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problém s médiom <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> nefunguje"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Problém odstránite klepnutím"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Médium <xliff:g id="NAME">%s</xliff:g> je poškodené. Vyberte ho a vyriešte problém."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Zariadenie možno bude potrebné preformátovať. Klepnutím ho vysuniete."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Nepodporované úložisko <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Bolo rozpoznané médium <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> nefunguje"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Toto zariadenie nepodporuje úložisko <xliff:g id="NAME">%s</xliff:g>. Klepnutím ho nastavíte v podporovanom formáte."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Nastavte klepnutím."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Vyberte a vytvorte tak <xliff:g id="NAME">%s</xliff:g> v podporovanom formáte."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Zariadenie možno bude potrebné preformátovať"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Úl. <xliff:g id="NAME">%s</xliff:g> bolo neočakávane odobraté"</string>
@@ -1929,6 +1929,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Preferovaný región"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Zadajte názov jazyka"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Navrhované"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Navrhované"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Všetky jazyky"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Všetky oblasti"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Vyhľadávanie"</string>
@@ -2051,7 +2052,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Chcete povoliť aplikácii <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> prístup k všetkým denníkom zariadenia?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Povoliť jednorazový prístup"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Nepovoliť"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Denníky zariadenia zaznamenávajú, čo sa deje vo vašom zariadení. Aplikácie môžu pomocou týchto denníkov vyhľadávať a riešiť problémy.\n\nNiektoré denníky môžu obsahovať citlivé údaje, preto povoľte prístup k všetkým denníkom zariadenia iba dôveryhodným aplikáciám. \n\nAk tejto aplikácii nepovolíte prístup k všetkým denníkom zariadenia, stále bude mať prístup k vlastným denníkom. Výrobca vášho zariadenia bude mať naďalej prístup k niektorým denníkom alebo informáciám vo vašom zariadení. Ďalšie informácie"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Denníky zariadenia zaznamenávajú, čo sa deje vo vašom zariadení. Aplikácie môžu pomocou týchto denníkov vyhľadávať a riešiť problémy.\n\nNiektoré denníky môžu obsahovať citlivé údaje, preto povoľte prístup k všetkým denníkom zariadenia iba dôveryhodným aplikáciám. \n\nAk tejto aplikácii nepovolíte prístup k všetkým denníkom zariadenia, stále bude mať prístup k vlastným denníkom. Výrobca vášho zariadenia bude mať naďalej prístup k niektorým denníkom alebo informáciám vo vašom zariadení."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Už nezobrazovať"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> chce zobrazovať rezy z aplikácie <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Upraviť"</string>
@@ -2274,7 +2275,7 @@
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Zapnúť v Nastaveniach"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Zavrieť"</string>
<string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Odblokujte mikrofón zariadenia"</string>
- <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"Odblokujte fotoaparát zariadenia"</string>
+ <string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"Odblokujte kameru zariadenia"</string>
<string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"Pre aplikáciu <b><xliff:g id="APP">%s</xliff:g></b> a všetky aplikácie a služby"</string>
<string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"Odblokovať"</string>
<string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Ochrana súkromia senzorov"</string>
@@ -2292,5 +2293,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Skontrolovať aktívne aplikácie"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"V zariadení <xliff:g id="DEVICE">%1$s</xliff:g> nemáte prístup ku kamere telefónu"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"V zariadení <xliff:g id="DEVICE">%1$s</xliff:g> nemáte prístup ku kamere tabletu"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"K tomuto obsahu nie je počas streamovania prístup. Skúste namiesto toho použiť telefón."</string>
<string name="system_locale_title" msgid="711882686834677268">"Predvolené systémom"</string>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index fa4f2a3a1..c0f0b0d 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -610,7 +610,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Dejanje s prstnim odtisom je bilo preklicano."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Dejanje s prstnim odtisom je preklical uporabnik."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Preveč poskusov. Poskusite znova pozneje."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Preveč poskusov. Tipalo prstnih odtisov je onemogočeno."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Poskusite znova."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Ni registriranih prstnih odtisov."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ta naprava nima tipala prstnih odtisov."</string>
@@ -1251,10 +1252,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Pripravljanje aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Zagon aplikacij."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Dokončevanje zagona."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Ali želite nadaljevati nastavitev?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Pritisnili ste gumb za vklop, s čimer običajno izklopite zaslon.\n\nPoskusite se narahlo dotakniti med nastavljanjem prstnega odtisa."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Izklopi zaslon"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Nadaljuj nastavitev"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Dotaknite se za izklop zaslona"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Izklopi zaslon"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Želite nadaljevati preverjanje prstnega odtisa?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Pritisnili ste gumb za vklop, s čimer običajno izklopite zaslon.\n\nZa preverjanje prstnega odtisa se poskusite narahlo dotakniti."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Izklopi zaslon"</string>
@@ -1407,16 +1407,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Dotaknite se, če želite nastaviti"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Izberite, če želite nastaviti."</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Napravo boste morda morali znova formatirati. Če jo želite izvreči, se dotaknite."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Za prenos fotografij in predstavnosti"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Za shranjevanje fotografij, videoposnetkov, glasbe in druge vsebine."</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Brskajte po predstavnostnih datotekah."</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Težava z nosilcem <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"Naprava <xliff:g id="NAME">%s</xliff:g> ne deluje"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Dotaknite se, da to popravite"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Nosilec <xliff:g id="NAME">%s</xliff:g> je pokvarjen. Izberite, če ga želite popraviti."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Napravo boste morda morali znova formatirati. Če jo želite izvreči, se dotaknite."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Nepodprta naprava za shran. <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Zaznana je bila naprava <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"Naprava <xliff:g id="NAME">%s</xliff:g> ne deluje"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Ta naprava ne podpira tega nosilca <xliff:g id="NAME">%s</xliff:g>. Dotaknite se, če želite nastaviti v podprti obliki."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Dotaknite se za nastavitev."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Izberite, da nastavite »<xliff:g id="NAME">%s</xliff:g>« v podprti obliki."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Napravo boste morda morali znova formatirati"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Shramba <xliff:g id="NAME">%s</xliff:g> nepričak. odstranjena"</string>
@@ -1929,6 +1929,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Nastavitev območja"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Vnesite ime jezika"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Predlagano"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Predlagano"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Vsi jeziki"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Vse regije"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Išči"</string>
@@ -2051,7 +2052,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Ali aplikaciji <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> dovolite dostop do vseh dnevnikov naprave?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Dovoli enkratni dostop"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Ne dovoli"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"V dnevnikih naprave se beleži dogajanje v napravi. Aplikacije lahko te dnevnike uporabijo za iskanje in odpravljanje težav.\n\nNekateri dnevniki morda vsebujejo občutljive podatke, zato dostop do vseh dnevnikov naprave omogočite le aplikacijam, ki jim zaupate. \n\nČe tej aplikaciji ne dovolite dostopa do vseh dnevnikov naprave, bo aplikacija kljub temu lahko dostopala do svojih dnevnikov. Proizvajalec naprave bo morda lahko kljub temu dostopal do nekaterih dnevnikov ali podatkov v napravi. Več o tem"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"V dnevnikih naprave se beleži dogajanje v napravi. Aplikacije lahko te dnevnike uporabijo za iskanje in odpravljanje težav.\n\nNekateri dnevniki morda vsebujejo občutljive podatke, zato dostop do vseh dnevnikov naprave omogočite le aplikacijam, ki jim zaupate. \n\nČe tej aplikaciji ne dovolite dostopa do vseh dnevnikov naprave, bo aplikacija kljub temu lahko dostopala do svojih dnevnikov. Proizvajalec naprave bo morda lahko kljub temu dostopal do nekaterih dnevnikov ali podatkov v napravi."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ne prikaži več"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Aplikacija <xliff:g id="APP_0">%1$s</xliff:g> želi prikazati izreze aplikacije <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Uredi"</string>
@@ -2292,5 +2293,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Preverite aktivne aplikacije"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Ni mogoče dostopati do fotoaparata telefona prek naprave <xliff:g id="DEVICE">%1$s</xliff:g>."</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Ni mogoče dostopati do fotoaparata tabličnega računalnika prek naprave <xliff:g id="DEVICE">%1$s</xliff:g>."</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Do te vsebine ni mogoče dostopati med pretočnim predvajanjem. Poskusite s telefonom."</string>
<string name="system_locale_title" msgid="711882686834677268">"Sistemsko privzeto"</string>
</resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 744d7be..68380bc 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operacioni i gjurmës së gishtit u anulua."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Veprimi i gjurmës së gishtit u anulua nga përdoruesi."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Keni bërë shumë tentativa. Provo përsëri më vonë."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Shumë përpjekje. Sensori i gjurmës së gishtit u çaktivizua."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Provo përsëri."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nuk ka asnjë gjurmë gishti të regjistruar."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Kjo pajisje nuk ka sensor të gjurmës së gishtit."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Po përgatit <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Aplikacionet e fillimit."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Po përfundon nisjen."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Të vazhdohet konfigurimi?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Shtype butonin e energjisë — zakonisht, kjo e fik ekranin.\n\nProvo të trokasësh lehtë ndërkohë që konfiguron gjurmën e gishtit."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Fik ekranin"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Vazhdo konfigurimin"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Trokit për ta fikur ekranin"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Fik ekranin"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Të vazhdohet verifikimi i gjurmës?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Shtype butonin e energjisë — zakonisht, kjo e fik ekranin.\n\nProvo të trokasësh lehtë për të verifikuar gjurmën e gishtit."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Fik ekranin"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Trokit për ta konfiguruar"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Zgjidhe për ta konfiguruar"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Mund të jetë nevoja ta riformatosh pajisjen. Trokit për ta nxjerrë."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Për transferimin e fotografive dhe skedarëve të tjerë"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Për ruajtjen e fotografive, videove, muzikës etj."</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Shfleto skedarët e medias"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problem me <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> nuk punon"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Trokit për ta rregulluar"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> është dëmtuar. Zgjidh për ta rregulluar."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Mund të jetë nevoja ta riformatosh pajisjen. Trokit për ta nxjerrë."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> nuk mbështetet"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"U zbulua <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> nuk punon"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Kjo pajisje nuk e mbështet këtë <xliff:g id="NAME">%s</xliff:g>. Trokit për ta konfiguruar në një format të mbështetur."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Trokit për të konfiguruar"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Zgjidh të konfigurosh <xliff:g id="NAME">%s</xliff:g> në një format të mbështetur."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Mund të jetë nevoja ta riformatosh pajisjen"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> u hoq papritur"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Preferenca e rajonit"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Shkruaj emrin e gjuhës"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Sugjeruar"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Të sugjeruara"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Të gjitha gjuhët"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Të gjitha rajonet"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Kërko"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Të lejohet që <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> të ketë qasje te të gjitha evidencat e pajisjes?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Lejo qasjen vetëm për një herë"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Mos lejo"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Evidencat e pajisjes regjistrojnë çfarë ndodh në pajisjen tënde. Aplikacionet mund t\'i përdorin këto evidenca për të gjetur dhe rregulluar problemet.\n\nDisa evidenca mund të përmbajnë informacione delikate, ndaj lejo vetëm aplikacionet që u beson të kenë qasje te të gjitha evidencat e pajisjes. \n\nNëse nuk e lejon këtë aplikacion që të ketë qasje tek të gjitha evidencat e pajisjes, ai mund të vazhdojë të ketë qasje tek evidencat e tij. Prodhuesi i pajisjes sate mund të jetë ende në gjendje që të ketë qasje te disa evidenca ose informacione në pajisjen tënde. Mëso më shumë"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Evidencat e pajisjes regjistrojnë çfarë ndodh në pajisjen tënde. Aplikacionet mund t\'i përdorin këto evidenca për të gjetur dhe rregulluar problemet.\n\nDisa evidenca mund të përmbajnë informacione delikate, ndaj lejo vetëm aplikacionet që u beson të kenë qasje te të gjitha evidencat e pajisjes. \n\nNëse nuk e lejon këtë aplikacion që të ketë qasje te të gjitha evidencat e pajisjes, ai mund të vazhdojë të ketë qasje tek evidencat e tij. Prodhuesi i pajisjes sate mund të jetë ende në gjendje që të ketë qasje te disa evidenca ose informacione në pajisjen tënde."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Mos e shfaq më"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> dëshiron të shfaqë pjesë të <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Modifiko"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Kontrollo aplikacionet aktive"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nuk mund të qasesh në kamerën e telefonit tënd nga <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Nuk mund të qasesh në kamerën e tabletit tënd nga <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Nuk mund të kesh qasje në të gjatë transmetimit. Provoje në telefon më mirë."</string>
<string name="system_locale_title" msgid="711882686834677268">"Parazgjedhja e sistemit"</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index faea736..368bf1e 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -609,7 +609,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Радња са отиском прста је отказана."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Корисник је отказао радњу са отиском прста."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Превише покушаја. Пробајте поново касније."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Превише покушаја. Сензор за отисак прста је онемогућен."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Пробајте поново."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Није регистрован ниједан отисак прста."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Овај уређај нема сензор за отисак прста."</string>
@@ -1250,10 +1251,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Припрема се <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Покретање апликација."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Завршавање покретања."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Желите ли да наставите са подешавањем?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Притиснули сте дугме за укључивање – тиме обично искључујете екран.\n\nПробајте лагано да додирнете док подешавате отисак прста."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Искључи екран"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Настави подешавање"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Додирните да бисте искључили екран"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Искључи екран"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Настављате верификацију отиска прста?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Притиснули сте дугме за укључивање – тиме обично искључујете екран.\n\nПробајте лагано да додирнете да бисте верификовали отисак прста."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Искључи екран"</string>
@@ -1406,16 +1406,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Додирните да бисте подесили"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Изаберите да бисте подесили"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Можда морате да реформатирате уређај. Додирните да бисте избацили."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"За пренос слика и медија"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"За чување слика, видео снимака, музике и другог садржаја"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Прегледајте медијске фајлове"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Проблем са: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> не ради"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Додирните да бисте исправили"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Медиј <xliff:g id="NAME">%s</xliff:g> је оштећен. Изаберите да га поправите."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Можда морате да реформатирате уређај. Додирните да бисте избацили."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Уређај <xliff:g id="NAME">%s</xliff:g> није подржан"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Откривенo: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> не ради"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Овај уређај не подржава овај уређај <xliff:g id="NAME">%s</xliff:g>. Додирните да бисте подесили подржани формат."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Додирните да бисте подесили."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Изаберите да бисте подесили уређај <xliff:g id="NAME">%s</xliff:g> у подржаном формату."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Можда морате да реформатирате уређај"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Уређај <xliff:g id="NAME">%s</xliff:g> је неочекивано уклоњен"</string>
@@ -1928,6 +1928,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Подешавање региона"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Унесите назив језика"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Предложени"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Предложено"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Сви језици"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Сви региони"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Претражи"</string>
@@ -2050,7 +2051,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Желите да дозволите апликацији <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> да приступа свим евиденцијама уређаја?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Дозволи једнократан приступ"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Не дозволи"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Евиденције уређаја региструју шта се дешава на уређају. Апликације могу да користе те евиденције да би пронашле и решиле проблеме.\n\nНеке евиденције могу да садрже осетљиве информације, па приступ свим евиденцијама уређаја треба да дозвољавате само апликацијама у које имате поверења. \n\nАко не дозволите овој апликацији да приступа свим евиденцијама уређаја, она и даље може да приступа сопственим евиденцијама. Произвођач уређаја ће можда и даље моћи да приступа неким евиденцијама или информацијама на уређају. Сазнајте више"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Евиденције уређаја региструју шта се дешава на уређају. Апликације могу да користе те евиденције да би пронашле и решиле проблеме.\n\nНеке евиденције могу да садрже осетљиве информације, па приступ свим евиденцијама уређаја треба да дозвољавате само апликацијама у које имате поверења. \n\nАко не дозволите овој апликацији да приступа свим евиденцијама уређаја, она и даље може да приступа сопственим евиденцијама. Произвођач уређаја ће можда и даље моћи да приступа неким евиденцијама или информацијама на уређају."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Не приказуј поново"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Апликација <xliff:g id="APP_0">%1$s</xliff:g> жели да приказује исечке из апликације <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Измени"</string>
@@ -2291,5 +2292,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Проверите активне апликације"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Не може да се приступи камери телефона са <xliff:g id="DEVICE">%1$s</xliff:g> уређаја"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Не може да се приступи камери таблета са <xliff:g id="DEVICE">%1$s</xliff:g> уређаја"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Овом не можете да приступате током стримовања. Пробајте на телефону."</string>
<string name="system_locale_title" msgid="711882686834677268">"Подразумевани системски"</string>
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index f899929..7a90fed 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -242,7 +242,7 @@
<string name="global_actions" product="default" msgid="6410072189971495460">"Telefonalternativ"</string>
<string name="global_action_lock" msgid="6949357274257655383">"Skärmlås"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"Stäng av"</string>
- <string name="global_action_power_options" msgid="1185286119330160073">"Strömbrytare"</string>
+ <string name="global_action_power_options" msgid="1185286119330160073">"Av/på"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Starta om"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"Nödsituation"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Felrapport"</string>
@@ -608,13 +608,14 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingeravtrycksåtgärden avbröts."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingeravtrycksåtgärden avbröts av användaren."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Du har gjort för många försök. Försök igen senare."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Du har försökt för många gånger. Fingeravtryckssensorn har inaktiverats."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Försök igen."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Inga fingeravtryck har registrerats."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Enheten har ingen fingeravtryckssensor."</string>
<string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensorn har tillfälligt inaktiverats."</string>
<string name="fingerprint_error_bad_calibration" msgid="4385512597740168120">"Det går inte att använda fingeravtryckssensorn. Besök ett reparationsställe"</string>
- <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Strömbrytaren nedtryckt"</string>
+ <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Av/på-knappen nedtryckt"</string>
<string name="fingerprint_name_template" msgid="8941662088160289778">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Använd ditt fingeravtryck"</string>
<string name="fingerprint_or_screen_lock_app_setting_name" msgid="3501743523487644907">"Använd ditt fingeravtryck eller skärmlåset"</string>
@@ -1249,12 +1250,11 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> förbereds."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Appar startas."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Uppgraderingen är klar."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Vill du fortsätta med konfigureringen?"</string>
- <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Du tryckte på strömbrytaren, vilket vanligtvis stänger av skärmen.\n\nTesta att trycka lätt när du konfigurerar fingeravtrycket."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Stäng av skärmen"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Fortsätt konfigurera"</string>
+ <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Du tryckte på av/på-knappen, vilket vanligtvis stänger av skärmen.\n\nTesta att trycka lätt när du konfigurerar fingeravtrycket."</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tryck för att stänga av skärmen"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Stäng av skärmen"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Vill du verifiera ditt fingeravtryck?"</string>
- <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Du tryckte på strömbrytaren, vilket vanligtvis stänger av skärmen.\n\nTesta att trycka lätt för att verifiera ditt fingeravtryck."</string>
+ <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Du tryckte på av/på-knappen, vilket vanligtvis stänger av skärmen.\n\nTesta att trycka lätt för att verifiera ditt fingeravtryck."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Stäng av skärmen"</string>
<string name="fp_power_button_bp_negative_button" msgid="3971364246496775178">"Fortsätt"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> körs"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Tryck för att konfigurera"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Välj för att konfigurera"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Du måste eventuellt formatera om enheten. Tryck för att mata ut."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"För överföring av foton och media"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"För lagring av foton, videor, musik och mer"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Bläddra bland mediefiler"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problem med <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> fungerar inte"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Tryck och åtgärda"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> har skadats. Välj för att åtgärda."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Du måste eventuellt formatera om enheten. Tryck för att mata ut."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> stöds inte"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> identifierades"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> fungerar inte"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Enheten har inte stöd för <xliff:g id="NAME">%s</xliff:g>. Tryck här om du vill konfigurera i ett format som stöds."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Tryck för att konfigurera."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Välj för att konfigurera <xliff:g id="NAME">%s</xliff:g> i ett format som stöds."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Du måste eventuellt formatera om enheten"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> togs bort oväntat"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Regionsinställningar"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Ange språk"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Förslag"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Förslag"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Alla språk"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Alla regioner"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Sök"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Vill du tillåta att <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> får åtkomst till alla enhetsloggar?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Tillåt engångsåtkomst"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Tillåt inte"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"I enhetsloggar registreras vad som händer på enheten. Appar kan använda dessa loggar för att hitta och åtgärda problem.\n\nVissa loggar kan innehålla känsliga uppgifter, så du ska bara bevilja appar du litar på åtkomst till alla enhetsloggar. \n\nEn app har åtkomst till sina egna loggar även om du inte ger den åtkomst till alla enhetsloggar. Enhetens tillverkare kan fortfarande ha åtkomst till vissa loggar eller viss information på enheten. Läs mer"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"I enhetsloggar registreras vad som händer på enheten. Appar kan använda dessa loggar för att hitta och åtgärda problem.\n\nVissa loggar kan innehålla känsliga uppgifter, så du ska bara bevilja appar du litar på åtkomst till alla enhetsloggar. \n\nEn app har åtkomst till sina egna loggar även om du inte ger den åtkomst till alla enhetsloggar. Enhetens tillverkare kan fortfarande ha åtkomst till vissa loggar eller viss information på enheten."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Visa inte igen"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> vill kunna visa bitar av <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Redigera"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Kontrollera aktiva appar"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Telefonens kamera kan inte användas från <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Surfplattans kamera kan inte användas från <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Det går inte att komma åt innehållet när du streamar. Testa med telefonen i stället."</string>
<string name="system_locale_title" msgid="711882686834677268">"Systemets standardinställning"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 3f57bd1..2d54843 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Mchakato wa alama ya kidole umeghairiwa."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Mtumiaji ameghairi uthibitishaji wa alama ya kidole."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Majaribio mengi mno. Jaribu tena baadaye."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Majaribio mengi mno. Kitambua alama ya kidole kimezimwa."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Jaribu tena."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Hakuna alama za vidole zilizojumuishwa."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Kifaa hiki hakina kitambua alama ya kidole."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Inaandaa <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Programu zinaanza"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Inamaliza kuwasha."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Ungependa kuendelea kuweka mipangilio?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Umebonyeza kitufe cha kuwasha/kuzima — kwa kawaida, hali hii huzima skrini.\n\nJaribu kugusa taratibu unapoweka mipangilio ya alama ya kidole chako."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Zima skrini"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Endelea kuweka mipangilio"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Gusa ili uzime skrini"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Zima skrini"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Utaendelea kuthibitisha alama ya kidole chako?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Umebonyeza kitufe cha kuwasha/kuzima — kwa kawaida, hali hii huzima skrini.\n\nJaribu kugusa taratibu ili uthibitishe alama ya kidole chako."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Zima skrini"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Gusa ili uweke mipangilio"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Chagua ili uweke mipangilio"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Huenda ukahitaji kubadilisha mipangilio ya kifaa. Gusa ili uondoe."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Kwa ajili ya kuhamisha picha na maudhui"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Kwa ajili ya kuhifadhi picha, video, muziki na zaidi"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Vinjari faili za maudhui"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Tatizo limetokea kwenye <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> haifanyi kazi"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Gusa ili urekebishe"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> imeharibika. Ichague ili uirekebishe."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Huenda ukahitaji kubadilisha mipangilio ya kifaa. Gusa ili uondoe."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> isiyotumika"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Imetambua <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> haifanyi kazi"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Kifaa hiki hakitumii <xliff:g id="NAME">%s</xliff:g>. Gusa ili uweke mipangilio ya muundo unaoweza kutumika."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Gusa ili uweke mipangilio ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Chagua ili uweke mipangilio ya <xliff:g id="NAME">%s</xliff:g> katika muundo unaoweza kutumika."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Huenda ukahitaji kubadilisha mipangilio ya kifaa"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> imeondolewa bila kutarajiwa"</string>
@@ -1568,7 +1568,7 @@
<string name="action_bar_home_subtitle_description_format" msgid="4346835454749569826">"%1$s, %2$s, %3$s"</string>
<string name="storage_internal" msgid="8490227947584914460">"Hifadhi ya ndani ya pamoja"</string>
<string name="storage_sd_card" msgid="3404740277075331881">"Kadi ya SD"</string>
- <string name="storage_sd_card_label" msgid="7526153141147470509">"Kadi ya SD iliyotengenezwa na <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
+ <string name="storage_sd_card_label" msgid="7526153141147470509">"Kadi ya SD ya <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="448030813201444573">"Hifadhi ya USB"</string>
<string name="storage_usb_drive_label" msgid="6631740655876540521">"Hifadhi ya USB iliyotengenezwa na <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb" msgid="2391213347883616886">"Hifadhi ya USB"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Mapendeleo ya eneo"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Weka jina la lugha"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Zinazopendekezwa"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Yanayopendekezwa"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Lugha zote"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Maeneo yote"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Tafuta"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Ungependa kuruhusu <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ifikie kumbukumbu zote za kifaa?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Ruhusu ufikiaji wa mara moja"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Usiruhusu"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Kumbukumbu za kifaa hurekodi kinachofanyika kwenye kifaa chako. Programu zinaweza kutumia kumbukumbu hizi ili kutambua na kurekebisha hitilafu.\n\nBaadhi ya kumbukumbu huenda zikawa na taarifa nyeti, hivyo ruhusu tu programu unazoziamini kufikia kumbukumbu zote za kifaa. \n\nIwapo hutaruhusu programu hii ifikie kumbukumbu zote za kifaa, bado inaweza kufikia kumbukumbu zake yenyewe. Mtengenezaji wa kifaa chako bado anaweza kufikia baadhi ya kumbukumbu au taarifa zilizopo kwenye kifaa chako. Pata maelezo zaidi"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Kumbukumbu za kifaa zinarekodi kinachofanyika kwenye kifaa chako. Programu zinaweza kutumia kumbukumbu hizi ili kutambua na kurekebisha hitilafu.\n\nBaadhi ya kumbukumbu huenda zikawa na taarifa nyeti, hivyo ruhusu tu programu unazoziamini kufikia kumbukumbu zote za kifaa. \n\nIwapo hutaruhusu programu hii ifikie kumbukumbu zote za kifaa, bado inaweza kufikia kumbukumbu zake yenyewe. Huenda mtengenezaji wa kifaa chako bado akaweza kufikia baadhi ya kumbukumbu au taarifa zilizopo kwenye kifaa chako."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Usionyeshe tena"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> inataka kuonyesha vipengee <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Badilisha"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Angalia programu zinazotumika"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Haiwezi kufikia kamera ya simu kutoka kwenye <xliff:g id="DEVICE">%1$s</xliff:g> yako"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Haiwezi kufikia kamera ya kompyuta kibao kutoka kwenye <xliff:g id="DEVICE">%1$s</xliff:g> yako"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Huwezi kufikia maudhui haya unapotiririsha. Badala yake jaribu kwenye simu yako."</string>
<string name="system_locale_title" msgid="711882686834677268">"Chaguomsingi la mfumo"</string>
</resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 42d4bfa..9a6f6c1 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"கைரேகை செயல்பாடு ரத்துசெய்யப்பட்டது."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"பயனர், கைரேகை உறுதிப்படுத்துதலை ரத்துசெய்தார்."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"அதிகமான முயற்சிகள். பிறகு முயற்சிக்கவும்."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"பலமுறை முயன்றுவிட்டீர்கள். கைரேகை சென்சார் முடக்கப்பட்டது."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"மீண்டும் முயற்சிக்கவும்."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"கைரேகைப் பதிவுகள் எதுவும் இல்லை."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"இந்தச் சாதனத்தில் கைரேகை சென்சார் இல்லை."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>ஐத் தயார்செய்கிறது."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ஆப்ஸ் தொடங்கப்படுகின்றன."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"துவக்குதலை முடிக்கிறது."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"அமைவைத் தொடரவா?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"நீங்கள் பவர் பட்டனை அழுத்தியுள்ளீர்கள் — வழக்கமாக இது திரையை ஆஃப் செய்யும்.\n\nஉங்கள் கைரேகையை அமைக்கும்போது மெதுவாகத் தொடுங்கள்."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"திரையை ஆஃப் செய்"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"அமைவைத் தொடர்க"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"திரையை அணைக்க தட்டவும்"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"திரையை அணை"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"கைரேகைச் சரிபார்ப்பைத் தொடரவா?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"நீங்கள் பவர் பட்டனை அழுத்தியுள்ளீர்கள் — வழக்கமாக இது திரையை ஆஃப் செய்யும்.\n\nஉங்கள் கைரேகையைச் சரிபார்க்க மெதுவாகத் தொடுங்கள்."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"திரையை ஆஃப் செய்"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"அமைக்க, தட்டவும்"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"அமைக்கத் தேர்ந்தெடுங்கள்"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"சாதனத்தை ரீஃபார்மேட் செய்ய வேண்டியிருக்கும். வெளியேற்ற தட்டவும்."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"படங்களையும் மீடியாவையும் மாற்றலாம்"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"படங்கள், வீடியோக்கள், இசை மற்றும் பலவற்றைச் சேமிப்பதற்கு"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"மீடியா ஃபைல்களை உலாவுக"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> இல் சிக்கல்"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> வேலை செய்யவில்லை"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"சரிசெய்ய, தட்டவும்"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> சிதைந்துள்ளது. சரிசெய்ய, தேர்ந்தெடுக்கவும்."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"சாதனத்தை ரீஃபார்மேட் செய்ய வேண்டியிருக்கும். வெளியேற்ற தட்டவும்."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"ஆதரிக்கப்படாத <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> கண்டறியப்பட்டுள்ளது"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> வேலை செய்யவில்லை"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"சாதனம் இந்த <xliff:g id="NAME">%s</xliff:g>ஐ ஆதரிக்கவில்லை. ஆதரிக்கப்படும் வடிவமைப்பில் அமைக்க, தட்டவும்."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"அமைக்க தட்டுங்கள்."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"ஆதரிக்கப்படும் வடிவத்தில் <xliff:g id="NAME">%s</xliff:g> ஐ அமைக்கத் தேர்ந்தெடுங்கள்."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"சாதனத்தை ரீஃபார்மேட் செய்ய வேண்டியிருக்கும்"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> அகற்றப்பட்டது"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"மண்டல விருப்பம்"</string>
<string name="search_language_hint" msgid="7004225294308793583">"மொழி பெயரை உள்ளிடுக"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"பரிந்துரைகள்"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"பரிந்துரைக்கப்படுபவை"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"எல்லா மொழிகளும்"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"எல்லா மண்டலங்களும்"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"தேடு"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"சாதனப் பதிவுகள் அனைத்தையும் <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> அணுக அனுமதிக்கவா?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"ஒருமுறை அணுகலை அனுமதி"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"அனுமதிக்க வேண்டாம்"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"உங்கள் சாதனத்தில் நடப்பவற்றைச் சாதனப் பதிவுகள் ரெக்கார்டு செய்யும். சிக்கல்களைக் கண்டறிந்து சரிசெய்ய ஆப்ஸ் இந்தப் பதிவுகளைப் பயன்படுத்தலாம்.\n\nபாதுகாக்கப்பட வேண்டிய தகவல்கள் சில பதிவுகளில் இருக்கக்கூடும் என்பதால் சாதனப் பதிவுகள் அனைத்தையும் அணுக நீங்கள் நம்பும் ஆப்ஸை மட்டும் அனுமதிக்கவும். \n\nசாதனப் பதிவுகள் அனைத்தையும் அணுக இந்த ஆப்ஸை அனுமதிக்கவில்லை என்றாலும் அதற்குச் சொந்தமான பதிவுகளை அதனால் அணுக முடியும். சாதன உற்பத்தியாளர் உங்கள் சாதனத்திலுள்ள சில பதிவுகளையோ தகவல்களையோ தொடர்ந்து அணுகக்கூடும். மேலும் அறிக"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"உங்கள் சாதனத்தில் நடப்பவற்றைச் சாதனப் பதிவுகள் ரெக்கார்டு செய்யும். சிக்கல்களைக் கண்டறிந்து சரிசெய்ய ஆப்ஸ் இந்தப் பதிவுகளைப் பயன்படுத்தலாம்.\n\nபாதுகாக்கப்பட வேண்டிய தகவல்கள் சில பதிவுகளில் இருக்கக்கூடும் என்பதால் சாதனப் பதிவுகள் அனைத்தையும் அணுக நீங்கள் நம்பும் ஆப்ஸை மட்டும் அனுமதிக்கவும். \n\nசாதனப் பதிவுகள் அனைத்தையும் அணுக இந்த ஆப்ஸை அனுமதிக்கவில்லை என்றாலும் அதற்குச் சொந்தமான பதிவுகளை அதனால் அணுக முடியும். உங்கள் சாதனத்திலுள்ள சில பதிவுகளையோ தகவல்களையோ சாதன உற்பத்தியாளரால் தொடர்ந்து அணுக முடியும்."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"மீண்டும் காட்டாதே"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_2">%2$s</xliff:g> ஆப்ஸின் விழிப்பூட்டல்களைக் காண்பிக்க, <xliff:g id="APP_0">%1$s</xliff:g> அனுமதி கேட்கிறது"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"திருத்து"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"செயலிலுள்ள ஆப்ஸைப் பாருங்கள்"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"உங்கள் <xliff:g id="DEVICE">%1$s</xliff:g> சாதனத்திலிருந்து மொபைலின் கேமராவை அணுக முடியாது"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"உங்கள் <xliff:g id="DEVICE">%1$s</xliff:g> சாதனத்திலிருந்து டேப்லெட்டின் கேமராவை அணுக முடியாது"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"ஸ்ட்ரீமின்போது இதை அணுக முடியாது. அதற்குப் பதிலாக உங்கள் மொபைலில் பயன்படுத்திப் பார்க்கவும்."</string>
<string name="system_locale_title" msgid="711882686834677268">"சிஸ்டத்தின் இயல்பு"</string>
</resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 8207c50..257959f 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -149,11 +149,11 @@
<!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
<skip />
<string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> బ్యాకప్ కాలింగ్"</string>
- <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వార్డ్ చేయబడలేదు"</string>
+ <string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వర్డ్ చేయబడలేదు"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> సెకన్ల తర్వాత <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
- <string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వార్డ్ చేయబడలేదు"</string>
- <string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వార్డ్ చేయబడలేదు"</string>
+ <string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వర్డ్ చేయబడలేదు"</string>
+ <string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వర్డ్ చేయబడలేదు"</string>
<string name="fcComplete" msgid="1080909484660507044">"లక్షణం కోడ్ పూర్తయింది."</string>
<string name="fcError" msgid="5325116502080221346">"కనెక్షన్ సమస్య లేదా లక్షణం కోడ్ చెల్లదు."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"సరే"</string>
@@ -287,7 +287,7 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB కనెక్షన్"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"యాప్ అమలవుతోంది"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"బ్యాటరీని ఉపయోగిస్తున్న యాప్లు"</string>
- <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"మాగ్నిఫికేషన్"</string>
+ <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"మ్యాగ్నిఫికేషన్"</string>
<string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"యాక్సెసిబిలిటీ వినియోగం"</string>
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> బ్యాటరీని ఉపయోగిస్తోంది"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> యాప్లు బ్యాటరీని ఉపయోగిస్తున్నాయి"</string>
@@ -333,7 +333,7 @@
<string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"నొక్కిన అంశాలు బిగ్గరగా చదివి వినిపించబడతాయి మరియు సంజ్ఞలను ఉపయోగించి స్క్రీన్ను విశ్లేషించవచ్చు."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"మీరు టైప్ చేస్తున్న వచనాన్ని పరిశీలిస్తుంది"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"క్రెడిట్ కార్డు నంబర్లు మరియు పాస్వర్డ్ల వంటి వ్యక్తిగత డేటాను కలిగి ఉంటుంది."</string>
- <string name="capability_title_canControlMagnification" msgid="7701572187333415795">"డిస్ప్లే మాగ్నిఫికేషన్ను నియంత్రించండి"</string>
+ <string name="capability_title_canControlMagnification" msgid="7701572187333415795">"డిస్ప్లే మ్యాగ్నిఫికేషన్ను నియంత్రించండి"</string>
<string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"డిస్ప్లే జూమ్ స్థాయి మరియు స్థానాన్ని నియంత్రిస్తుంది."</string>
<string name="capability_title_canPerformGestures" msgid="9106545062106728987">"సంజ్ఞలను చేయడం"</string>
<string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"నొక్కగలరు, స్వైప్ చేయగలరు, స్క్రీన్పై రెండు వేళ్లను ఉంచి ఆ వేళ్లను దగ్గరకు లేదా దూరానికి లాగగలరు మరియు ఇతర సంజ్ఞలను చేయగలరు."</string>
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"వేలిముద్ర యాక్టివిటీ రద్దయింది."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"వేలిముద్ర చర్యని వినియోగదారు రద్దు చేశారు."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"చాలా ఎక్కువ ప్రయత్నాలు చేశారు. తర్వాత మళ్లీ ప్రయత్నించండి."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"అనేకసార్లు ప్రయత్నించారు. వేలిముద్ర సెన్సార్ నిలిపివేయబడింది."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"మళ్లీ ప్రయత్నించండి."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"వేలిముద్రలు నమోదు చేయబడలేదు."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ఈ పరికరంలో వేలిముద్ర సెన్సార్ ఎంపిక లేదు."</string>
@@ -941,7 +942,7 @@
<string name="lockscreen_transport_play_description" msgid="106868788691652733">"ప్లే చేయి"</string>
<string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"ఆపివేయి"</string>
<string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"రివైండ్ చేయి"</string>
- <string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"వేగంగా ఫార్వార్డ్ చేయి"</string>
+ <string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"వేగంగా ఫార్వర్డ్ చేయి"</string>
<string name="emergency_calls_only" msgid="3057351206678279851">"ఎమర్జెన్సీ కాల్స్ మాత్రమే"</string>
<string name="lockscreen_network_locked_message" msgid="2814046965899249635">"నెట్వర్క్ లాక్ చేయబడింది"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"సిమ్ కార్డు PUK-లాక్ చేయబడింది."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>ని సిద్ధం చేస్తోంది."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"యాప్లను ప్రారంభిస్తోంది."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"బూట్ను ముగిస్తోంది."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"సెటప్ను కొనసాగించాలా?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"మీరు పవర్ బటన్ను నొక్కారు — ఇది సాధారణంగా స్క్రీన్ను ఆఫ్ చేస్తుంది.\n\nమీ వేలిముద్రను సెటప్ చేస్తున్నప్పుడు తేలికగా ట్యాప్ చేయడానికి ట్రై చేయండి."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"స్క్రీన్ను ఆఫ్ చేయి"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"సెటప్ను కొనసాగించు"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"స్క్రీన్ను ఆఫ్ చేయడానికి ట్యాప్ చేయండి"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"స్క్రీన్ను ఆఫ్ చేయి"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"మీ వేలిముద్ర వెరిఫైను కొనసాగించాలా?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"మీరు పవర్ బటన్ను నొక్కారు — ఇది సాధారణంగా స్క్రీన్ను ఆఫ్ చేస్తుంది.\n\nమీ వేలిముద్రను వెరిఫై చేయడానికి తేలికగా ట్యాప్ చేయడం ట్రై చేయండి."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"స్క్రీన్ను ఆఫ్ చేయి"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"సెటప్ చేయడానికి నొక్కండి"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"సెటప్ చేయడానికి ఎంచుకోండి"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"మీరు పరికరాన్ని తిరిగి ఫార్మాట్ చేయాల్సి ఉంటుంది. తొలగించడానికి ట్యాప్ చేయండి"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"ఫోటోలు, మీడియాను బదిలీ చేయడానికి"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"ఫోటోలు, వీడియోలు, మ్యూజిక్ ఇంకా మరిన్నింటిని స్టోర్ చేయడానికి నోటిఫికేషన్ బాడీని ఉపయోగించండి"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"మీడియా ఫైల్స్ను బ్రౌజ్ చేయండి"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g>తో సమస్య ఉంది"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> పని చేయటం లేదు"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"పరిష్కరించడానికి నొక్కండి"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> పాడైంది. సరిచేయడానికి ఎంచుకోండి."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"మీరు పరికరాన్ని తిరిగి ఫార్మాట్ చేయాల్సి ఉంటుంది. తొలగించడానికి ట్యాప్ చేయండి"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g>కి మద్దతు లేదు"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> గుర్తించబడింది"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> పని చేయటం లేదు"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ఈ పరికరం ఈ <xliff:g id="NAME">%s</xliff:g>కు సపోర్ట్ ఇవ్వదు. సపోర్ట్ ఉన్న ఫార్మాట్లో సెటప్ చేయడానికి నొక్కండి."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"సెటప్ చేయడానికి ట్యాప్ చేయండి ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"సపోర్ట్ చేసే ఫార్మాట్లో <xliff:g id="NAME">%s</xliff:g>ను సెటప్ చేయడానికి ఎంచుకోండి."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"మీరు పరికరాన్ని తిరిగి ఫార్మాట్ చేయాల్సి ఉంటుంది"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ఊహించని విధంగా తీసివేయబడింది"</string>
@@ -1715,7 +1715,7 @@
<string name="accessibility_button_instructional_text" msgid="8853928358872550500">"ఫీచర్ల మధ్య మారడానికి, యాక్సెసిబిలిటీ బటన్ను నొక్కి & పట్టుకోండి."</string>
<string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"ఫీచర్ల మధ్య మారడానికి, రెండు చేతి వేళ్ళతో పైకి స్వైప్ చేసి పట్టుకోండి."</string>
<string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"ఫీచర్ల మధ్య మారడానికి, మూడు చేతి వేళ్ళతో పైకి స్వైప్ చేసి పట్టుకోండి."</string>
- <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"మాగ్నిఫికేషన్"</string>
+ <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"మ్యాగ్నిఫికేషన్"</string>
<string name="user_switched" msgid="7249833311585228097">"ప్రస్తుత వినియోగదారు <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> యూజర్కు స్విచ్ అవుతోంది…"</string>
<string name="user_logging_out_message" msgid="7216437629179710359">"<xliff:g id="NAME">%1$s</xliff:g>ని లాగ్ అవుట్ చేస్తోంది…"</string>
@@ -1823,7 +1823,7 @@
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"రద్దు చేయబడింది"</string>
<string name="write_fail_reason_cannot_write" msgid="432118118378451508">"కంటెంట్ను వ్రాయడంలో ఎర్రర్"</string>
<string name="reason_unknown" msgid="5599739807581133337">"తెలియదు"</string>
- <string name="reason_service_unavailable" msgid="5288405248063804713">"ముద్రణ సేవ ప్రారంభించబడలేదు"</string>
+ <string name="reason_service_unavailable" msgid="5288405248063804713">"ప్రింట్ సర్వీసు ప్రారంభించబడలేదు"</string>
<string name="print_service_installed_title" msgid="6134880817336942482">"<xliff:g id="NAME">%s</xliff:g> సేవ ఇన్స్టాల్ చేయబడింది"</string>
<string name="print_service_installed_message" msgid="7005672469916968131">"ప్రారంభించడానికి నొక్కండి"</string>
<string name="restr_pin_enter_admin_pin" msgid="1199419462726962697">"నిర్వాహకుల పిన్ను నమోదు చేయండి"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"ప్రాంతం ప్రాధాన్యత"</string>
<string name="search_language_hint" msgid="7004225294308793583">"భాష పేరును టైప్ చేయండి"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"సూచించినవి"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"సూచించబడినవి"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"అన్ని భాషలు"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"అన్ని ప్రాంతాలు"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"సెర్చ్"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"అన్ని పరికర లాగ్లను యాక్సెస్ చేయడానికి <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>ను అనుమతించాలా?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"వన్-టైమ్ యాక్సెస్ను అనుమతించండి"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"అనుమతించవద్దు"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"మీ పరికరంలో జరిగే దాన్ని పరికర లాగ్లు రికార్డ్ చేస్తాయి. సమస్యలను కనుగొని, పరిష్కరించడానికి యాప్లు ఈ లాగ్లను ఉపయోగిస్తాయి.\n\nకొన్ని లాగ్లలో గోప్యమైన సమాచారం ఉండవచ్చు, కాబట్టి మీరు విశ్వసించే యాప్లను మాత్రమే అన్ని పరికర లాగ్లను యాక్సెస్ చేయడానికి అనుమతించండి. \n\nఅన్ని పరికర లాగ్లను యాక్సెస్ చేయడానికి మీరు ఈ యాప్ను అనుమతించకపోతే, అది తన స్వంత లాగ్లను ఇప్పటికి యాక్సెస్ చేయగలదు. మీ పరికర తయారీదారు ఇప్పటికీ మీ పరికరంలో కొన్ని లాగ్లు లేదా సమాచారాన్ని యాక్సెస్ చేయగలరు. మరింత తెలుసుకోండి"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"మీ పరికరంలో జరిగే దాన్ని పరికర లాగ్లు రికార్డ్ చేస్తాయి. సమస్యలను కనుగొని, పరిష్కరించడానికి యాప్లు ఈ లాగ్లను ఉపయోగిస్తాయి.\n\nకొన్ని లాగ్లలో గోప్యమైన సమాచారం ఉండవచ్చు, కాబట్టి మీరు విశ్వసించే యాప్లను మాత్రమే అన్ని పరికర లాగ్లను యాక్సెస్ చేయడానికి అనుమతించండి. \n\nఅన్ని పరికర లాగ్లను యాక్సెస్ చేయడానికి మీరు ఈ యాప్ను అనుమతించకపోతే, అది తన స్వంత లాగ్లను ఇప్పటికి యాక్సెస్ చేయగలదు. మీ పరికర తయారీదారు ఇప్పటికీ మీ పరికరంలో కొన్ని లాగ్లు లేదా సమాచారాన్ని యాక్సెస్ చేయగలరు."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"మళ్లీ చూపవద్దు"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> <xliff:g id="APP_2">%2$s</xliff:g> స్లైస్లను చూపించాలనుకుంటోంది"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"ఎడిట్ చేయండి"</string>
@@ -2268,7 +2269,7 @@
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
<string name="window_magnification_prompt_title" msgid="2876703640772778215">"కొత్త మ్యాగ్నిఫికేషన్ సెట్టింగ్లు"</string>
- <string name="window_magnification_prompt_content" msgid="8159173903032344891">"మీరు ఇప్పుడు మీ స్క్రీన్ కొంత భాగాన్ని మాగ్నిఫై చేయవచ్చు"</string>
+ <string name="window_magnification_prompt_content" msgid="8159173903032344891">"మీరు ఇప్పుడు మీ స్క్రీన్ కొంత భాగాన్ని మ్యాగ్నిఫై చేయవచ్చు"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"సెట్టింగ్లలో ఆన్ చేయండి"</string>
<string name="dismiss_action" msgid="1728820550388704784">"విస్మరించు"</string>
<string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"పరికరం మైక్రోఫోన్ను అన్బ్లాక్ చేయండి"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"యాక్టివ్గా ఉన్న యాప్లను చెక్ చేయండి"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"మీ <xliff:g id="DEVICE">%1$s</xliff:g> నుండి ఫోన్ కెమెరాను యాక్సెస్ చేయడం సాధ్యపడదు"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"మీ <xliff:g id="DEVICE">%1$s</xliff:g> నుండి టాబ్లెట్ కెమెరాను యాక్సెస్ చేయడం సాధ్యపడదు"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"స్ట్రీమింగ్ చేస్తున్నప్పుడు దీన్ని యాక్సెస్ చేయడం సాధ్యపడదు. బదులుగా మీ ఫోన్లో ట్రై చేయండి."</string>
<string name="system_locale_title" msgid="711882686834677268">"సిస్టమ్ ఆటోమేటిక్ సెట్టింగ్"</string>
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index f54f4ec..c5bdaa9 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"ยกเลิกการทำงานของลายนิ้วมือ"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ผู้ใช้ยกเลิกการทำงานของลายนิ้วมือ"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"ดำเนินการหลายครั้งเกินไป ลองอีกครั้งในภายหลัง"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"ลองหลายครั้งเกินไป ปิดใช้เซ็นเซอร์ลายนิ้วมือแล้ว"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ลองอีกครั้ง"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ไม่มีลายนิ้วมือที่ลงทะเบียน"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"อุปกรณ์นี้ไม่มีเซ็นเซอร์ลายนิ้วมือ"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"กำลังเตรียม <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"กำลังเริ่มต้นแอปพลิเคชัน"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"เสร็จสิ้นการบูต"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"ตั้งค่าต่อไหม"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"คุณกดปุ่มเปิด/ปิดซึ่งโดยปกติจะเป็นการปิดหน้าจอ\n\nลองแตะเบาๆ ขณะตั้งค่าลายนิ้วมือ"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"ปิดหน้าจอ"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"ตั้งค่าต่อ"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"แตะเพื่อปิดหน้าจอ"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ปิดหน้าจอ"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"ยืนยันลายนิ้วมือต่อไหม"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"คุณกดปุ่มเปิด/ปิดซึ่งโดยปกติจะเป็นการปิดหน้าจอ\n\nลองแตะเบาๆ เพื่อยืนยันลายนิ้วมือ"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ปิดหน้าจอ"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"แตะเพื่อตั้งค่า"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"เลือกเพื่อตั้งค่า"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"คุณอาจต้องฟอร์แมตอุปกรณ์นี้ใหม่ แตะเพื่อนำอุปกรณ์ออก"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"สำหรับการโอนรูปภาพและสื่อ"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"สำหรับการจัดเก็บรูปภาพ วิดีโอ เพลง และอื่นๆ"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"เรียกดูไฟล์สื่อ"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"ปัญหาเกี่ยวกับ <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ใช้งานไม่ได้"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"แตะเพื่อแก้ไข"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> เสียหาย เลือกเพื่อแก้ไข"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"คุณอาจต้องฟอร์แมตอุปกรณ์นี้ใหม่ แตะเพื่อนำอุปกรณ์ออก"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"ไม่สนับสนุน <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"ตรวจพบ<xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ใช้งานไม่ได้"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"อุปกรณ์นี้ไม่สนับสนุน <xliff:g id="NAME">%s</xliff:g> นี้ แตะเพื่อตั้งค่าในรูปแบบที่สนับสนุน"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"แตะเพื่อตั้งค่า"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"เลือกเพื่อตั้งค่า<xliff:g id="NAME">%s</xliff:g> ในรูปแบบที่รองรับ"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"คุณอาจต้องฟอร์แมตอุปกรณ์นี้ใหม่"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ถูกนำออกไปโดยไม่คาดคิด"</string>
@@ -1427,7 +1427,7 @@
<string name="ext_media_unmount_action" msgid="966992232088442745">"นำอุปกรณ์ออก"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"สำรวจ"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"เปลี่ยนเอาต์พุต"</string>
- <string name="ext_media_missing_title" msgid="3209472091220515046">"ไม่มี <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_missing_title" msgid="3209472091220515046">"ไม่มี<xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_missing_message" msgid="4408988706227922909">"ใส่อุปกรณ์อีกครั้ง"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"กำลังย้าย <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"กำลังย้ายข้อมูล"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"ค่ากำหนดภูมิภาค"</string>
<string name="search_language_hint" msgid="7004225294308793583">"พิมพ์ชื่อภาษา"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"แนะนำ"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"แนะนำ"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"ทุกภาษา"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"ภูมิภาคทั้งหมด"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"ค้นหา"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"อนุญาตให้ <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> เข้าถึงบันทึกทั้งหมดของอุปกรณ์ใช่ไหม"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"อนุญาตสิทธิ์เข้าถึงแบบครั้งเดียว"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"ไม่อนุญาต"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"บันทึกของอุปกรณ์เก็บข้อมูลสิ่งที่เกิดขึ้นในอุปกรณ์ แอปสามารถใช้บันทึกเหล่านี้เพื่อค้นหาและแก้ไขปัญหา\n\nบันทึกบางรายการอาจมีข้อมูลที่ละเอียดอ่อน คุณจึงควรอนุญาตเฉพาะแอปที่เชื่อถือได้ให้เข้าถึงบันทึกทั้งหมดของอุปกรณ์ \n\nหากคุณไม่อนุญาตให้แอปนี้เข้าถึงบันทึกทั้งหมดของอุปกรณ์ แอปจะยังเข้าถึงบันทึกของตัวเองได้อยู่ ผู้ผลิตอุปกรณ์อาจยังเข้าถึงบันทึกหรือข้อมูลบางรายการในอุปกรณ์ของคุณได้ ดูข้อมูลเพิ่มเติม"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"บันทึกของอุปกรณ์เก็บข้อมูลสิ่งที่เกิดขึ้นในอุปกรณ์ แอปสามารถใช้บันทึกเหล่านี้เพื่อค้นหาและแก้ไขปัญหา\n\nบันทึกบางรายการอาจมีข้อมูลที่ละเอียดอ่อน คุณจึงควรอนุญาตเฉพาะแอปที่เชื่อถือได้ให้เข้าถึงบันทึกทั้งหมดของอุปกรณ์ \n\nหากคุณไม่อนุญาตให้แอปนี้เข้าถึงบันทึกทั้งหมดของอุปกรณ์ แอปจะยังเข้าถึงบันทึกของตัวเองได้อยู่ ผู้ผลิตอุปกรณ์อาจยังเข้าถึงบันทึกหรือข้อมูลบางรายการในอุปกรณ์ของคุณได้"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"ไม่ต้องแสดงอีก"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> ต้องการแสดงส่วนต่างๆ ของ <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"แก้ไข"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ตรวจสอบแอปที่ใช้งานอยู่"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"เข้าถึงกล้องของโทรศัพท์จาก <xliff:g id="DEVICE">%1$s</xliff:g> ไม่ได้"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"เข้าถึงกล้องของแท็บเล็ตจาก <xliff:g id="DEVICE">%1$s</xliff:g> ไม่ได้"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"เข้าถึงเนื้อหานี้ไม่ได้ขณะที่สตรีมมิง โปรดลองเข้าถึงในโทรศัพท์แทน"</string>
<string name="system_locale_title" msgid="711882686834677268">"ค่าเริ่มต้นของระบบ"</string>
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 9a77b4b..5172940 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Nakansela ang operasyong ginagamitan ng fingerprint."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Kinansela ng user ang operasyon sa fingerprint."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Napakaraming pagtatangka. Subukan ulit sa ibang pagkakataon."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Masyadong maraming beses sumubok. Na-disable ang sensor para sa fingerprint."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Subukang muli."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Walang naka-enroll na fingerprint."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Walang sensor ng fingerprint ang device na ito."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Ihinahanda ang <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Sinisimulan ang apps."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Pagtatapos ng pag-boot."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Ituloy ang pag-set up?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Pinindot mo ang power button — karaniwan nitong ino-off ang screen.\n\nSubukang i-tap habang sine-set up ang iyong fingerprint."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"I-off ang screen"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Ituloy ang setup"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Mag-tap para i-off ang screen"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"I-off ang screen"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Magpatuloy sa pag-verify ng fingerprint?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Pinindot mo ang power button — karaniwan nitong ino-off ang screen.\n\nSubukang i-tap para i-verify ang iyong fingerprint."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"I-off ang screen"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Mag-tap para i-set up"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Piliin para i-set up"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Baka kailanganin mong i-reformat ang device. I-tap para i-eject."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Para sa paglilipat ng mga larawan at media"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Para sa pag-store ng mga larawan, video, musika, at higit pa"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Mag-browse ng mga media file"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Isyu sa <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"Hindi gumagana ang <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Mag-tap para ayusin"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Sira ang <xliff:g id="NAME">%s</xliff:g>. Piliin upang ayusin."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Baka kailanganin mong i-reformat ang device. I-tap para i-eject."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Hindi sinusuportahang <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"May na-detect na <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"Hindi gumagana ang <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Hindi sinusuportahan ng device na ito ang <xliff:g id="NAME">%s</xliff:g> na ito. I-tap upang i-set up sa isang sinusuportahang format."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"I-tap para i-set up."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Piliin para i-set up ang <xliff:g id="NAME">%s</xliff:g> sa isang sinusuportahang format."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Baka kailanganin mong i-reformat ang device"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Hindi inaasahang naalis ang <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1428,7 +1428,7 @@
<string name="ext_media_browse_action" msgid="344865351947079139">"I-explore"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Ilipat ang output"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"Nawawala ang <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="ext_media_missing_message" msgid="4408988706227922909">"Ikabit muli ang device"</string>
+ <string name="ext_media_missing_message" msgid="4408988706227922909">"Ikabit ulit ang device"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"Inililipat ang <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"Naglilipat ng data"</string>
<string name="ext_media_move_success_title" msgid="4901763082647316767">"Tapos na ang paglipat ng content"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Kagustuhan sa rehiyon"</string>
<string name="search_language_hint" msgid="7004225294308793583">"I-type ang wika"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Iminumungkahi"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Iminumungkahi"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Lahat ng wika"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Lahat ng rehiyon"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Maghanap"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Payagan ang <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> na i-access ang lahat ng log ng device?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Payagan ang isang beses na pag-access"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Huwag payagan"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Nire-record ng mga log ng device kung ano ang nangyayari sa iyong device. Magagamit ng mga app ang mga log na ito para maghanap at mag-ayos ng mga isyu.\n\nPosibleng maglaman ang ilang log ng sensitibong impormasyon, kaya ang mga app lang na pinagkakatiwalaan mo ang payagang maka-access sa lahat ng log ng device. \n\nKung hindi mo papayagan ang app na ito na i-access ang lahat ng log ng device, maa-access pa rin nito ang mga sarili nitong log. Posible pa ring ma-access ng manufacturer ng iyong device ang ilang log o impormasyon sa device mo. Matuto pa"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Nire-record ng mga log ng device kung ano ang nangyayari sa iyong device. Magagamit ng mga app ang mga log na ito para maghanap at mag-ayos ng mga isyu.\n\nPosibleng maglaman ang ilang log ng sensitibong impormasyon, kaya ang mga app lang na pinagkakatiwalaan mo ang payagang maka-access sa lahat ng log ng device. \n\nKung hindi mo papayagan ang app na ito na i-access ang lahat ng log ng device, maa-access pa rin nito ang mga sarili nitong log. Posible pa ring ma-access ng manufacturer ng iyong device ang ilang log o impormasyon sa device mo."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Huwag ipakita ulit"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"Gustong ipakita ng <xliff:g id="APP_0">%1$s</xliff:g> ang mga slice ng <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"I-edit"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Tingnan ang mga aktibong app"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Hindi ma-access ang camera ng telepono mula sa iyong <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Hindi ma-access ang camera ng tablet mula sa iyong <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Hindi ito puwedeng i-access habang nagsi-stream. Subukan na lang sa iyong telepono."</string>
<string name="system_locale_title" msgid="711882686834677268">"Default ng system"</string>
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index d27cb60..472c453 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Parmak izi işlemi iptal edildi."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Parmak izi işlemi kullanıcı tarafından iptal edildi."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Çok fazla deneme yapıldı. Daha sonra tekrar deneyin."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Çok fazla deneme yapıldı. Parmak izi sensörü devre dışı bırakıldı."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Tekrar deneyin."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Parmak izi kaydedilmedi."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Bu cihazda parmak izi sensörü yok."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> hazırlanıyor."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Uygulamalar başlatılıyor"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Açılış tamamlanıyor."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Kuruluma devam edilsin mi?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Güç düğmesine bastınız. Bu düğmeye basıldığında genellikle ekran kapanır.\n\nParmak izinizi tanımlarken hafifçe dokunmayı deneyin."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Ekranı kapat"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Kuruluma devam et"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Ekranı kapatmak için dokunun"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Ekranı kapat"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Parmak izi doğrulamaya devam edilsin mi?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Güç düğmesine bastınız. Bu düğmeye basıldığında genellikle ekran kapanır.\n\nParmak izinizi doğrulamak için hafifçe dokunmayı deneyin."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Ekranı kapat"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Ayarlamak için dokunun"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Kurmak için harici medyayı seçin"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Cihazı yeniden biçimlendirmeniz gerekebilir. Çıkarmak için dokunun."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Fotoğraf ve medya aktarmak için"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Fotoğraf, video, müzik ve daha fazlasını depolamak için"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Medya dosyalarına göz atın"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> medyasında sorun oluştu"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> çalışmıyor"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Düzeltmek için dokunun"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> bozuk. Düzeltmek için seçin."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Cihazı yeniden biçimlendirmeniz gerekebilir. Çıkarmak için dokunun."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Desteklenmeyen <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> algılandı"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> çalışmıyor"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Bu cihaz, bu <xliff:g id="NAME">%s</xliff:g> ortamını desteklemiyor. Desteklenen bir biçimde kurmak için dokunun."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Ayarlamak için dokunun."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"<xliff:g id="NAME">%s</xliff:g> kurulumunu desteklenen biçimde yapmak için seçin."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Cihazı yeniden biçimlendirmeniz gerekebilir"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> beklenmedik şekilde çıkarıldı"</string>
@@ -1596,7 +1596,7 @@
<string name="validity_period" msgid="1717724283033175968">"Geçerlilik:"</string>
<string name="issued_on" msgid="5855489688152497307">"Yayınlanma tarihi:"</string>
<string name="expires_on" msgid="1623640879705103121">"Sona erme tarihi:"</string>
- <string name="serial_number" msgid="3479576915806623429">"Seri numara:"</string>
+ <string name="serial_number" msgid="3479576915806623429">"Seri numarası:"</string>
<string name="fingerprints" msgid="148690767172613723">"Parmak izleri:"</string>
<string name="sha256_fingerprint" msgid="7103976380961964600">"SHA-256 parmak izi:"</string>
<string name="sha1_fingerprint" msgid="2339915142825390774">"SHA-1 parmak izi:"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Bölge tercihi"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Dil adını yazın"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Önerilen"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Önerilen"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Tüm diller"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Tüm bölgeler"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Ara"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> uygulamasının tüm cihaz günlüklerine erişmesine izin verilsin mi?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Tek seferlik erişim izni ver"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"İzin verme"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Cihaz günlükleri, cihazınızda olanları kaydeder. Uygulamalar, sorunları bulup düzeltmek için bu günlükleri kullanabilir.\n\nBazı günlükler hassas bilgiler içerebileceği için yalnızca güvendiğiniz uygulamaların tüm cihaz günlüklerine erişmesine izin verin. \n\nBu uygulamanın tüm cihaz günlüklerine erişmesine izin vermeseniz de kendi günlüklerine erişmeye devam edebilir. Ayrıca, cihaz üreticiniz de cihazınızdaki bazı günlüklere veya bilgilere erişmeye devam edebilir. Daha fazla bilgi"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Cihaz günlükleri, cihazınızda olanları kaydeder. Uygulamalar, sorunları bulup düzeltmek için bu günlükleri kullanabilir.\n\nBazı günlükler hassas bilgiler içerebileceği için yalnızca güvendiğiniz uygulamaların tüm cihaz günlüklerine erişmesine izin verin. \n\nBu uygulamanın tüm cihaz günlüklerine erişmesine izin vermeseniz de kendi günlüklerine erişmeye devam edebilir. Ayrıca, cihaz üreticiniz de cihazınızdaki bazı günlüklere veya bilgilere erişmeye devam edebilir."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Bir daha gösterme"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> uygulaması, <xliff:g id="APP_2">%2$s</xliff:g> dilimlerini göstermek istiyor"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Düzenle"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Etkin uygulamaları kontrol edin"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan telefonun kamerasına erişilemiyor"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan tabletin kamerasına erişilemiyor"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Canlı oynatılırken bu içeriğe erişilemez. Bunun yerine telefonunuzu kullanmayı deneyin."</string>
<string name="system_locale_title" msgid="711882686834677268">"Sistem varsayılanı"</string>
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 9ea6633..98c9412 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -610,7 +610,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Дію з відбитком пальця скасовано."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Користувач скасував дію з відбитком пальця."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Забагато спроб. Спробуйте пізніше."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Забагато спроб. Сканер відбитків пальців вимкнено."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Повторіть спробу."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Відбитки пальців не зареєстровано."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"На цьому пристрої немає сканера відбитків пальців."</string>
@@ -1251,10 +1252,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Підготовка додатка <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Запуск програм."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Завершення завантаження."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Продовжити реєстрацію?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Ви натиснули кнопку живлення – зазвичай після цього вимикається екран.\n\nЩоб зареєструвати відбиток пальця, спробуйте лише злегка торкнутися датчика."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Вимкнути екран"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Додати відбиток"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Натисніть, щоб вимкнути екран"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Вимкнути екран"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Продовжити підтвердження відбитка?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Ви натиснули кнопку живлення – зазвичай після цього вимикається екран.\n\nЩоб підтвердити відбиток пальця, спробуйте лише злегка торкнутися датчика."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Вимкнути екран"</string>
@@ -1407,16 +1407,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Торкніться, щоб налаштувати"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Виберіть, щоб налаштувати"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Можливо, пристрій доведеться відформатувати. Натисніть, щоб вилучити."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Для перенесення фотографій і медіафайлів"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Для зберігання фотографій, відео, музики тощо"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Перегляньте файли на носії"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Проблема з носієм (<xliff:g id="NAME">%s</xliff:g>)"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> не працює"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Торкніться, щоб виправити"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"Пристрій <xliff:g id="NAME">%s</xliff:g> пошкоджено. Виберіть, щоб виправити."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Можливо, пристрій доведеться відформатувати. Натисніть, щоб вилучити."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> не підтримується"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Знайдено пристрій (<xliff:g id="NAME">%s</xliff:g>)"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> не працює"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"<xliff:g id="NAME">%s</xliff:g> не підтримується цим пристроєм. Торкніться, щоб налаштувати підтримуваний формат."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Натисніть, щоб налаштувати"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Виберіть, щоб налаштувати носій (<xliff:g id="NAME">%s</xliff:g>) у підтримуваному форматі."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Можливо, пристрій доведеться відформатувати"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> несподівано вийнято"</string>
@@ -1929,6 +1929,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Вибір регіону"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Введіть назву мови"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Рекомендовані"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Пропоновані"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Усі мови"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Усі регіони"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Пошук"</string>
@@ -2051,7 +2052,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Надати додатку <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> доступ до всіх журналів пристрою?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Надати доступ лише цього разу"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Не дозволяти"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"У журналах пристрою реєструється все, що відбувається на ньому. За допомогою цих журналів додатки можуть виявляти й усувати проблеми.\n\nДеякі журнали можуть містити конфіденційні дані, тому надавати доступ до всіх журналів пристрою слід лише надійним додаткам. \n\nЯкщо додаток не має доступу до всіх журналів пристрою, він усе одно може використовувати власні журнали. Виробник вашого пристрою все одно може використовувати деякі журнали чи інформацію на ньому. Докладніше"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"У журналах пристрою реєструється все, що відбувається на ньому. За допомогою цих журналів додатки можуть виявляти й усувати проблеми.\n\nДеякі журнали можуть містити конфіденційні дані, тому надавати доступ до всіх журналів пристрою слід лише надійним додаткам. \n\nЯкщо додаток не має доступу до всіх журналів пристрою, він усе одно може використовувати власні журнали. Виробник вашого пристрою все одно може використовувати деякі журнали чи інформацію на ньому."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Більше не показувати"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> хоче показати фрагменти додатка <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Редагувати"</string>
@@ -2292,5 +2293,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Перевірте активні додатки"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Не вдається отримати доступ до камери телефона з пристрою <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Не вдається отримати доступ до камери планшета з пристрою <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Цей контент недоступний під час потокового передавання. Спробуйте натомість скористатися телефоном."</string>
<string name="system_locale_title" msgid="711882686834677268">"Налаштування системи за умовчанням"</string>
</resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 0d6538e..92cefcd 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"فنگر پرنٹ کی کارروائی منسوخ ہوگئی۔"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"صارف نے فنگر پرنٹ کی کارروائی منسوخ کر دی۔"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"کافی زیادہ کوششیں کی گئیں۔ بعد میں دوبارہ کوشش کریں۔"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"کافی زیادہ کوششیں۔ فنگر پرنٹ سینسر غیر فعال ہو گیا۔"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"دوبارہ کوشش کریں۔"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"کوئی فنگر پرنٹ مندرج شدہ نہیں ہے۔"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"اس آلہ میں فنگر پرنٹ سینسر نہیں ہے۔"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> تیار ہو رہی ہے۔"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ایپس شروع ہو رہی ہیں۔"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"بوٹ مکمل ہو رہا ہے۔"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"سیٹ اپ جاری رکھیں؟"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"آپ نے پاور بٹن دبایا — اس سے عام طور پر اسکرین آف ہو جاتی ہے۔\n\nاپنے فنگر پرنٹ کو سیٹ اپ کرنے کے دوران ہلکا سا تھپتھپانے کی کوشش کریں۔"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"اسکرین آف کریں"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"سیٹ اپ جاری رکھیں"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"اسکرین آف کرنے کیلئے تھپتھپائیں"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"اسکرین آف کریں"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"اپنے فنگر پرنٹ کی توثیق کرنا جاری رکھیں؟"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"آپ نے پاور بٹن دبایا — اس سے عام طور پر اسکرین آف ہو جاتی ہے۔\n\nاپنے فنگر پرنٹ کی توثیق کرنے کے لیے ہلکا سا تھپتھپانے کی کوشش کریں۔"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"اسکرین آف کریں"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"سیٹ اپ کرنے کیلئے تھپتھپائیں"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"سیٹ اپ کرنے کے لیے منتخب کریں"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"آپ کو آلے کو پھر سے فارمیٹ کرنے کی ضرورت پیش آ سکتی ہے۔ خارج کرنے کے لیے تھپتھپائیں۔"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"تصاویر اور میڈیا منتقل کرنے کیلئے"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"تصاویر، ویڈیوز، موسیقی وغیرہ کو اسٹور کرنے کے لئے"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"میڈیا فائلز کو براؤز کریں"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> کے ساتھ مسئلہ"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> کام نہیں کر رہا ہے"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"درست کرنے کیلئے تھپتھپائیں"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> خراب ہے۔ اسے ٹھیک کرنے کیلئے منتخب کریں۔"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"آپ کو آلے کو پھر سے فارمیٹ کرنے کی ضرورت پیش آ سکتی ہے۔ خارج کرنے کے لیے تھپتھپائیں۔"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"غیر تعاون یافتہ <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> کا پتا چلا"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> کام نہیں کر رہا ہے"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"یہ آلہ <xliff:g id="NAME">%s</xliff:g> کو سپورٹ نہیں کرتا۔ ایک سپورٹ یافتہ فارمیٹ میں سیٹ اپ کرنے کیلئے تھپتھپائیں۔"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"سیٹ اپ کرنے کیلئے تھپتھپائیں ۔"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"سپورٹ یافتہ فارمیٹ میں <xliff:g id="NAME">%s</xliff:g> سیٹ اپ کرنے کے لیے منتخب کریں۔"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"آپ کو آلے کو پھر سے فارمیٹ کرنے کی ضرورت پیش آ سکتی ہے"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> غیر متوقع طور پر ہٹا دیا گیا"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"علاقہ کی ترجیح"</string>
<string name="search_language_hint" msgid="7004225294308793583">"زبان کا نام ٹائپ کریں"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"تجویز کردہ"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"تجویز کردہ"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"سبھی زبانیں"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"تمام علاقے"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"تلاش"</string>
@@ -1987,7 +1988,7 @@
<string name="app_category_productivity" msgid="1844422703029557883">"پروڈکٹیوٹی"</string>
<string name="app_category_accessibility" msgid="6643521607848547683">"ایکسیسبیلٹی"</string>
<string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"آلہ کی اسٹوریج"</string>
- <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"USB ڈیبگ کرنا"</string>
+ <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"USB ڈیبگنگ"</string>
<string name="time_picker_hour_label" msgid="4208590187662336864">"گھنٹہ"</string>
<string name="time_picker_minute_label" msgid="8307452311269824553">"منٹ"</string>
<string name="time_picker_header_text" msgid="9073802285051516688">"وقت سیٹ کریں"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> کو آلے کے تمام لاگز تک رسائی کی اجازت دیں؟"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"یک وقتی رسائی کی اجازت دیں"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"اجازت نہ دیں"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"آپ کے آلے پر جو ہوتا ہے آلے کے لاگز اسے ریکارڈ کر لیتے ہیں۔ ایپس ان لاگز کا استعمال مسائل کو تلاش کرنے اور ان کو حل کرنے کے لیے کر سکتی ہیں۔\n\nکچھ لاگز میں حساس معلومات شامل ہو سکتی ہیں، اس لیے صرف اپنی بھروسے مند ایپس کو ہی آلے کے تمام لاگز تک رسائی کی اجازت دیں۔ \n\nاگر آپ اس ایپ کو آلے کے تمام لاگز تک رسائی کی اجازت نہیں دیتے ہیں تب بھی یہ اپنے لاگز تک رسائی حاصل کر سکتی ہے۔ آپ کے آلے کا مینوفیکچرر اب بھی آپ کے آلے پر کچھ لاگز یا معلومات تک رسائی حاصل کر سکتا ہے۔ مزید جانیں"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"آپ کے آلے پر جو ہوتا ہے آلے کے لاگز اسے ریکارڈ کر لیتے ہیں۔ ایپس ان لاگز کا استعمال مسائل کو تلاش کرنے اور ان کو حل کرنے کے لیے کر سکتی ہیں۔\n\nکچھ لاگز میں حساس معلومات شامل ہو سکتی ہیں، اس لیے صرف اپنے بھروسے مند ایپس کو ہی آلے کے تمام لاگز تک رسائی کی اجازت دیں۔ \n\nاگر آپ اس ایپ کو آلے کے تمام لاگز تک رسائی کی اجازت نہیں دیتے ہیں تب بھی یہ اپنے لاگز تک رسائی حاصل کر سکتی ہے۔ آپ کے آلے کا مینوفیکچرر اب بھی آپ کے آلے پر کچھ لاگز یا معلومات تک رسائی حاصل کر سکتا ہے۔"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"دوبارہ نہ دکھائیں"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> <xliff:g id="APP_2">%2$s</xliff:g> کے سلائسز دکھانا چاہتی ہے"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"ترمیم کریں"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"فعال ایپس چیک کریں"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"آپ کے <xliff:g id="DEVICE">%1$s</xliff:g> سے فون کے کیمرا تک رسائی حاصل نہیں کی جا سکتی"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"آپ کے <xliff:g id="DEVICE">%1$s</xliff:g> سے ٹیبلیٹ کے کیمرا تک رسائی حاصل نہیں کی جا سکتی"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"سلسلہ بندی کے دوران اس تک رسائی حاصل نہیں کی جا سکتی۔ اس کے بجائے اپنے فون پر کوشش کریں۔"</string>
<string name="system_locale_title" msgid="711882686834677268">"سسٹم ڈیفالٹ"</string>
</resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index e344ea5..a260f84 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Barmoq izi tekshiruvi bekor qilindi."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Barmoq izi amali foydalanuvchi tomonidan bekor qilindi"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Urinishlar soni ko‘payib ketdi. Keyinroq qayta urinib ko‘ring."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Urinishlar soni ko‘payib ketdi. Barmoq izi skaneri bloklandi."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Qayta urinib ko‘ring."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Hech qanday barmoq izi qayd qilinmagan."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Bu qurilmada barmoq izi skaneri mavjud emas."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> tayyorlanmoqda."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Ilovalar ishga tushirilmoqda."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Tizimni yuklashni tugatish."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Sozlashni davom ettirasizmi?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Quvvat tugmasini bosdingiz — bu odatda ekranni oʻchiradi.\n\nBarmoq izini qoʻshish vaqtida tugmaga yengilgina tegining."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Ekranni oʻchirish"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Sozlashni davom ettirish"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Ekranni oʻchirish uchun bosing"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Ekranni oʻchirish"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Barmoq izi tasdiqlashda davom etilsinmi?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Quvvat tugmasini bosdingiz. Bu odatda ekranni oʻchiradi.\n\nBarmoq izingizni tasdiqlash uchun tugmaga yengilgina tegining."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Ekranni oʻchirish"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Sozlash uchun bosing"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Sozlash uchun tanlang"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Qurilmani qayta formatlashingiz lozim. Chiqarib tashlash uchun bosing."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Rasm va boshqa fayllarni o‘tkazish"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Rasm, video, musiqa va boshqalarni saqlash uchun"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Media fayl tanlash"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> bilan muammo"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ishlamayapti"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Tuzatish uchun bosing"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g>: buzilgan. Tuzatish uchun uni tanlang."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Qurilmani qayta formatlashingiz lozim. Chiqarib tashlash uchun bosing."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> qo‘llab-quvvatlanmaydi"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> aniqlandi"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> ishlamayapti"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Bu xotira qurilmasi (<xliff:g id="NAME">%s</xliff:g>) qo‘llab-quvvatlanmaydi. Uni mos keladigan formatda sozlash uchun bu yerga bosing."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Sozlash uchun bosing"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Xotira qurilmasini (<xliff:g id="NAME">%s</xliff:g>) mos formatda sozlash uchun buni tanlang."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Qurilmani qayta formatlashingiz lozim"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> kutilmaganda chiqarib olindi"</string>
@@ -1425,10 +1425,10 @@
<string name="ext_media_unmounting_notification_message" msgid="5717036261538754203">"Chiqarib olinmasin"</string>
<string name="ext_media_init_action" msgid="2312974060585056709">"Sozlash"</string>
<string name="ext_media_unmount_action" msgid="966992232088442745">"Chiqarish"</string>
- <string name="ext_media_browse_action" msgid="344865351947079139">"O‘rganish"</string>
+ <string name="ext_media_browse_action" msgid="344865351947079139">"Ochish"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Audio chiqishni almashtirish"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> topilmadi"</string>
- <string name="ext_media_missing_message" msgid="4408988706227922909">"Qurilmani yana ulang"</string>
+ <string name="ext_media_missing_message" msgid="4408988706227922909">"Qurilmani qayta ulang"</string>
<string name="ext_media_move_specific_title" msgid="8492118544775964250">"<xliff:g id="NAME">%s</xliff:g> ko‘chirib o‘tkazilmoqda"</string>
<string name="ext_media_move_title" msgid="2682741525619033637">"Ma’lumotlar ko‘chirilmoqda"</string>
<string name="ext_media_move_success_title" msgid="4901763082647316767">"Kontent ko‘chirildi"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Hudud sozlamalari"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Til nomini kiriting"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Taklif etiladi"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Tavsiya etiladi"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Barcha tillar"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Barcha hududlar"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Qidiruv"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ilovasining qurilmadagi barcha jurnallarga kirishiga ruxsat berilsinmi?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Bir matalik foydalanishga ruxsat berish"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Rad etish"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Qurilma jurnaliga qurilma bilan yuz bergan hodisalar qaydlari yoziladi. Ilovalar bu jurnal qaydlari yordamida muammolarni topishi va bartaraf qilishi mumkin.\n\nAyrim jurnal qaydlarida maxfiy axborotlar yozilishi mumkin, shu sababli qurilmadagi barcha jurnal qaydlariga ruxsatni faqat ishonchli ilovalarga bering. \n\nBu ilovaga qurilmadagi barcha jurnal qaydlariga ruxsat berilmasa ham, u oʻzining jurnalini ocha oladi. Qurilma ishlab chiqaruvchisi ham ayrim jurnallar yoki qurilma haqidagi axborotlarni ocha oladi. Batafsil"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Qurilma jurnaliga qurilma bilan yuz bergan hodisalar qaydlari yoziladi. Ilovalar bu jurnal qaydlari yordamida muammolarni topishi va bartaraf qilishi mumkin.\n\nAyrim jurnal qaydlarida maxfiy axborotlar yozilishi mumkin, shu sababli qurilmadagi barcha jurnal qaydlariga ruxsatni faqat ishonchli ilovalarga bering. \n\nBu ilovaga qurilmadagi barcha jurnal qaydlariga ruxsat berilmasa ham, u oʻzining jurnalini ocha oladi. Qurilma ishlab chiqaruvchisi ham ayrim jurnallar yoki qurilma haqidagi axborotlarni ocha oladi."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Boshqa chiqmasin"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> ilovasi <xliff:g id="APP_2">%2$s</xliff:g> ilovasidan fragmentlar ko‘rsatish uchun ruxsat so‘ramoqda"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Tahrirlash"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Faol ilovalarni tekshiring"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> qurilmasidan telefonning kamerasiga kirish imkonsiz"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"<xliff:g id="DEVICE">%1$s</xliff:g> qurilmasidan planshetning kamerasiga kirish imkonsiz"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Bu kontent striming vaqtida ochilmaydi. Telefon orqali urininb koʻring."</string>
<string name="system_locale_title" msgid="711882686834677268">"Tizim standarti"</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 86ca67b..7d16667 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Thao tác dùng dấu vân tay bị hủy."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Người dùng đã hủy thao tác dùng dấu vân tay."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Quá nhiều lần thử. Hãy thử lại sau."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Quá nhiều lần thử. Cảm biến vân tay đã bị tắt."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Thử lại."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Chưa đăng ký vân tay."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Thiết bị này không có cảm biến vân tay."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Đang chuẩn bị <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Khởi động ứng dụng."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Hoàn tất khởi động."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Tiếp tục thiết lập?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Bạn đã nhấn nút nguồn – thao tác này thường tắt màn hình.\n\nHãy thử nhấn nhẹ khi thiết lập vân tay của bạn."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Tắt màn hình"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Tiếp tục thiết lập"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Nhấn để tắt màn hình"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Tắt màn hình"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Tiếp tục xác minh vân tay của bạn?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Bạn đã nhấn nút nguồn – thao tác này thường tắt màn hình.\n\nHãy thử nhấn nhẹ để xác minh vân tay."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Tắt màn hình"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Hãy nhấn để thiết lập"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Chọn để thiết lập"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Bạn có thể phải định dạng lại thiết bị. Nhấn để ngắt kết nối."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Để chuyển ảnh và phương tiện"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Để lưu trữ ảnh, video, nhạc và nhiều nội dung khác"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Duyệt xem các tệp nội dung nghe nhìn"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Vấn đề với <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> không hoạt động"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Hãy nhấn để sửa"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> bị lỗi. Chọn để sửa."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Bạn có thể phải định dạng lại thiết bị. Nhấn để ngắt kết nối."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> không được hỗ trợ"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"Đã phát hiện <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> không hoạt động"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Thiết bị này không hỗ trợ <xliff:g id="NAME">%s</xliff:g> này. Nhấn để thiết lập ở định dạng được hỗ trợ."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Nhấn để thiết lập."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Chọn để thiết lập <xliff:g id="NAME">%s</xliff:g> ở một định dạng được hỗ trợ."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Bạn có thể phải định dạng lại thiết bị"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Đã tháo đột ngột <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1424,7 +1424,7 @@
<string name="ext_media_unmounting_notification_title" msgid="4147986383917892162">"Đang ngắt kết nối <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmounting_notification_message" msgid="5717036261538754203">"Không tháo"</string>
<string name="ext_media_init_action" msgid="2312974060585056709">"Thiết lập"</string>
- <string name="ext_media_unmount_action" msgid="966992232088442745">"Tháo"</string>
+ <string name="ext_media_unmount_action" msgid="966992232088442745">"Ngắt kết nối"</string>
<string name="ext_media_browse_action" msgid="344865351947079139">"Khám phá"</string>
<string name="ext_media_seamless_action" msgid="8837030226009268080">"Chuyển đổi đầu ra"</string>
<string name="ext_media_missing_title" msgid="3209472091220515046">"<xliff:g id="NAME">%s</xliff:g> bị thiếu"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Tùy chọn khu vực"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Nhập tên ngôn ngữ"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Đề xuất"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Ðề xuất"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Tất cả ngôn ngữ"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Tất cả khu vực"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Tìm kiếm"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Cho phép <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> truy cập vào tất cả các nhật ký thiết bị?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Cho phép truy cập một lần"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Không cho phép"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Nhật ký thiết bị ghi lại những hoạt động diễn ra trên thiết bị. Các ứng dụng có thể dùng nhật ký này để tìm và khắc phục sự cố.\n\nMột số nhật ký có thể chứa thông tin nhạy cảm, vì vậy, bạn chỉ nên cấp quyền truy cập vào mọi nhật ký trên thiết bị cho những ứng dụng mà mình tin cậy. \n\nNếu bạn không cho phép ứng dụng này truy cập vào mọi nhật ký trên thiết bị, thì ứng dụng vẫn có thể truy cập vào nhật ký của chính nó. Nhà sản xuất thiết bị vẫn có thể truy cập vào một số nhật ký hoặc thông tin trên thiết bị của bạn. Tìm hiểu thêm"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Nhật ký thiết bị ghi lại những hoạt động diễn ra trên thiết bị. Các ứng dụng có thể dùng nhật ký này để tìm và khắc phục sự cố.\n\nMột số nhật ký có thể chứa thông tin nhạy cảm, vì vậy, bạn chỉ nên cấp quyền truy cập vào toàn bộ nhật ký thiết bị cho những ứng dụng mà mình tin cậy. \n\nNếu bạn không cho phép ứng dụng này truy cập vào toàn bộ nhật ký thiết bị, thì ứng dụng vẫn có thể truy cập vào nhật ký của chính nó. Nhà sản xuất thiết bị vẫn có thể truy cập vào một số nhật ký hoặc thông tin trên thiết bị của bạn."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Không hiện lại"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> muốn hiển thị các lát của <xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Chỉnh sửa"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Xem các ứng dụng đang hoạt động"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Không truy cập được vào máy ảnh trên điện thoại từ <xliff:g id="DEVICE">%1$s</xliff:g> của bạn"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Không truy cập được vào máy ảnh trên máy tính bảng từ <xliff:g id="DEVICE">%1$s</xliff:g> của bạn"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Bạn không thể truy cập vào nội dung này trong khi phát trực tuyến. Hãy thử trên điện thoại."</string>
<string name="system_locale_title" msgid="711882686834677268">"Theo chế độ mặc định của hệ thống"</string>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index b8c8198..169bdb3 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"指纹操作已取消。"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"用户取消了指纹操作。"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"尝试次数过多,请稍后重试。"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"尝试次数过多。指纹传感器已停用。"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"请重试。"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"未注册任何指纹。"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"此设备没有指纹传感器。"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"正在准备升级<xliff:g id="APPNAME">%1$s</xliff:g>。"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"正在启动应用。"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"即将完成启动。"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"要继续设置吗?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"您已按电源按钮,这通常会关闭屏幕。\n\n请尝试在设置指纹时轻轻按一下。"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"关闭屏幕"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"继续设置"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"按一下即可关闭屏幕"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"关闭屏幕"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"要继续验证您的指纹吗?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"您已按电源按钮,这通常会关闭屏幕。\n\n请尝试轻轻按一下来验证您的指纹。"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"关闭屏幕"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"点按即可进行设置"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"选择即可设置"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"您可能需要重新格式化设备。点按即可弹出。"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"可用于传输照片和媒体文件"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"用于存储照片、视频和音乐等"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"浏览媒体文件"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g>出现问题"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g>无法使用"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"点按即可修正问题"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g>已损坏。选择即可进行修正。"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"您可能需要重新格式化设备。点按即可弹出。"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g>不受支持"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"检测到<xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g>无法使用"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"该设备不支持此<xliff:g id="NAME">%s</xliff:g>。点按即可使用支持的格式进行设置。"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"点按即可设置。"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"选择即可使用支持的格式设置<xliff:g id="NAME">%s</xliff:g>。"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"您可能需要重新格式化设备"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>已意外移除"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"区域偏好设置"</string>
<string name="search_language_hint" msgid="7004225294308793583">"输入语言名称"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"建议语言"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"推荐地区"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"所有语言"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"所有国家/地区"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"搜索"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"允许“<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>”访问所有设备日志吗?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"允许访问一次"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"不允许"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"设备日志会记录设备上发生的活动。应用可以使用这些日志查找和修复问题。\n\n部分日志可能包含敏感信息,因此请仅允许您信任的应用访问所有设备日志。\n\n如果您不授予此应用访问所有设备日志的权限,它仍然可以访问自己的日志。您的设备制造商可能仍然能够访问您设备上的部分日志或信息。了解详情"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"设备日志会记录设备上发生的活动。应用可以使用这些日志查找和修复问题。\n\n部分日志可能包含敏感信息,因此请仅允许您信任的应用访问所有设备日志。\n\n如果您不授予此应用访问所有设备日志的权限,它仍然可以访问自己的日志。您的设备制造商可能仍然能够访问设备上的部分日志或信息。"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"不再显示"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"“<xliff:g id="APP_0">%1$s</xliff:g>”想要显示“<xliff:g id="APP_2">%2$s</xliff:g>”图块"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"编辑"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"查看使用中的应用"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"无法从<xliff:g id="DEVICE">%1$s</xliff:g>上访问手机的摄像头"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"无法从<xliff:g id="DEVICE">%1$s</xliff:g>上访问平板电脑的摄像头"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"流式传输时无法访问此内容。您可以尝试在手机上访问。"</string>
<string name="system_locale_title" msgid="711882686834677268">"系统默认设置"</string>
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 1727a46..eaa19d9 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"指紋操作已取消。"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"使用者已取消指紋操作。"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"嘗試次數過多,請稍後再試。"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"嘗試次數過多,指紋感應器已停用。"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"再試一次。"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"未註冊任何指紋"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"此裝置沒有指紋感應器。"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"正在準備 <xliff:g id="APPNAME">%1$s</xliff:g>。"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"正在啟動應用程式。"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"啟動完成。"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"要繼續設定嗎?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"您已按下開關按鈕,這麼做通常會關閉螢幕。\n\n設定指紋時請嘗試輕按開關按鈕。"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"關閉螢幕"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"繼續設定"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"輕按即可關閉螢幕"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"關閉螢幕"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"要繼續驗證指紋嗎?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"您已按下開關按鈕,這麼做通常會關閉螢幕。\n\n嘗試輕按開關按鈕以驗證指紋。"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"關閉螢幕"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"輕按即可設定"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"選取即可設定"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"您可能需要將裝置重新格式化。輕按即可退出。"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"用於轉移相片和媒體"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"用於儲存相片、影片、音樂等"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"瀏覽媒體檔案"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g>發生問題"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"「<xliff:g id="NAME">%s</xliff:g>」無法運作"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"輕按即可修正問題"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g>已損毀。選取即可修正。"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"您可能需要將裝置重新格式化。輕按即可退出。"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"不支援的 <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"已偵測到「<xliff:g id="NAME">%s</xliff:g>」"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"「<xliff:g id="NAME">%s</xliff:g>」無法運作"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"此裝置並不支援此 <xliff:g id="NAME">%s</xliff:g>。輕按即可在支援的格式設定。"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"輕按即可設定。"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"選取即可使用支援的格式設定 <xliff:g id="NAME">%s</xliff:g>。"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"您可能需要將裝置重新格式化"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>被意外移除"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"地區偏好設定"</string>
<string name="search_language_hint" msgid="7004225294308793583">"輸入語言名稱"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"建議"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"建議的語言"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"所有語言"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"所有國家/地區"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"搜尋"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"要允許「<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>」存取所有裝置記錄嗎?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"允許存取一次"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"不允許"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"裝置記錄記下裝置上的活動。應用程式可使用這些記錄找出並修正問題。\n\n有些記錄可能包含敏感資料,因此建議您只允許信任的應用程式存取所有裝置記錄。\n\n如果不允許此應用程式存取所有裝置記錄,此應用程式仍能存取自己的記錄。您的裝置製造商可能仍可存取裝置上的一些記錄或資料。瞭解詳情"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"裝置記錄會記下裝置上的活動。應用程式可透過這些記錄找出並修正問題。\n\n部分記錄可能包含敏感資料,因此請只允許信任的應用程式存取所有裝置記錄。\n\n如果不允許此應用程式存取所有裝置記錄,此應用程式仍能存取自己的記錄,且裝置製造商可能仍可存取裝置上的部分記錄或資料。"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"不要再顯示"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"「<xliff:g id="APP_0">%1$s</xliff:g>」想顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的快訊"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"編輯"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"查看使用中的應用程式"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"無法從 <xliff:g id="DEVICE">%1$s</xliff:g> 存取手機的相機"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"無法從 <xliff:g id="DEVICE">%1$s</xliff:g> 存取平板電腦的相機"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"串流播放時無法使用,請改用手機。"</string>
<string name="system_locale_title" msgid="711882686834677268">"系統預設"</string>
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 424ef62..753b4b6 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"指紋作業已取消。"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"使用者已取消指紋驗證作業。"</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"嘗試次數過多,請稍後再試。"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"嘗試次數過多,指紋感應器已停用。"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"請再試一次。"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"未登錄任何指紋。"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"這個裝置沒有指紋感應器。"</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"正在準備升級「<xliff:g id="APPNAME">%1$s</xliff:g>」。"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"正在啟動應用程式。"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"啟動完成。"</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"要繼續設定嗎?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"你已按下電源鍵,這麼做通常會關閉螢幕。\n\n設定指紋時請試著減輕觸碰電源鍵的力道。"</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"關閉螢幕"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"繼續設定"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"輕觸即可關閉螢幕"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"關閉螢幕"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"要繼續驗證指紋嗎?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"你已按下電源鍵,這麼做通常會關閉螢幕。\n\n驗證指紋時,請試著減輕觸碰電源鍵的力道。"</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"關閉螢幕"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"輕觸即可進行設定"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"選取即可設定"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"你可能要將裝置重新格式化。輕觸即可退出裝置。"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"可用於傳輸相片和媒體"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"用於儲存相片、影片、音樂等"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"瀏覽媒體檔案"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g>發生問題"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"「<xliff:g id="NAME">%s</xliff:g>」無法運作"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"輕觸即可修正問題"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g>已損毀。選取即可進行修正。"</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"你可能要將裝置重新格式化。輕觸即可退出裝置。"</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"不支援的「<xliff:g id="NAME">%s</xliff:g>」"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"偵測到「<xliff:g id="NAME">%s</xliff:g>」"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"「<xliff:g id="NAME">%s</xliff:g>」無法運作"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"此裝置不支援這個 <xliff:g id="NAME">%s</xliff:g>。輕觸即可使用支援的格式進行設定。"</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"輕觸即可設定。"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"選取即可使用支援的格式設定「<xliff:g id="NAME">%s</xliff:g>」。"</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"你可能要將裝置重新格式化"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"意外移除「<xliff:g id="NAME">%s</xliff:g>」"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"地區偏好設定"</string>
<string name="search_language_hint" msgid="7004225294308793583">"請輸入語言名稱"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"建議語言"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"建議的語言"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"所有語言"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"所有地區"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"搜尋"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"要允許「<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>」存取所有裝置記錄嗎?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"允許一次性存取"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"不允許"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"裝置記錄會記下裝置上的活動。應用程式可以根據這些記錄找出問題並進行修正。\n\n由於某些記錄可能含有機密資訊,建議只讓信任的應用程式存取所有裝置記錄。\n\n如果你不允許這個應用程式存取所有裝置記錄,這個應用程式仍可存取屬於自己的記錄,而裝置製造商也或許還是可以存取裝置的某些記錄或資訊。瞭解詳情"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"系統會透過裝置記錄記下裝置上的活動。應用程式可以根據這些記錄找出問題並進行修正。\n\n某些記錄可能含有機密資訊,因此請勿讓不信任的應用程式存取所有裝置記錄。\n\n即使你不允許這個應用程式存取所有裝置記錄,這個應用程式仍能存取自己的記錄,而且裝置製造商或許仍可存取裝置的某些記錄或資訊。"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"不要再顯示"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"「<xliff:g id="APP_0">%1$s</xliff:g>」想要顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的區塊"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"編輯"</string>
@@ -2286,9 +2287,10 @@
<string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"某個應用程式正在耗用大量電力"</string>
<string name="notification_title_long_running_fgs" msgid="8170284286477131587">"某個應用程式目前仍在運作"</string>
<string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"「<xliff:g id="APP">%1$s</xliff:g>」正在背景運作。輕觸即可管理電池用量。"</string>
- <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"「<xliff:g id="APP">%1$s</xliff:g>」應用程式可能會影響電池續航力。輕觸即可查看使用中的應用程式。"</string>
- <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"查看使用中的應用程式"</string>
+ <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"「<xliff:g id="APP">%1$s</xliff:g>」應用程式可能會影響電池續航力,輕觸即可查看運作中的應用程式。"</string>
+ <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"查看運作中的應用程式"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"無法從 <xliff:g id="DEVICE">%1$s</xliff:g> 存取手機的相機"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"無法從 <xliff:g id="DEVICE">%1$s</xliff:g> 存取平板電腦的相機"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"串流播放時無法存取這項內容,請改用手機。"</string>
<string name="system_locale_title" msgid="711882686834677268">"系統預設"</string>
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 6ce71c0..ac137fb 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -608,7 +608,8 @@
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Ukusebenza kwezigxivizo zeminwe kukhanseliwe."</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Umsebenzi wezigxivizo zomunwe ukhanselwe umsebenzisi."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Imizamo eminingi kakhulu. Zama futhi emuva kwesikhathi."</string>
- <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Imizamo eminingi kakhulu. Inzwa yezigxivizo zeminwe ikhutshaziwe."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Zama futhi."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Azikho izigxivizo zeminwe ezibhalisiwe."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Le divayisi ayinayo inzwa yezigxivizo zeminwe."</string>
@@ -1249,10 +1250,9 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Ukulungisela i-<xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Qalisa izinhlelo zokusebenza."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Qedela ukuqala kabusha."</string>
- <string name="fp_power_button_enrollment_title" msgid="3574363228413259548">"Qhubeka nokusetha?"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Ucindezele inkinobho yamandla — lokhu kuvame ukuvala isikrini.\n\nZama ukuthepha kancane ngenkathi usetha isigxivizo sakho somunwe."</string>
- <string name="fp_power_button_enrollment_positive_button" msgid="2095415838459356833">"Vala isikrini"</string>
- <string name="fp_power_button_enrollment_negative_button" msgid="6558436406362486747">"Qhubeka nokusetha"</string>
+ <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Thepha ukuze uvale isikrini"</string>
+ <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Vala isikrini"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"Qhubeka uqinisekise isigxivizo sakho somunwe?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Ucindezele inkinobho yamandla — lokhu kuvame ukuvala isikrini.\n\nZama ukuthepha kancane ukuze uqinisekise isigxivizo sakho somunwe."</string>
<string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Vala isikrini"</string>
@@ -1405,16 +1405,16 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Thepha ukuze usethe"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Khetha ukuze usethe"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Kungase kudingeke ukuthi ufomethe kabusha idivayisi. Thepha ukuze ukhiphe."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"Ukuze kudluliselwe izithombe nemidiya"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Isitoreji sezithombe, amavidiyo, umculo nokuningi"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Phequlula amafayela wemidiya"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Inkinga ngo-<xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"I-<xliff:g id="NAME">%s</xliff:g> ayisebenzi"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Thepha ukuze ulungise"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3003611129979934633">"<xliff:g id="NAME">%s</xliff:g> yonakele. Khetha ukulungisa."</string>
<string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Kungase kudingeke ukuthi ufomethe kabusha idivayisi. Thepha ukuze ukhiphe."</string>
- <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Akusekelwe <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"I-<xliff:g id="NAME">%s</xliff:g> itholiwe"</string>
<string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"I-<xliff:g id="NAME">%s</xliff:g> ayisebenzi"</string>
- <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Le divayisi ayisekeli le <xliff:g id="NAME">%s</xliff:g>. Thepha ukuze usethe ngefomethi esekelwayo."</string>
+ <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Thepha ukuze usethe ."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Khetha ukusetha i-<xliff:g id="NAME">%s</xliff:g> ngefomethi esekelwayo."</string>
<string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Kungase kudingeke ukuthi ufomethe kabusha idivayisi"</string>
<string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"I-<xliff:g id="NAME">%s</xliff:g> isuswe ngokungalindelekile"</string>
@@ -1927,6 +1927,7 @@
<string name="country_selection_title" msgid="5221495687299014379">"Okuncamelayo kwesifunda"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Thayipha igama lolimi"</string>
<string name="language_picker_section_suggested" msgid="6556199184638990447">"Okuphakanyisiwe"</string>
+ <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Okuphakanyisiwe"</string>
<string name="language_picker_section_all" msgid="1985809075777564284">"Zonke izilimi"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Zonke izifunda"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Sesha"</string>
@@ -2049,7 +2050,7 @@
<string name="log_access_confirmation_title" msgid="2343578467290592708">"Vumela i-<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ukuba ifinyelele wonke amalogu edivayisi?"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"Vumela ukufinyelela kwesikhathi esisodwa"</string>
<string name="log_access_confirmation_deny" msgid="7685790957455099845">"Ungavumeli"</string>
- <string name="log_access_confirmation_body" msgid="6581985716241928135">"Amalogu edivayisi arekhoda okwenzekayo kudivayisi yakho. Ama-app angasebenzisa lawa malogu ukuze athole futhi alungise izinkinga.\n\nAmanye amalogu angase aqukathe ulwazi olubucayi, ngakho vumela ama-app owathembayo kuphela ukuthi afinyelele wonke amalogu edivayisi. \n\nUma ungayivumeli le app ukuthi ifinyelele wonke amalogu wedivayisi, isengakwazi ukufinyelela amalogu wayo. Umkhiqizi wedivayisi yakho usengakwazi ukufinyelela amanye amalogu noma ulwazi kudivayisi yakho. Funda kabanzi"</string>
+ <string name="log_access_confirmation_body" msgid="1806692062668620735">"Amalogu edivayisi arekhoda okwenzekayo kudivayisi yakho. Ama-app angasebenzisa lawa malogu ukuze athole futhi alungise izinkinga.\n\nAmanye amalogu angase aqukathe ulwazi olubucayi, ngakho vumela ama-app owathembayo kuphela ukuthi afinyelele wonke amalogu edivayisi. \n\nUma ungayivumeli le app ukuthi ifinyelele wonke amalogu wedivayisi, isengakwazi ukufinyelela amalogu wayo. Umkhiqizi wedivayisi yakho usengakwazi ukufinyelela amanye amalogu noma ulwazi kudivayisi yakho."</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"Ungabonisi futhi"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"I-<xliff:g id="APP_0">%1$s</xliff:g> ifuna ukubonisa izingcezu ze-<xliff:g id="APP_2">%2$s</xliff:g>"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"Hlela"</string>
@@ -2290,5 +2291,6 @@
<string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Hlola ama-app asebenzayo"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Ayikwazi ukufinyelela ikhamera yefoni kusuka ku-<xliff:g id="DEVICE">%1$s</xliff:g> yakho"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Ayikwazi ukufinyelela ikhamera yethebulethi kusuka ku-<xliff:g id="DEVICE">%1$s</xliff:g> yakho"</string>
+ <string name="vdm_secure_window" msgid="161700398158812314">"Lokhu akukwazi ukufinyelelwa ngenkathi usakaza. Zama efonini yakho kunalokho."</string>
<string name="system_locale_title" msgid="711882686834677268">"Okuzenzakalelayo kwesistimu"</string>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 515ea50..004b5f6 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5484,22 +5484,22 @@
ignores some hyphen character related typographic features, e.g. kerning. -->
<enum name="fullFast" value="4" />
</attr>
- <!-- Indicates the line break strategies can be used when calculating the text wrapping. -->
+ <!-- Specifies the line-break strategies for text wrapping. -->
<attr name="lineBreakStyle">
- <!-- No line break style specific. -->
+ <!-- No line-break rules are used for line breaking. -->
<enum name="none" value="0" />
- <!-- Use the least restrictive rule for line-breaking. -->
+ <!-- The least restrictive line-break rules are used for line breaking. -->
<enum name="loose" value="1" />
- <!-- Indicates breaking text with the most comment set of line-breaking rules. -->
+ <!-- The most common line-break rules are used for line breaking. -->
<enum name="normal" value="2" />
- <!-- Indicates breaking text with the most strictest line-breaking rules. -->
+ <!-- The most strict line-break rules are used for line breaking. -->
<enum name="strict" value="3" />
</attr>
- <!-- Specify the phrase-based line break can be used when calculating the text wrapping.-->
+ <!-- Specifies the line-break word strategies for text wrapping.-->
<attr name="lineBreakWordStyle">
- <!-- No line break word style specific. -->
+ <!-- No line-break word style is used for line breaking. -->
<enum name="none" value="0" />
- <!-- Specify the phrase based breaking. -->
+ <!-- Line breaking is based on phrases, which results in text wrapping only on meaningful words. -->
<enum name="phrase" value="1" />
</attr>
<!-- Specify the type of auto-size. Note that this feature is not supported by EditText,
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1af80a5..483efd86c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -550,6 +550,9 @@
<!-- If this is true, long press on power button will be available from the non-interactive state -->
<bool name="config_supportLongPressPowerWhenNonInteractive">false</bool>
+ <!-- If this is true, then keep dreaming when undocking. -->
+ <bool name="config_keepDreamingWhenUndocking">false</bool>
+
<!-- Auto-rotation behavior -->
<!-- If true, enables auto-rotation features using the accelerometer.
@@ -932,6 +935,8 @@
<!-- Nominal White Z --> <item>1.089058</item>
</string-array>
+ <!-- Boolean indicating whether light mode is allowed when DWB is turned on. -->
+ <bool name="config_displayWhiteBalanceLightModeAllowed">true</bool>
<!-- Indicate available ColorDisplayManager.COLOR_MODE_xxx. -->
<integer-array name="config_availableColorModes">
@@ -2055,6 +2060,10 @@
<!-- The default volume for the ring stream -->
<integer name="config_audio_ring_vol_default">5</integer>
+ <!-- The default value for whether head tracking for
+ spatial audio is enabled for a newly connected audio device -->
+ <bool name="config_spatial_audio_head_tracking_enabled_default">false</bool>
+
<!-- Flag indicating whether platform level volume adjustments are enabled for remote sessions
on grouped devices. -->
<bool name="config_volumeAdjustmentForRemoteGroupSessions">true</bool>
@@ -2427,9 +2436,6 @@
<!-- The list of supported dream complications -->
<integer-array name="config_supportedDreamComplications">
</integer-array>
- <!-- The list of dream complications which should be enabled by default -->
- <integer-array name="config_dreamComplicationsEnabledByDefault">
- </integer-array>
<!-- Are we allowed to dream while not plugged in? -->
<bool name="config_dreamsEnabledOnBattery">false</bool>
@@ -3538,6 +3544,16 @@
automatically dismissing. This is currently used in SideFpsEventHandler -->
<integer name="config_sideFpsToastTimeout">3000</integer>
+ <!-- This acquired message will cause the sidefpsKgPowerPress window to be skipped.
+ If this is set to BIOMETRIC_ACQUIRED_VENDOR, then the framework will skip on
+ config_sidefpsSkipWaitForPowerVendorAcquireMessage -->
+ <integer name="config_sidefpsSkipWaitForPowerAcquireMessage">6</integer>
+
+ <!-- This vendor acquired message that will cause the sidefpsKgPowerPress window to be skipped.
+ config_sidefpsSkipWaitForPowerOnFingerUp must be true and
+ config_sidefpsSkipWaitForPowerAcquireMessage must be BIOMETRIC_ACQUIRED_VENDOR == 6. -->
+ <integer name="config_sidefpsSkipWaitForPowerVendorAcquireMessage">2</integer>
+
<!-- This config is used to force VoiceInteractionService to start on certain low ram devices.
It declares the package name of VoiceInteractionService that should be started. -->
<string translatable="false" name="config_forceVoiceInteractionServicePackage"></string>
@@ -4876,6 +4892,14 @@
<item>0.875</item>
</string-array>
+ <!-- When each intermediate SFPS enroll stage ends, as a fraction of total progress. -->
+ <string-array name="config_sfps_enroll_stage_thresholds" translatable="false">
+ <item>0</item> <!-- [-1 // <0/25] No animation 1x -->
+ <item>0.36</item> <!-- [0 to 8 // <9/25] Pad center 9x -->
+ <item>0.52</item> <!-- [9 to 12 // <13/25] Tip 4x -->
+ <item>0.76</item> <!-- [13 to 18 // <19/25] Left 6x -->
+ </string-array> <!-- [19 to 24 // <25/25] Right 6x -->
+
<!-- Messages that should not be shown to the user during face auth enrollment. This should be
used to hide messages that may be too chatty or messages that the user can't do much about.
Entries are defined in android.hardware.biometrics.face@1.0 types.hal -->
@@ -5083,6 +5107,10 @@
<!-- If true, the wallpaper will scale regardless of the value of shouldZoomOutWallpaper() -->
<bool name="config_alwaysScaleWallpaper">false</bool>
+ <!-- Set to true to offset the wallpaper when using multiple displays so that it's centered
+ at the same position as in the largest display.-->
+ <bool name="config_offsetWallpaperToCenterOfLargestDisplay">false</bool>
+
<!-- Package name that will receive an explicit manifest broadcast for
android.os.action.POWER_SAVE_MODE_CHANGED. -->
<string name="config_powerSaveModeChangedListenerPackage" translatable="false"></string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 17f0fd0..aad32b1 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1740,7 +1740,7 @@
<!-- Generic error message shown when the fingerprint operation fails because too many attempts have been made. -->
<string name="fingerprint_error_lockout">Too many attempts. Try again later.</string>
<!-- Generic error message shown when the fingerprint operation fails because strong authentication is required -->
- <string name="fingerprint_error_lockout_permanent">Too many attempts. Fingerprint sensor disabled.</string>
+ <string name="fingerprint_error_lockout_permanent">Too many attempts. Use screen lock instead.</string>
<!-- Generic error message shown when the fingerprint hardware can't recognize the fingerprint -->
<string name="fingerprint_error_unable_to_process">Try again.</string>
<!-- Generic error message shown when the user has no enrolled fingerprints -->
@@ -5429,8 +5429,10 @@
<!-- Hint text in a search edit box (used to filter long language / country lists) [CHAR LIMIT=25] -->
<string name="search_language_hint">Type language name</string>
- <!-- List section subheader for the language picker, containing a list of suggested languages determined by the default region [CHAR LIMIT=30] -->
+ <!-- List section subheader for the language picker, containing a list of suggested languages [CHAR LIMIT=30] -->
<string name="language_picker_section_suggested">Suggested</string>
+ <!-- "List section subheader for the language picker, containing a list of suggested regions available for that language [CHAR LIMIT=30] -->
+ <string name="language_picker_regions_section_suggested">Suggested</string>
<!-- List section subheader for the language picker, containing a list of all languages available [CHAR LIMIT=30] -->
<string name="language_picker_section_all">All languages</string>
<!-- List section subheader for the region picker, containing a list of all regions supported for the selected language.
@@ -5752,7 +5754,7 @@
<!-- Content for the log access confirmation dialog. [CHAR LIMIT=NONE]-->
<string name="log_access_confirmation_body">Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps you trust to access all device logs.
- \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device. Learn more
+ \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device.
</string>
<!-- Privacy notice do not show [CHAR LIMIT=20] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c098aca..71919ff 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -278,6 +278,7 @@
<java-symbol type="integer" name="config_audio_notif_vol_steps" />
<java-symbol type="integer" name="config_audio_ring_vol_default" />
<java-symbol type="integer" name="config_audio_ring_vol_steps" />
+ <java-symbol type="bool" name="config_spatial_audio_head_tracking_enabled_default" />
<java-symbol type="bool" name="config_avoidGfxAccel" />
<java-symbol type="bool" name="config_bluetooth_address_validation" />
<java-symbol type="integer" name="config_chooser_max_targets_per_row" />
@@ -1978,6 +1979,7 @@
<java-symbol type="bool" name="config_allowTheaterModeWakeFromLidSwitch" />
<java-symbol type="bool" name="config_allowTheaterModeWakeFromDock" />
<java-symbol type="bool" name="config_allowTheaterModeWakeFromWindowLayout" />
+ <java-symbol type="bool" name="config_keepDreamingWhenUndocking" />
<java-symbol type="bool" name="config_goToSleepOnButtonPressTheaterMode" />
<java-symbol type="bool" name="config_supportLongPressPowerWhenNonInteractive" />
<java-symbol type="bool" name="config_wimaxEnabled" />
@@ -2230,7 +2232,6 @@
<java-symbol type="string" name="config_dreamsDefaultComponent" />
<java-symbol type="bool" name="config_dreamsOnlyEnabledForSystemUser" />
<java-symbol type="array" name="config_supportedDreamComplications" />
- <java-symbol type="array" name="config_dreamComplicationsEnabledByDefault" />
<java-symbol type="array" name="config_disabledDreamComponents" />
<java-symbol type="bool" name="config_dismissDreamOnActivityStart" />
<java-symbol type="string" name="config_loggable_dream_prefix" />
@@ -2635,6 +2636,8 @@
<java-symbol type="integer" name="config_sidefpsKeyguardPowerPressWindow"/>
<java-symbol type="integer" name="config_sidefpsPostAuthDowntime"/>
<java-symbol type="integer" name="config_sideFpsToastTimeout"/>
+ <java-symbol type="integer" name="config_sidefpsSkipWaitForPowerAcquireMessage"/>
+ <java-symbol type="integer" name="config_sidefpsSkipWaitForPowerVendorAcquireMessage"/>
<!-- Clickable toast used during sidefps enrollment -->
<java-symbol type="layout" name="side_fps_toast" />
@@ -2700,7 +2703,7 @@
<java-symbol type="integer" name="config_udfps_illumination_transition_ms" />
<java-symbol type="bool" name="config_is_powerbutton_fps" />
<java-symbol type="array" name="config_udfps_enroll_stage_thresholds" />
-
+ <java-symbol type="array" name="config_sfps_enroll_stage_thresholds" />
<java-symbol type="array" name="config_face_acquire_enroll_ignorelist" />
<java-symbol type="array" name="config_face_acquire_vendor_enroll_ignorelist" />
<java-symbol type="array" name="config_face_acquire_keyguard_ignorelist" />
@@ -3135,6 +3138,7 @@
<java-symbol type="string" name="language_picker_section_all" />
<java-symbol type="string" name="region_picker_section_all" />
<java-symbol type="string" name="language_picker_section_suggested" />
+ <java-symbol type="string" name="language_picker_regions_section_suggested" />
<java-symbol type="string" name="language_selection_title" />
<java-symbol type="string" name="search_language_hint" />
@@ -3415,6 +3419,7 @@
<java-symbol type="integer" name="config_displayWhiteBalanceColorTemperatureDefault" />
<java-symbol type="array" name="config_displayWhiteBalanceDisplayPrimaries" />
<java-symbol type="array" name="config_displayWhiteBalanceDisplayNominalWhite" />
+ <java-symbol type="bool" name="config_displayWhiteBalanceLightModeAllowed" />
<!-- Default first user restrictions -->
<java-symbol type="array" name="config_defaultFirstUserRestrictions" />
@@ -4361,6 +4366,10 @@
<!-- The max scale for the wallpaper when it's zoomed in -->
<java-symbol type="dimen" name="config_wallpaperMaxScale"/>
+ <!-- Set to true to offset the wallpaper when using multiple displays so that it's centered
+ at the same position than in the largest display. -->
+ <java-symbol type="bool" name="config_offsetWallpaperToCenterOfLargestDisplay" />
+
<!-- Set to true to enable the user switcher on the keyguard. -->
<java-symbol type="bool" name="config_keyguardUserSwitcher" />
diff --git a/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java b/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
new file mode 100644
index 0000000..282fdad
--- /dev/null
+++ b/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.fail;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.google.common.base.Strings;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class AutomaticZenRuleTest {
+ private static final String CLASS = "android.app.AutomaticZenRule";
+
+ @Test
+ public void testLongFields_inConstructor() {
+ String longString = Strings.repeat("A", 65536);
+ Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
+
+ // test both variants where there's an owner, and where there's a configuration activity
+ AutomaticZenRule rule1 = new AutomaticZenRule(
+ longString, // name
+ new ComponentName("pkg", longString), // owner
+ null, // configuration activity
+ longUri, // conditionId
+ null, // zen policy
+ 0, // interruption filter
+ true); // enabled
+
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule1.getName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ rule1.getConditionId().toString().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule1.getOwner().getClassName().length());
+
+ AutomaticZenRule rule2 = new AutomaticZenRule(
+ longString, // name
+ null, // owner
+ new ComponentName(longString, "SomeClassName"), // configuration activity
+ longUri, // conditionId
+ null, // zen policy
+ 0, // interruption filter
+ false); // enabled
+
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule2.getName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ rule2.getConditionId().toString().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ rule2.getConfigurationActivity().getPackageName().length());
+ }
+
+ @Test
+ public void testLongFields_inSetters() {
+ String longString = Strings.repeat("A", 65536);
+ Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
+
+ AutomaticZenRule rule = new AutomaticZenRule(
+ "sensible name",
+ new ComponentName("pkg", "ShortClass"),
+ null,
+ Uri.parse("uri://short"),
+ null, 0, true);
+
+ rule.setName(longString);
+ rule.setConditionId(longUri);
+ rule.setConfigurationActivity(new ComponentName(longString, longString));
+
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule.getName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ rule.getConditionId().toString().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ rule.getConfigurationActivity().getPackageName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ rule.getConfigurationActivity().getClassName().length());
+ }
+
+ @Test
+ public void testLongInputsFromParcel() {
+ // Create a rule with long fields, set directly via reflection so that we can confirm that
+ // a rule with too-long fields that comes in via a parcel has its fields truncated directly.
+ AutomaticZenRule rule = new AutomaticZenRule(
+ "placeholder",
+ new ComponentName("place", "holder"),
+ null,
+ Uri.parse("uri://placeholder"),
+ null, 0, true);
+
+ try {
+ String longString = Strings.repeat("A", 65536);
+ Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
+ Field name = Class.forName(CLASS).getDeclaredField("name");
+ name.setAccessible(true);
+ name.set(rule, longString);
+ Field conditionId = Class.forName(CLASS).getDeclaredField("conditionId");
+ conditionId.setAccessible(true);
+ conditionId.set(rule, longUri);
+ Field owner = Class.forName(CLASS).getDeclaredField("owner");
+ owner.setAccessible(true);
+ owner.set(rule, new ComponentName(longString, longString));
+ Field configActivity = Class.forName(CLASS).getDeclaredField("configurationActivity");
+ configActivity.setAccessible(true);
+ configActivity.set(rule, new ComponentName(longString, longString));
+ } catch (NoSuchFieldException e) {
+ fail(e.toString());
+ } catch (ClassNotFoundException e) {
+ fail(e.toString());
+ } catch (IllegalAccessException e) {
+ fail(e.toString());
+ }
+
+ Parcel parcel = Parcel.obtain();
+ rule.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ AutomaticZenRule fromParcel = new AutomaticZenRule(parcel);
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, fromParcel.getName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ fromParcel.getConditionId().toString().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ fromParcel.getConfigurationActivity().getPackageName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ fromParcel.getConfigurationActivity().getClassName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ fromParcel.getOwner().getPackageName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ fromParcel.getOwner().getClassName().length());
+ }
+}
diff --git a/core/tests/coretests/src/android/os/BundleTest.java b/core/tests/coretests/src/android/os/BundleTest.java
index a3bda8b..0fa5ec3 100644
--- a/core/tests/coretests/src/android/os/BundleTest.java
+++ b/core/tests/coretests/src/android/os/BundleTest.java
@@ -409,6 +409,69 @@
}
@Test
+ public void readFromParcel_withLazyValues_copiesUnderlyingParcel() {
+ Bundle bundle = new Bundle();
+ Parcelable parcelable = new CustomParcelable(13, "Tiramisu");
+ bundle.putParcelable("key", parcelable);
+ bundle.putString("string", "value");
+ Parcel parcelledBundle = getParcelledBundle(bundle);
+
+ Bundle testBundle = new Bundle();
+ testBundle.setClassLoader(getClass().getClassLoader());
+ testBundle.readFromParcel(parcelledBundle);
+ // Recycle the parcel as it should have been copied
+ parcelledBundle.recycle();
+ assertThat(testBundle.getString("string")).isEqualTo("value");
+ assertThat(testBundle.<Parcelable>getParcelable("key")).isEqualTo(parcelable);
+ }
+
+ @Test
+ public void readFromParcelWithRwHelper_whenThrowingAndNotDefusing_throws() {
+ Bundle bundle = new Bundle();
+ Parcelable parcelable = new CustomParcelable(13, "Tiramisu");
+ bundle.putParcelable("key", parcelable);
+ bundle.putString("string", "value");
+ Parcel parcelledBundle = getParcelledBundle(bundle);
+ parcelledBundle.setReadWriteHelper(new Parcel.ReadWriteHelper());
+
+ Bundle testBundle = new Bundle();
+ assertThrows(BadParcelableException.class,
+ () -> testBundle.readFromParcel(parcelledBundle));
+ }
+
+ @Test
+ public void readFromParcelWithRwHelper_whenThrowingAndDefusing_returnsNull() {
+ Bundle bundle = new Bundle();
+ Parcelable parcelable = new CustomParcelable(13, "Tiramisu");
+ bundle.putParcelable("key", parcelable);
+ bundle.putString("string", "value");
+ Parcel parcelledBundle = getParcelledBundle(bundle);
+ parcelledBundle.setReadWriteHelper(new Parcel.ReadWriteHelper());
+
+ Bundle.setShouldDefuse(true);
+ Bundle testBundle = new Bundle();
+ testBundle.readFromParcel(parcelledBundle);
+ // Recycle the parcel as it should not be referenced
+ parcelledBundle.recycle();
+ assertThat(testBundle.getString("string")).isNull();
+ assertThat(testBundle.<Parcelable>getParcelable("key")).isNull();
+ }
+
+ @Test
+ public void readFromParcelWithRwHelper_withoutLazyObject_returnsValue() {
+ Bundle bundle = new Bundle();
+ bundle.putString("string", "value");
+ Parcel parcelledBundle = getParcelledBundle(bundle);
+ parcelledBundle.setReadWriteHelper(new Parcel.ReadWriteHelper());
+
+ Bundle testBundle = new Bundle();
+ testBundle.readFromParcel(parcelledBundle);
+ // Recycle the parcel as it should not be referenced
+ parcelledBundle.recycle();
+ assertThat(testBundle.getString("string")).isEqualTo("value");
+ }
+
+ @Test
public void partialDeserialization_whenNotDefusing_throws() throws Exception {
Bundle.setShouldDefuse(false);
Bundle bundle = getMalformedBundle();
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index 2054b4f..8cf118c 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -18,8 +18,10 @@
import static android.view.InsetsController.ANIMATION_TYPE_NONE;
import static android.view.InsetsController.ANIMATION_TYPE_USER;
+import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.statusBars;
import static junit.framework.Assert.assertEquals;
@@ -28,6 +30,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -75,6 +78,7 @@
private boolean mRemoveSurfaceCalled = false;
private InsetsController mController;
private InsetsState mState;
+ private ViewRootImpl mViewRoot;
@Before
public void setup() {
@@ -86,10 +90,9 @@
instrumentation.runOnMainSync(() -> {
final Context context = instrumentation.getTargetContext();
// cannot mock ViewRootImpl since it's final.
- final ViewRootImpl viewRootImpl = new ViewRootImpl(context,
- context.getDisplayNoVerify());
+ mViewRoot = new ViewRootImpl(context, context.getDisplayNoVerify());
try {
- viewRootImpl.setView(new TextView(context), new LayoutParams(), null);
+ mViewRoot.setView(new TextView(context), new LayoutParams(), null);
} catch (BadTokenException e) {
// activity isn't running, lets ignore BadTokenException.
}
@@ -97,7 +100,7 @@
mSpyInsetsSource = Mockito.spy(new InsetsSource(ITYPE_STATUS_BAR));
mState.addSource(mSpyInsetsSource);
- mController = new InsetsController(new ViewRootInsetsControllerHost(viewRootImpl));
+ mController = new InsetsController(new ViewRootInsetsControllerHost(mViewRoot));
mConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, mState,
() -> mMockTransaction, mController) {
@Override
@@ -207,4 +210,40 @@
});
}
+
+ @Test
+ public void testWontUpdateImeLeashVisibility_whenAnimation() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ InsetsState state = new InsetsState();
+ ViewRootInsetsControllerHost host = new ViewRootInsetsControllerHost(mViewRoot);
+ InsetsController insetsController = new InsetsController(host, (controller, type) -> {
+ if (type == ITYPE_IME) {
+ return new InsetsSourceConsumer(ITYPE_IME, state,
+ () -> mMockTransaction, controller) {
+ @Override
+ public int requestShow(boolean fromController) {
+ return SHOW_IMMEDIATELY;
+ }
+ };
+ }
+ return new InsetsSourceConsumer(type, controller.getState(), Transaction::new,
+ controller);
+ }, host.getHandler());
+ InsetsSourceConsumer imeConsumer = insetsController.getSourceConsumer(ITYPE_IME);
+
+ // Initial IME insets source control with its leash.
+ imeConsumer.setControl(new InsetsSourceControl(ITYPE_IME, mLeash,
+ false /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1]);
+ reset(mMockTransaction);
+
+ // Verify when the app requests controlling show IME animation, the IME leash
+ // visibility won't be updated when the consumer received the same leash in setControl.
+ insetsController.controlWindowInsetsAnimation(ime(), 0L,
+ null /* interpolator */, null /* cancellationSignal */, null /* listener */);
+ assertTrue(insetsController.getAnimationType(ITYPE_IME) == ANIMATION_TYPE_USER);
+ imeConsumer.setControl(new InsetsSourceControl(ITYPE_IME, mLeash,
+ true /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1]);
+ verify(mMockTransaction, never()).show(mLeash);
+ });
+ }
}
diff --git a/core/tests/coretests/src/android/window/BackNavigationTest.java b/core/tests/coretests/src/android/window/BackNavigationTest.java
index bbbc423..77d61d5 100644
--- a/core/tests/coretests/src/android/window/BackNavigationTest.java
+++ b/core/tests/coretests/src/android/window/BackNavigationTest.java
@@ -92,7 +92,7 @@
try {
mInstrumentation.getUiAutomation().waitForIdle(500, 1000);
BackNavigationInfo info = ActivityTaskManager.getService()
- .startBackNavigation(true, null);
+ .startBackNavigation(true, null, null);
assertNotNull("BackNavigationInfo is null", info);
assertNotNull("OnBackInvokedCallback is null", info.getOnBackInvokedCallback());
info.getOnBackInvokedCallback().onBackInvoked();
diff --git a/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java b/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
index 0cee526..271a20b 100644
--- a/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
@@ -17,6 +17,8 @@
package com.android.internal.widget;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
@@ -279,4 +281,49 @@
// This drawable must not be loaded - if it was, the code ignored the package specification.
assertThat(d).isNull();
}
+
+ @Test
+ public void resolveResourcesForIcon_notAResourceIcon_returnsNull() {
+ Icon icon = Icon.createWithContentUri(Uri.parse("some_uri"));
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon)).isNull();
+ }
+
+ @Test
+ public void resolveResourcesForIcon_localPackageIcon_returnsPackageResources() {
+ Icon icon = Icon.createWithResource(mContext, R.drawable.test32x24);
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon))
+ .isSameInstanceAs(mContext.getResources());
+ }
+
+ @Test
+ public void resolveResourcesForIcon_iconWithoutPackageSpecificed_returnsPackageResources() {
+ Icon icon = Icon.createWithResource("", R.drawable.test32x24);
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon))
+ .isSameInstanceAs(mContext.getResources());
+ }
+
+ @Test
+ public void resolveResourcesForIcon_systemPackageSpecified_returnsSystemPackage() {
+ Icon icon = Icon.createWithResource("android", R.drawable.test32x24);
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon)).isSameInstanceAs(
+ Resources.getSystem());
+ }
+
+ @Test
+ public void resolveResourcesForIcon_differentPackageSpecified_returnsPackageResources() throws
+ PackageManager.NameNotFoundException {
+ String pkg = "com.android.settings";
+ Resources res = mContext.getPackageManager().getResourcesForApplication(pkg);
+ int resId = res.getIdentifier("ic_android", "drawable", pkg);
+ Icon icon = Icon.createWithResource(pkg, resId);
+
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon).getDrawable(resId,
+ mContext.getTheme())).isNotNull();
+ }
+
+ @Test
+ public void resolveResourcesForIcon_invalidPackageSpecified_returnsNull() {
+ Icon icon = Icon.createWithResource("invalid.package", R.drawable.test32x24);
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon)).isNull();
+ }
}
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index f030d80..e0e13f5 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -81,5 +81,6 @@
<permission name="android.permission.READ_DEVICE_CONFIG" />
<permission name="android.permission.READ_SAFETY_CENTER_STATUS" />
<permission name="android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS" />
+ <permission name="android.permission.READ_SEARCH_INDEXABLES" />
</privapp-permissions>
</permissions>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 6897c01..9a1b8a9 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -171,10 +171,11 @@
<assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="audioserver" />
<assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="audioserver" />
<assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="audioserver" />
- <assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="audioserver" />
+ <assign-permission name="android.permission.INTERACT_ACROSS_USERS_FULL" uid="audioserver" />
<assign-permission name="android.permission.OBSERVE_SENSOR_PRIVACY" uid="audioserver" />
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="cameraserver" />
+ <assign-permission name="android.permission.INTERACT_ACROSS_USERS_FULL" uid="cameraserver" />
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="cameraserver" />
<assign-permission name="android.permission.WAKE_LOCK" uid="cameraserver" />
<assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="cameraserver" />
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 49767844..f6499f8 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1,12 +1,6 @@
{
"version": "1.0.0",
"messages": {
- "-2146181682": {
- "message": "Releasing screen wakelock, obscured by %s",
- "level": "DEBUG",
- "group": "WM_DEBUG_KEEP_SCREEN_ON",
- "at": "com\/android\/server\/wm\/WindowManagerService.java"
- },
"-2127842445": {
"message": "Clearing startingData for token=%s",
"level": "VERBOSE",
@@ -1759,6 +1753,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-384639879": {
+ "message": "Acquiring screen wakelock due to %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_KEEP_SCREEN_ON",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"-381522987": {
"message": "Display %d state is now (%d), so update recording?",
"level": "VERBOSE",
@@ -1801,6 +1801,12 @@
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
"at": "com\/android\/server\/wm\/Transition.java"
},
+ "-353495930": {
+ "message": "TaskFragmentTransaction changes are not collected in transition because there is an ongoing sync for applySyncTransaction().",
+ "level": "WARN",
+ "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/WindowOrganizerController.java"
+ },
"-347866078": {
"message": "Setting move animation on %s",
"level": "VERBOSE",
@@ -2041,12 +2047,6 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
- "-108248992": {
- "message": "Defer transition ready for TaskFragmentTransaction=%s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_WINDOW_TRANSITIONS",
- "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
- },
"-106400104": {
"message": "Preload recents with %s",
"level": "DEBUG",
@@ -2095,12 +2095,6 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/TaskFragment.java"
},
- "-79016993": {
- "message": "Continue transition ready for TaskFragmentTransaction=%s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_WINDOW_TRANSITIONS",
- "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
- },
"-70719599": {
"message": "Unregister remote animations for organizer=%s uid=%d pid=%d",
"level": "VERBOSE",
@@ -2377,6 +2371,12 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "191486492": {
+ "message": "handleNotObscuredLocked: %s was holding screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_KEEP_SCREEN_ON",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"200829729": {
"message": "ScreenRotationAnimation onAnimationEnd",
"level": "DEBUG",
@@ -2497,6 +2497,12 @@
"group": "WM_DEBUG_ANIM",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "286170861": {
+ "message": "Creating Pending Transition for TaskFragment: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/WindowOrganizerController.java"
+ },
"288485303": {
"message": "Attempted to set remove mode to a display that does not exist: %d",
"level": "WARN",
@@ -2647,6 +2653,12 @@
"group": "WM_DEBUG_ANIM",
"at": "com\/android\/server\/wm\/WindowContainer.java"
},
+ "390947100": {
+ "message": "Screenshotting %s [%s]",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/Transition.java"
+ },
"397382873": {
"message": "Moving to PAUSED: %s %s",
"level": "VERBOSE",
@@ -3037,6 +3049,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "782864973": {
+ "message": "Releasing screen wakelock, obscured by %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_KEEP_SCREEN_ON",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"791468751": {
"message": "Pausing rotation during re-position",
"level": "DEBUG",
@@ -3079,6 +3097,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
+ "851368695": {
+ "message": "Deferred transition id=%d has been continued before the TaskFragmentTransaction=%s is finished",
+ "level": "WARN",
+ "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
+ },
"872933199": {
"message": "Changing focus from %s to %s displayId=%d Callers=%s",
"level": "DEBUG",
@@ -3271,6 +3295,12 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "1046228706": {
+ "message": "Defer transition id=%d for TaskFragmentTransaction=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
+ },
"1046922686": {
"message": "requestScrollCapture: caught exception dispatching callback: %s",
"level": "WARN",
@@ -3313,6 +3343,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
},
+ "1075460705": {
+ "message": "Continue transition id=%d for TaskFragmentTransaction=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
+ },
"1087494661": {
"message": "Clear window stuck on animatingExit status: %s",
"level": "WARN",
@@ -4171,6 +4207,12 @@
"group": "WM_DEBUG_FOCUS_LIGHT",
"at": "com\/android\/server\/wm\/InputMonitor.java"
},
+ "2004282287": {
+ "message": "Override sync-method for %s because seamless rotating",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/Transition.java"
+ },
"2010476671": {
"message": "Animation done in %s: reportedVisible=%b okToDisplay=%b okToAnimate=%b startingDisplayed=%b",
"level": "VERBOSE",
@@ -4267,18 +4309,6 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "2088592090": {
- "message": "handleNotObscuredLocked: %s was holding screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by%s",
- "level": "DEBUG",
- "group": "WM_DEBUG_KEEP_SCREEN_ON",
- "at": "com\/android\/server\/wm\/RootWindowContainer.java"
- },
- "2096635066": {
- "message": "Acquiring screen wakelock due to %s",
- "level": "DEBUG",
- "group": "WM_DEBUG_KEEP_SCREEN_ON",
- "at": "com\/android\/server\/wm\/WindowManagerService.java"
- },
"2100457473": {
"message": "Task=%d contains embedded TaskFragment. Disabled all input during TaskFragment remote animation.",
"level": "DEBUG",
diff --git a/data/keyboards/Vendor_054c_Product_0ce6.kl b/data/keyboards/Vendor_054c_Product_0ce6.kl
index 4d51a9e..411dd95 100644
--- a/data/keyboards/Vendor_054c_Product_0ce6.kl
+++ b/data/keyboards/Vendor_054c_Product_0ce6.kl
@@ -16,6 +16,8 @@
# Sony Playstation(R) DualSense Controller
#
+# Only use this key layout if we have HID_PLAYSTATION!
+requires_kernel_config CONFIG_HID_PLAYSTATION
# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
diff --git a/data/keyboards/Vendor_054c_Product_0ce6_fallback.kl b/data/keyboards/Vendor_054c_Product_0ce6_fallback.kl
new file mode 100644
index 0000000..d1a364c
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0ce6_fallback.kl
@@ -0,0 +1,75 @@
+# Copyright (C) 2022 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Sony Playstation(R) DualSense Controller
+#
+
+# Use this if HID_PLAYSTATION is not available
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 304 BUTTON_X
+# Cross
+key 305 BUTTON_A
+# Circle
+key 306 BUTTON_B
+# Triangle
+key 307 BUTTON_Y
+
+key 308 BUTTON_L1
+key 309 BUTTON_R1
+key 310 BUTTON_L2
+key 311 BUTTON_R2
+
+# L2 axis
+axis 0x03 LTRIGGER
+# R2 axis
+axis 0x04 RTRIGGER
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+# Right Analog Stick
+axis 0x02 Z
+axis 0x05 RZ
+
+# Left stick click
+key 314 BUTTON_THUMBL
+# Right stick click
+key 315 BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share / "half-sun"
+key 312 BUTTON_SELECT
+# Options / three horizontal lines
+key 313 BUTTON_START
+# PS key
+key 316 BUTTON_MODE
+
+# Touchpad press
+key 317 BUTTON_1
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/ktfmt_includes.txt b/ktfmt_includes.txt
deleted file mode 100644
index 96da8c9..0000000
--- a/ktfmt_includes.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-packages/SystemUI/compose/
-packages/SystemUI/screenshot/
-packages/SystemUI/src/com/android/systemui/people/data
-packages/SystemUI/src/com/android/systemui/people/ui
-packages/SystemUI/src/com/android/systemui/keyguard/data
-packages/SystemUI/src/com/android/systemui/keyguard/dagger
-packages/SystemUI/src/com/android/systemui/keyguard/domain
-packages/SystemUI/src/com/android/systemui/keyguard/shared
-packages/SystemUI/src/com/android/systemui/keyguard/ui
\ No newline at end of file
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
index 1335e5e..febd791 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -21,7 +21,6 @@
import android.app.Activity;
import android.app.WindowConfiguration.WindowingMode;
import android.content.Intent;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
@@ -29,6 +28,7 @@
import android.window.TaskFragmentCreationParams;
import android.window.TaskFragmentInfo;
import android.window.TaskFragmentOrganizer;
+import android.window.TaskFragmentTransaction;
import android.window.WindowContainerTransaction;
import androidx.annotation.NonNull;
@@ -62,18 +62,7 @@
* Callback that notifies the controller about changes to task fragments.
*/
interface TaskFragmentCallback {
- void onTaskFragmentAppeared(@NonNull WindowContainerTransaction wct,
- @NonNull TaskFragmentInfo taskFragmentInfo);
- void onTaskFragmentInfoChanged(@NonNull WindowContainerTransaction wct,
- @NonNull TaskFragmentInfo taskFragmentInfo);
- void onTaskFragmentVanished(@NonNull WindowContainerTransaction wct,
- @NonNull TaskFragmentInfo taskFragmentInfo);
- void onTaskFragmentParentInfoChanged(@NonNull WindowContainerTransaction wct,
- int taskId, @NonNull Configuration parentConfig);
- void onActivityReparentedToTask(@NonNull WindowContainerTransaction wct,
- int taskId, @NonNull Intent activityIntent, @NonNull IBinder activityToken);
- void onTaskFragmentError(@NonNull WindowContainerTransaction wct,
- @Nullable TaskFragmentInfo taskFragmentInfo, int opType);
+ void onTransactionReady(@NonNull TaskFragmentTransaction transaction);
}
/**
@@ -270,50 +259,16 @@
wct.deleteTaskFragment(mFragmentInfos.get(fragmentToken).getToken());
}
- @Override
- public void onTaskFragmentAppeared(@NonNull WindowContainerTransaction wct,
- @NonNull TaskFragmentInfo taskFragmentInfo) {
- final IBinder fragmentToken = taskFragmentInfo.getFragmentToken();
- mFragmentInfos.put(fragmentToken, taskFragmentInfo);
- mCallback.onTaskFragmentAppeared(wct, taskFragmentInfo);
+ void updateTaskFragmentInfo(@NonNull TaskFragmentInfo taskFragmentInfo) {
+ mFragmentInfos.put(taskFragmentInfo.getFragmentToken(), taskFragmentInfo);
}
- @Override
- public void onTaskFragmentInfoChanged(@NonNull WindowContainerTransaction wct,
- @NonNull TaskFragmentInfo taskFragmentInfo) {
- final IBinder fragmentToken = taskFragmentInfo.getFragmentToken();
- mFragmentInfos.put(fragmentToken, taskFragmentInfo);
- mCallback.onTaskFragmentInfoChanged(wct, taskFragmentInfo);
- }
-
- @Override
- public void onTaskFragmentVanished(@NonNull WindowContainerTransaction wct,
- @NonNull TaskFragmentInfo taskFragmentInfo) {
+ void removeTaskFragmentInfo(@NonNull TaskFragmentInfo taskFragmentInfo) {
mFragmentInfos.remove(taskFragmentInfo.getFragmentToken());
- mCallback.onTaskFragmentVanished(wct, taskFragmentInfo);
}
@Override
- public void onTaskFragmentParentInfoChanged(@NonNull WindowContainerTransaction wct,
- int taskId, @NonNull Configuration parentConfig) {
- mCallback.onTaskFragmentParentInfoChanged(wct, taskId, parentConfig);
- }
-
- @Override
- public void onActivityReparentedToTask(@NonNull WindowContainerTransaction wct,
- int taskId, @NonNull Intent activityIntent, @NonNull IBinder activityToken) {
- mCallback.onActivityReparentedToTask(wct, taskId, activityIntent, activityToken);
- }
-
- @Override
- public void onTaskFragmentError(@NonNull WindowContainerTransaction wct,
- @NonNull IBinder errorCallbackToken,
- @Nullable TaskFragmentInfo taskFragmentInfo,
- int opType, @NonNull Throwable exception) {
- if (taskFragmentInfo != null) {
- final IBinder fragmentToken = taskFragmentInfo.getFragmentToken();
- mFragmentInfos.put(fragmentToken, taskFragmentInfo);
- }
- mCallback.onTaskFragmentError(wct, taskFragmentInfo, opType);
+ public void onTransactionReady(@NonNull TaskFragmentTransaction transaction) {
+ mCallback.onTransactionReady(transaction);
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 0597809f..724a50f 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -19,6 +19,16 @@
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_OP_TYPE;
+import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO;
+import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_THROWABLE;
+import static android.window.TaskFragmentOrganizer.getTransitionType;
+import static android.window.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENTED_TO_TASK;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_ERROR;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_INFO_CHANGED;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_VANISHED;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT;
@@ -53,6 +63,7 @@
import android.util.Size;
import android.util.SparseArray;
import android.window.TaskFragmentInfo;
+import android.window.TaskFragmentTransaction;
import android.window.WindowContainerTransaction;
import androidx.annotation.GuardedBy;
@@ -99,7 +110,7 @@
private Consumer<List<SplitInfo>> mEmbeddingCallback;
private final List<SplitInfo> mLastReportedSplitStates = new ArrayList<>();
private final Handler mHandler;
- private final Object mLock = new Object();
+ final Object mLock = new Object();
private final ActivityStartMonitor mActivityStartMonitor;
public SplitController() {
@@ -144,203 +155,323 @@
}
}
+ /**
+ * Called when the transaction is ready so that the organizer can update the TaskFragments based
+ * on the changes in transaction.
+ */
@Override
- public void onTaskFragmentAppeared(@NonNull WindowContainerTransaction wct,
- @NonNull TaskFragmentInfo taskFragmentInfo) {
+ public void onTransactionReady(@NonNull TaskFragmentTransaction transaction) {
synchronized (mLock) {
- TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
- if (container == null) {
- return;
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
+ for (TaskFragmentTransaction.Change change : changes) {
+ final int taskId = change.getTaskId();
+ final TaskFragmentInfo info = change.getTaskFragmentInfo();
+ switch (change.getType()) {
+ case TYPE_TASK_FRAGMENT_APPEARED:
+ mPresenter.updateTaskFragmentInfo(info);
+ onTaskFragmentAppeared(wct, info);
+ break;
+ case TYPE_TASK_FRAGMENT_INFO_CHANGED:
+ mPresenter.updateTaskFragmentInfo(info);
+ onTaskFragmentInfoChanged(wct, info);
+ break;
+ case TYPE_TASK_FRAGMENT_VANISHED:
+ mPresenter.removeTaskFragmentInfo(info);
+ onTaskFragmentVanished(wct, info);
+ break;
+ case TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED:
+ onTaskFragmentParentInfoChanged(wct, taskId, change.getTaskConfiguration());
+ break;
+ case TYPE_TASK_FRAGMENT_ERROR:
+ final Bundle errorBundle = change.getErrorBundle();
+ final IBinder errorToken = change.getErrorCallbackToken();
+ final TaskFragmentInfo errorTaskFragmentInfo = errorBundle.getParcelable(
+ KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO, TaskFragmentInfo.class);
+ final int opType = errorBundle.getInt(KEY_ERROR_CALLBACK_OP_TYPE);
+ final Throwable exception = errorBundle.getSerializable(
+ KEY_ERROR_CALLBACK_THROWABLE, Throwable.class);
+ if (errorTaskFragmentInfo != null) {
+ mPresenter.updateTaskFragmentInfo(errorTaskFragmentInfo);
+ }
+ onTaskFragmentError(wct, errorToken, errorTaskFragmentInfo, opType,
+ exception);
+ break;
+ case TYPE_ACTIVITY_REPARENTED_TO_TASK:
+ onActivityReparentedToTask(
+ wct,
+ taskId,
+ change.getActivityIntent(),
+ change.getActivityToken());
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Unknown TaskFragmentEvent=" + change.getType());
+ }
}
- container.setInfo(wct, taskFragmentInfo);
- if (container.isFinished()) {
- mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
- } else {
- // Update with the latest Task configuration.
- updateContainer(wct, container);
- }
+ // Notify the server, and the server should apply and merge the
+ // WindowContainerTransaction to the active sync to finish the TaskFragmentTransaction.
+ mPresenter.onTransactionHandled(transaction.getTransactionToken(), wct,
+ getTransitionType(wct), false /* shouldApplyIndependently */);
updateCallbackIfNecessary();
}
}
- @Override
- public void onTaskFragmentInfoChanged(@NonNull WindowContainerTransaction wct,
+ /**
+ * Called when a TaskFragment is created and organized by this organizer.
+ *
+ * @param wct The {@link WindowContainerTransaction} to make any changes with if needed.
+ * @param taskFragmentInfo Info of the TaskFragment that is created.
+ */
+ // Suppress GuardedBy warning because lint ask to mark this method as
+ // @GuardedBy(container.mController.mLock), which is mLock itself
+ @SuppressWarnings("GuardedBy")
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ void onTaskFragmentAppeared(@NonNull WindowContainerTransaction wct,
@NonNull TaskFragmentInfo taskFragmentInfo) {
- synchronized (mLock) {
- TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
- if (container == null) {
- return;
- }
+ final TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
+ if (container == null) {
+ return;
+ }
- final boolean wasInPip = isInPictureInPicture(container);
- container.setInfo(wct, taskFragmentInfo);
- final boolean isInPip = isInPictureInPicture(container);
- // Check if there are no running activities - consider the container empty if there are
- // no non-finishing activities left.
- if (!taskFragmentInfo.hasRunningActivity()) {
- if (taskFragmentInfo.isTaskFragmentClearedForPip()) {
- // Do not finish the dependents if the last activity is reparented to PiP.
- // Instead, the original split should be cleanup, and the dependent may be
- // expanded to fullscreen.
- cleanupForEnterPip(wct, container);
- mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
- } else if (taskFragmentInfo.isTaskClearedForReuse()) {
- // Do not finish the dependents if this TaskFragment was cleared due to
- // launching activity in the Task.
- mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
- } else if (!container.isWaitingActivityAppear()) {
- // Do not finish the container before the expected activity appear until
- // timeout.
- mPresenter.cleanupContainer(wct, container, true /* shouldFinishDependent */);
- }
- } else if (wasInPip && isInPip) {
- // No update until exit PIP.
- return;
- } else if (isInPip) {
- // Enter PIP.
- // All overrides will be cleanup.
- container.setLastRequestedBounds(null /* bounds */);
- container.setLastRequestedWindowingMode(WINDOWING_MODE_UNDEFINED);
+ container.setInfo(wct, taskFragmentInfo);
+ if (container.isFinished()) {
+ mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
+ } else {
+ // Update with the latest Task configuration.
+ updateContainer(wct, container);
+ }
+ }
+
+ /**
+ * Called when the status of an organized TaskFragment is changed.
+ *
+ * @param wct The {@link WindowContainerTransaction} to make any changes with if needed.
+ * @param taskFragmentInfo Info of the TaskFragment that is changed.
+ */
+ // Suppress GuardedBy warning because lint ask to mark this method as
+ // @GuardedBy(container.mController.mLock), which is mLock itself
+ @SuppressWarnings("GuardedBy")
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ void onTaskFragmentInfoChanged(@NonNull WindowContainerTransaction wct,
+ @NonNull TaskFragmentInfo taskFragmentInfo) {
+ final TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
+ if (container == null) {
+ return;
+ }
+
+ final boolean wasInPip = isInPictureInPicture(container);
+ container.setInfo(wct, taskFragmentInfo);
+ final boolean isInPip = isInPictureInPicture(container);
+ // Check if there are no running activities - consider the container empty if there are
+ // no non-finishing activities left.
+ if (!taskFragmentInfo.hasRunningActivity()) {
+ if (taskFragmentInfo.isTaskFragmentClearedForPip()) {
+ // Do not finish the dependents if the last activity is reparented to PiP.
+ // Instead, the original split should be cleanup, and the dependent may be
+ // expanded to fullscreen.
cleanupForEnterPip(wct, container);
- } else if (wasInPip) {
- // Exit PIP.
- // Updates the presentation of the container. Expand or launch placeholder if
- // needed.
+ mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
+ } else if (taskFragmentInfo.isTaskClearedForReuse()) {
+ // Do not finish the dependents if this TaskFragment was cleared due to
+ // launching activity in the Task.
+ mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
+ } else if (!container.isWaitingActivityAppear()) {
+ // Do not finish the container before the expected activity appear until
+ // timeout.
+ mPresenter.cleanupContainer(wct, container, true /* shouldFinishDependent */);
+ }
+ } else if (wasInPip && isInPip) {
+ // No update until exit PIP.
+ return;
+ } else if (isInPip) {
+ // Enter PIP.
+ // All overrides will be cleanup.
+ container.setLastRequestedBounds(null /* bounds */);
+ container.setLastRequestedWindowingMode(WINDOWING_MODE_UNDEFINED);
+ cleanupForEnterPip(wct, container);
+ } else if (wasInPip) {
+ // Exit PIP.
+ // Updates the presentation of the container. Expand or launch placeholder if
+ // needed.
+ updateContainer(wct, container);
+ }
+ }
+
+ /**
+ * Called when an organized TaskFragment is removed.
+ *
+ * @param wct The {@link WindowContainerTransaction} to make any changes with if needed.
+ * @param taskFragmentInfo Info of the TaskFragment that is removed.
+ */
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ void onTaskFragmentVanished(@NonNull WindowContainerTransaction wct,
+ @NonNull TaskFragmentInfo taskFragmentInfo) {
+ final TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
+ if (container != null) {
+ // Cleanup if the TaskFragment vanished is not requested by the organizer.
+ removeContainer(container);
+ // Make sure the top container is updated.
+ final TaskFragmentContainer newTopContainer = getTopActiveContainer(
+ container.getTaskId());
+ if (newTopContainer != null) {
+ updateContainer(wct, newTopContainer);
+ }
+ }
+ cleanupTaskFragment(taskFragmentInfo.getFragmentToken());
+ }
+
+ /**
+ * Called when the parent leaf Task of organized TaskFragments is changed.
+ * When the leaf Task is changed, the organizer may want to update the TaskFragments in one
+ * transaction.
+ *
+ * For case like screen size change, it will trigger {@link #onTaskFragmentParentInfoChanged}
+ * with new Task bounds, but may not trigger {@link #onTaskFragmentInfoChanged} because there
+ * can be an override bounds.
+ *
+ * @param wct The {@link WindowContainerTransaction} to make any changes with if needed.
+ * @param taskId Id of the parent Task that is changed.
+ * @param parentConfig Config of the parent Task.
+ */
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ void onTaskFragmentParentInfoChanged(@NonNull WindowContainerTransaction wct,
+ int taskId, @NonNull Configuration parentConfig) {
+ onTaskConfigurationChanged(taskId, parentConfig);
+ if (isInPictureInPicture(parentConfig)) {
+ // No need to update presentation in PIP until the Task exit PIP.
+ return;
+ }
+ final TaskContainer taskContainer = getTaskContainer(taskId);
+ if (taskContainer == null || taskContainer.isEmpty()) {
+ Log.e(TAG, "onTaskFragmentParentInfoChanged on empty Task id=" + taskId);
+ return;
+ }
+ // Update all TaskFragments in the Task. Make a copy of the list since some may be
+ // removed on updating.
+ final List<TaskFragmentContainer> containers =
+ new ArrayList<>(taskContainer.mContainers);
+ for (int i = containers.size() - 1; i >= 0; i--) {
+ final TaskFragmentContainer container = containers.get(i);
+ // Wait until onTaskFragmentAppeared to update new container.
+ if (!container.isFinished() && !container.isWaitingActivityAppear()) {
updateContainer(wct, container);
}
- updateCallbackIfNecessary();
}
}
- @Override
- public void onTaskFragmentVanished(@NonNull WindowContainerTransaction wct,
- @NonNull TaskFragmentInfo taskFragmentInfo) {
- synchronized (mLock) {
- final TaskFragmentContainer container = getContainer(
- taskFragmentInfo.getFragmentToken());
- if (container != null) {
- // Cleanup if the TaskFragment vanished is not requested by the organizer.
- removeContainer(container);
- // Make sure the top container is updated.
- final TaskFragmentContainer newTopContainer = getTopActiveContainer(
- container.getTaskId());
- if (newTopContainer != null) {
- updateContainer(wct, newTopContainer);
- }
- updateCallbackIfNecessary();
- }
- cleanupTaskFragment(taskFragmentInfo.getFragmentToken());
- }
- }
-
- @Override
- public void onTaskFragmentParentInfoChanged(@NonNull WindowContainerTransaction wct,
- int taskId, @NonNull Configuration parentConfig) {
- synchronized (mLock) {
- onTaskConfigurationChanged(taskId, parentConfig);
- if (isInPictureInPicture(parentConfig)) {
- // No need to update presentation in PIP until the Task exit PIP.
- return;
- }
- final TaskContainer taskContainer = getTaskContainer(taskId);
- if (taskContainer == null || taskContainer.isEmpty()) {
- Log.e(TAG, "onTaskFragmentParentInfoChanged on empty Task id=" + taskId);
- return;
- }
- // Update all TaskFragments in the Task. Make a copy of the list since some may be
- // removed on updating.
- final List<TaskFragmentContainer> containers =
- new ArrayList<>(taskContainer.mContainers);
- for (int i = containers.size() - 1; i >= 0; i--) {
- final TaskFragmentContainer container = containers.get(i);
- // Wait until onTaskFragmentAppeared to update new container.
- if (!container.isFinished() && !container.isWaitingActivityAppear()) {
- updateContainer(wct, container);
- }
- }
- updateCallbackIfNecessary();
- }
- }
-
- @Override
- public void onActivityReparentedToTask(@NonNull WindowContainerTransaction wct,
+ /**
+ * Called when an Activity is reparented to the Task with organized TaskFragment. For example,
+ * when an Activity enters and then exits Picture-in-picture, it will be reparented back to its
+ * original Task. In this case, we need to notify the organizer so that it can check if the
+ * Activity matches any split rule.
+ *
+ * @param wct The {@link WindowContainerTransaction} to make any changes with if needed.
+ * @param taskId The Task that the activity is reparented to.
+ * @param activityIntent The intent that the activity is original launched with.
+ * @param activityToken If the activity belongs to the same process as the organizer, this
+ * will be the actual activity token; if the activity belongs to a
+ * different process, the server will generate a temporary token that
+ * the organizer can use to reparent the activity through
+ * {@link WindowContainerTransaction} if needed.
+ */
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ void onActivityReparentedToTask(@NonNull WindowContainerTransaction wct,
int taskId, @NonNull Intent activityIntent,
@NonNull IBinder activityToken) {
- synchronized (mLock) {
- // If the activity belongs to the current app process, we treat it as a new activity
- // launch.
- final Activity activity = getActivity(activityToken);
- if (activity != null) {
- // We don't allow split as primary for new launch because we currently only support
- // launching to top. We allow split as primary for activity reparent because the
- // activity may be split as primary before it is reparented out. In that case, we
- // want to show it as primary again when it is reparented back.
- if (!resolveActivityToContainer(wct, activity, true /* isOnReparent */)) {
- // When there is no embedding rule matched, try to place it in the top container
- // like a normal launch.
- placeActivityInTopContainer(wct, activity);
- }
- updateCallbackIfNecessary();
- return;
- }
-
- final TaskContainer taskContainer = getTaskContainer(taskId);
- if (taskContainer == null || taskContainer.isInPictureInPicture()) {
- // We don't embed activity when it is in PIP.
- return;
- }
-
- // If the activity belongs to a different app process, we treat it as starting new
- // intent, since both actions might result in a new activity that should appear in an
- // organized TaskFragment.
- TaskFragmentContainer targetContainer = resolveStartActivityIntent(wct, taskId,
- activityIntent, null /* launchingActivity */);
- if (targetContainer == null) {
+ // If the activity belongs to the current app process, we treat it as a new activity
+ // launch.
+ final Activity activity = getActivity(activityToken);
+ if (activity != null) {
+ // We don't allow split as primary for new launch because we currently only support
+ // launching to top. We allow split as primary for activity reparent because the
+ // activity may be split as primary before it is reparented out. In that case, we
+ // want to show it as primary again when it is reparented back.
+ if (!resolveActivityToContainer(wct, activity, true /* isOnReparent */)) {
// When there is no embedding rule matched, try to place it in the top container
// like a normal launch.
- targetContainer = taskContainer.getTopTaskFragmentContainer();
+ placeActivityInTopContainer(wct, activity);
}
- if (targetContainer == null) {
- return;
- }
- wct.reparentActivityToTaskFragment(targetContainer.getTaskFragmentToken(),
- activityToken);
- // Because the activity does not belong to the organizer process, we wait until
- // onTaskFragmentAppeared to trigger updateCallbackIfNecessary().
+ return;
}
+
+ final TaskContainer taskContainer = getTaskContainer(taskId);
+ if (taskContainer == null || taskContainer.isInPictureInPicture()) {
+ // We don't embed activity when it is in PIP.
+ return;
+ }
+
+ // If the activity belongs to a different app process, we treat it as starting new
+ // intent, since both actions might result in a new activity that should appear in an
+ // organized TaskFragment.
+ TaskFragmentContainer targetContainer = resolveStartActivityIntent(wct, taskId,
+ activityIntent, null /* launchingActivity */);
+ if (targetContainer == null) {
+ // When there is no embedding rule matched, try to place it in the top container
+ // like a normal launch.
+ targetContainer = taskContainer.getTopTaskFragmentContainer();
+ }
+ if (targetContainer == null) {
+ return;
+ }
+ wct.reparentActivityToTaskFragment(targetContainer.getTaskFragmentToken(),
+ activityToken);
+ // Because the activity does not belong to the organizer process, we wait until
+ // onTaskFragmentAppeared to trigger updateCallbackIfNecessary().
}
- @Override
- public void onTaskFragmentError(@NonNull WindowContainerTransaction wct,
- @Nullable TaskFragmentInfo taskFragmentInfo, int opType) {
- synchronized (mLock) {
- switch (opType) {
- case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT:
- case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT: {
- final TaskFragmentContainer container;
- if (taskFragmentInfo != null) {
- container = getContainer(taskFragmentInfo.getFragmentToken());
- } else {
- container = null;
- }
- if (container == null) {
- break;
- }
-
- // Update the latest taskFragmentInfo and perform necessary clean-up
- container.setInfo(wct, taskFragmentInfo);
- container.clearPendingAppearedActivities();
- if (container.isEmpty()) {
- mPresenter.cleanupContainer(wct, container,
- false /* shouldFinishDependent */);
- }
+ /**
+ * Called when the {@link WindowContainerTransaction} created with
+ * {@link WindowContainerTransaction#setErrorCallbackToken(IBinder)} failed on the server side.
+ *
+ * @param wct The {@link WindowContainerTransaction} to make any changes with if needed.
+ * @param errorCallbackToken token set in
+ * {@link WindowContainerTransaction#setErrorCallbackToken(IBinder)}
+ * @param taskFragmentInfo The {@link TaskFragmentInfo}. This could be {@code null} if no
+ * TaskFragment created.
+ * @param opType The {@link WindowContainerTransaction.HierarchyOp} of the failed
+ * transaction operation.
+ * @param exception exception from the server side.
+ */
+ // Suppress GuardedBy warning because lint ask to mark this method as
+ // @GuardedBy(container.mController.mLock), which is mLock itself
+ @SuppressWarnings("GuardedBy")
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ void onTaskFragmentError(@NonNull WindowContainerTransaction wct,
+ @Nullable IBinder errorCallbackToken, @Nullable TaskFragmentInfo taskFragmentInfo,
+ int opType, @NonNull Throwable exception) {
+ Log.e(TAG, "onTaskFragmentError=" + exception.getMessage());
+ switch (opType) {
+ case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT:
+ case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT: {
+ final TaskFragmentContainer container;
+ if (taskFragmentInfo != null) {
+ container = getContainer(taskFragmentInfo.getFragmentToken());
+ } else {
+ container = null;
+ }
+ if (container == null) {
break;
}
- default:
- Log.e(TAG, "onTaskFragmentError: taskFragmentInfo = " + taskFragmentInfo
- + ", opType = " + opType);
+
+ // Update the latest taskFragmentInfo and perform necessary clean-up
+ container.setInfo(wct, taskFragmentInfo);
+ container.clearPendingAppearedActivities();
+ if (container.isEmpty()) {
+ mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
+ }
+ break;
}
+ default:
+ Log.e(TAG, "onTaskFragmentError: taskFragmentInfo = " + taskFragmentInfo
+ + ", opType = " + opType);
}
}
@@ -452,7 +583,7 @@
}
if (!isOnReparent && getContainerWithActivity(activity) == null
- && getInitialTaskFragmentToken(activity) != null) {
+ && getTaskFragmentTokenFromActivityClientRecord(activity) != null) {
// We can't find the new launched activity in any recorded container, but it is
// currently placed in an embedded TaskFragment. This can happen in two cases:
// 1. the activity is embedded in another app.
@@ -673,6 +804,9 @@
* Checks if there is a rule to split the two activities. If there is one, puts them into split
* and returns {@code true}. Otherwise, returns {@code false}.
*/
+ // Suppress GuardedBy warning because lint ask to mark this method as
+ // @GuardedBy(mPresenter.mController.mLock), which is mLock itself
+ @SuppressWarnings("GuardedBy")
@GuardedBy("mLock")
private boolean putActivitiesIntoSplitIfNecessary(@NonNull WindowContainerTransaction wct,
@NonNull Activity primaryActivity, @NonNull Activity secondaryActivity) {
@@ -732,11 +866,12 @@
}
@VisibleForTesting
+ @GuardedBy("mLock")
void onActivityDestroyed(@NonNull Activity activity) {
// Remove any pending appeared activity, as the server won't send finished activity to the
// organizer.
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
- mTaskContainers.valueAt(i).cleanupPendingAppearedActivity(activity);
+ mTaskContainers.valueAt(i).onActivityDestroyed(activity);
}
// We didn't trigger the callback if there were any pending appeared activities, so check
// again after the pending is removed.
@@ -747,23 +882,23 @@
* Called when we have been waiting too long for the TaskFragment to become non-empty after
* creation.
*/
+ @GuardedBy("mLock")
void onTaskFragmentAppearEmptyTimeout(@NonNull TaskFragmentContainer container) {
- synchronized (mLock) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- onTaskFragmentAppearEmptyTimeout(wct, container);
- mPresenter.applyTransaction(wct);
- }
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ onTaskFragmentAppearEmptyTimeout(wct, container);
+ // Can be applied independently as a timeout callback.
+ mPresenter.applyTransaction(wct, getTransitionType(wct),
+ true /* shouldApplyIndependently */);
}
/**
* Called when we have been waiting too long for the TaskFragment to become non-empty after
* creation.
*/
+ @GuardedBy("mLock")
void onTaskFragmentAppearEmptyTimeout(@NonNull WindowContainerTransaction wct,
@NonNull TaskFragmentContainer container) {
- synchronized (mLock) {
- mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
- }
+ mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
}
/**
@@ -1471,15 +1606,16 @@
}
/**
- * Gets the token of the initial TaskFragment that embedded this activity. Do not rely on it
- * after creation because the activity could be reparented.
+ * Gets the token of the TaskFragment that embedded this activity. It is available as soon as
+ * the activity is created and attached, so it can be used during {@link #onActivityCreated}
+ * before the server notifies the organizer to avoid racing condition.
*/
@VisibleForTesting
@Nullable
- IBinder getInitialTaskFragmentToken(@NonNull Activity activity) {
+ IBinder getTaskFragmentTokenFromActivityClientRecord(@NonNull Activity activity) {
final ActivityThread.ActivityClientRecord record = ActivityThread.currentActivityThread()
.getActivityClient(activity.getActivityToken());
- return record != null ? record.mInitialTaskFragmentToken : null;
+ return record != null ? record.mTaskFragmentToken : null;
}
/**
@@ -1557,7 +1693,8 @@
@Nullable Bundle savedInstanceState) {
synchronized (mLock) {
final IBinder activityToken = activity.getActivityToken();
- final IBinder initialTaskFragmentToken = getInitialTaskFragmentToken(activity);
+ final IBinder initialTaskFragmentToken =
+ getTaskFragmentTokenFromActivityClientRecord(activity);
// If the activity is not embedded, then it will not have an initial task fragment
// token so no further action is needed.
if (initialTaskFragmentToken == null) {
@@ -1592,7 +1729,9 @@
synchronized (mLock) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
SplitController.this.onActivityCreated(wct, activity);
- mPresenter.applyTransaction(wct);
+ // The WCT should be applied and merged to the activity launch transition.
+ mPresenter.applyTransaction(wct, getTransitionType(wct),
+ false /* shouldApplyIndependently */);
}
}
@@ -1601,7 +1740,10 @@
synchronized (mLock) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
SplitController.this.onActivityConfigurationChanged(wct, activity);
- mPresenter.applyTransaction(wct);
+ // The WCT should be applied and merged to the Task change transition so that the
+ // placeholder is launched in the same transition.
+ mPresenter.applyTransaction(wct, getTransitionType(wct),
+ false /* shouldApplyIndependently */);
}
}
@@ -1653,7 +1795,10 @@
final TaskFragmentContainer launchedInTaskFragment = resolveStartActivityIntent(wct,
taskId, intent, launchingActivity);
if (launchedInTaskFragment != null) {
- mPresenter.applyTransaction(wct);
+ // Make sure the WCT is applied immediately instead of being queued so that the
+ // TaskFragment will be ready before activity attachment.
+ mPresenter.applyTransaction(wct, getTransitionType(wct),
+ false /* shouldApplyIndependently */);
// Amend the request to let the WM know that the activity should be placed in
// the dedicated container.
options.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN,
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 2b069d7..2ef8e4c 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -38,6 +38,7 @@
import android.view.WindowMetrics;
import android.window.WindowContainerTransaction;
+import androidx.annotation.GuardedBy;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -171,6 +172,7 @@
* created and the activity will be re-parented to it.
* @param rule The split rule to be applied to the container.
*/
+ @GuardedBy("mController.mLock")
void createNewSplitContainer(@NonNull WindowContainerTransaction wct,
@NonNull Activity primaryActivity, @NonNull Activity secondaryActivity,
@NonNull SplitPairRule rule) {
@@ -187,8 +189,10 @@
final TaskFragmentContainer curSecondaryContainer = mController.getContainerWithActivity(
secondaryActivity);
TaskFragmentContainer containerToAvoid = primaryContainer;
- if (rule.shouldClearTop() && curSecondaryContainer != null) {
- // Do not reuse the current TaskFragment if the rule is to clear top.
+ if (curSecondaryContainer != null
+ && (rule.shouldClearTop() || primaryContainer.isAbove(curSecondaryContainer))) {
+ // Do not reuse the current TaskFragment if the rule is to clear top, or if it is below
+ // the primary TaskFragment.
containerToAvoid = curSecondaryContainer;
}
final TaskFragmentContainer secondaryContainer = prepareContainerForActivity(wct,
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 77e26c0..b563677 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -137,6 +137,13 @@
return mContainers.isEmpty() && mFinishedContainer.isEmpty();
}
+ /** Called when the activity is destroyed. */
+ void onActivityDestroyed(@NonNull Activity activity) {
+ for (TaskFragmentContainer container : mContainers) {
+ container.onActivityDestroyed(activity);
+ }
+ }
+
/** Removes the pending appeared activity from all TaskFragments in this Task. */
void cleanupPendingAppearedActivity(@NonNull Activity pendingAppearedActivity) {
for (TaskFragmentContainer container : mContainers) {
@@ -162,4 +169,8 @@
}
return null;
}
+
+ int indexOf(@NonNull TaskFragmentContainer child) {
+ return mContainers.indexOf(child);
+ }
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index 11c0db3..626e0d9 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.app.Activity;
+import android.app.ActivityThread;
import android.app.WindowConfiguration.WindowingMode;
import android.content.Intent;
import android.graphics.Rect;
@@ -28,6 +29,7 @@
import android.window.TaskFragmentInfo;
import android.window.WindowContainerTransaction;
+import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -189,6 +191,19 @@
// Remove the pending activity from other TaskFragments.
mTaskContainer.cleanupPendingAppearedActivity(pendingAppearedActivity);
mPendingAppearedActivities.add(pendingAppearedActivity);
+ updateActivityClientRecordTaskFragmentToken(pendingAppearedActivity);
+ }
+
+ /**
+ * Updates the {@link ActivityThread.ActivityClientRecord#mTaskFragmentToken} for the
+ * activity. This makes sure the token is up-to-date if the activity is relaunched later.
+ */
+ private void updateActivityClientRecordTaskFragmentToken(@NonNull Activity activity) {
+ final ActivityThread.ActivityClientRecord record = ActivityThread
+ .currentActivityThread().getActivityClient(activity.getActivityToken());
+ if (record != null) {
+ record.mTaskFragmentToken = mToken;
+ }
}
void removePendingAppearedActivity(@NonNull Activity pendingAppearedActivity) {
@@ -196,8 +211,29 @@
}
void clearPendingAppearedActivities() {
+ final List<Activity> cleanupActivities = new ArrayList<>(mPendingAppearedActivities);
+ // Clear mPendingAppearedActivities so that #getContainerWithActivity won't return the
+ // current TaskFragment.
mPendingAppearedActivities.clear();
mPendingAppearedIntent = null;
+
+ // For removed pending activities, we need to update the them to their previous containers.
+ for (Activity activity : cleanupActivities) {
+ final TaskFragmentContainer curContainer = mController.getContainerWithActivity(
+ activity);
+ if (curContainer != null) {
+ curContainer.updateActivityClientRecordTaskFragmentToken(activity);
+ }
+ }
+ }
+
+ /** Called when the activity is destroyed. */
+ void onActivityDestroyed(@NonNull Activity activity) {
+ removePendingAppearedActivity(activity);
+ if (mInfo != null) {
+ // Remove the activity now because there can be a delay before the server callback.
+ mInfo.getActivities().remove(activity.getActivityToken());
+ }
}
@Nullable
@@ -251,6 +287,7 @@
return mInfo;
}
+ @GuardedBy("mController.mLock")
void setInfo(@NonNull WindowContainerTransaction wct, @NonNull TaskFragmentInfo info) {
if (!mIsFinished && mInfo == null && info.isEmpty()) {
// onTaskFragmentAppeared with empty info. We will remove the TaskFragment if no
@@ -258,10 +295,12 @@
// it is still empty after timeout.
if (mPendingAppearedIntent != null || !mPendingAppearedActivities.isEmpty()) {
mAppearEmptyTimeout = () -> {
- mAppearEmptyTimeout = null;
- // Call without the pass-in wct when timeout. We need to applyWct directly
- // in this case.
- mController.onTaskFragmentAppearEmptyTimeout(this);
+ synchronized (mController.mLock) {
+ mAppearEmptyTimeout = null;
+ // Call without the pass-in wct when timeout. We need to applyWct directly
+ // in this case.
+ mController.onTaskFragmentAppearEmptyTimeout(this);
+ }
};
mController.getHandler().postDelayed(mAppearEmptyTimeout, APPEAR_EMPTY_TIMEOUT_MS);
} else {
@@ -501,6 +540,18 @@
return new Size(maxMinWidth, maxMinHeight);
}
+ /** Whether the current TaskFragment is above the {@code other} TaskFragment. */
+ boolean isAbove(@NonNull TaskFragmentContainer other) {
+ if (mTaskContainer != other.mTaskContainer) {
+ throw new IllegalArgumentException(
+ "Trying to compare two TaskFragments in different Task.");
+ }
+ if (this == other) {
+ throw new IllegalArgumentException("Trying to compare a TaskFragment with itself.");
+ }
+ return mTaskContainer.indexOf(this) > mTaskContainer.indexOf(other);
+ }
+
@Override
public String toString() {
return toString(true /* includeContainersToFinishOnExit */);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index 6bfb16a..f24401f 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -20,21 +20,26 @@
import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_FLAT;
import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_HALF_OPENED;
+import static androidx.window.util.ExtensionHelper.isZero;
import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation;
import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect;
-import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityClient;
import android.app.Application;
import android.app.WindowConfiguration;
+import android.content.ComponentCallbacks;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
import android.util.ArrayMap;
+import android.window.WindowContext;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiContext;
import androidx.window.common.CommonFoldingFeature;
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
@@ -58,11 +63,14 @@
public class WindowLayoutComponentImpl implements WindowLayoutComponent {
private static final String TAG = "SampleExtension";
- private final Map<Activity, Consumer<WindowLayoutInfo>> mWindowLayoutChangeListeners =
+ private final Map<Context, Consumer<WindowLayoutInfo>> mWindowLayoutChangeListeners =
new ArrayMap<>();
private final DataProducer<List<CommonFoldingFeature>> mFoldingFeatureProducer;
+ private final Map<IBinder, WindowContextConfigListener> mWindowContextConfigListeners =
+ new ArrayMap<>();
+
public WindowLayoutComponentImpl(@NonNull Context context) {
((Application) context.getApplicationContext())
.registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged());
@@ -78,14 +86,42 @@
* @param activity hosting a {@link android.view.Window}
* @param consumer interested in receiving updates to {@link WindowLayoutInfo}
*/
+ @Override
public void addWindowLayoutInfoListener(@NonNull Activity activity,
@NonNull Consumer<WindowLayoutInfo> consumer) {
+ addWindowLayoutInfoListener((Context) activity, consumer);
+ }
+
+ /**
+ * Similar to {@link #addWindowLayoutInfoListener(Activity, Consumer)}, but takes a UI Context
+ * as a parameter.
+ */
+ // TODO(b/204073440): Add @Override to hook the API in WM extensions library.
+ public void addWindowLayoutInfoListener(@NonNull @UiContext Context context,
+ @NonNull Consumer<WindowLayoutInfo> consumer) {
+ if (mWindowLayoutChangeListeners.containsKey(context)
+ || mWindowLayoutChangeListeners.containsValue(consumer)) {
+ // Early return if the listener or consumer has been registered.
+ return;
+ }
+ if (!context.isUiContext()) {
+ throw new IllegalArgumentException("Context must be a UI Context, which should be"
+ + " an Activity or a WindowContext");
+ }
mFoldingFeatureProducer.getData((features) -> {
// Get the WindowLayoutInfo from the activity and pass the value to the layoutConsumer.
- WindowLayoutInfo newWindowLayout = getWindowLayoutInfo(activity, features);
+ WindowLayoutInfo newWindowLayout = getWindowLayoutInfo(context, features);
consumer.accept(newWindowLayout);
});
- mWindowLayoutChangeListeners.put(activity, consumer);
+ mWindowLayoutChangeListeners.put(context, consumer);
+
+ if (context instanceof WindowContext) {
+ final IBinder windowContextToken = context.getWindowContextToken();
+ final WindowContextConfigListener listener =
+ new WindowContextConfigListener(windowContextToken);
+ context.registerComponentCallbacks(listener);
+ mWindowContextConfigListeners.put(windowContextToken, listener);
+ }
}
/**
@@ -93,18 +129,30 @@
*
* @param consumer no longer interested in receiving updates to {@link WindowLayoutInfo}
*/
+ @Override
public void removeWindowLayoutInfoListener(@NonNull Consumer<WindowLayoutInfo> consumer) {
+ for (Context context : mWindowLayoutChangeListeners.keySet()) {
+ if (!mWindowLayoutChangeListeners.get(context).equals(consumer)) {
+ continue;
+ }
+ if (context instanceof WindowContext) {
+ final IBinder token = context.getWindowContextToken();
+ context.unregisterComponentCallbacks(mWindowContextConfigListeners.get(token));
+ mWindowContextConfigListeners.remove(token);
+ }
+ break;
+ }
mWindowLayoutChangeListeners.values().remove(consumer);
}
@NonNull
- Set<Activity> getActivitiesListeningForLayoutChanges() {
+ Set<Context> getContextsListeningForLayoutChanges() {
return mWindowLayoutChangeListeners.keySet();
}
private boolean isListeningForLayoutChanges(IBinder token) {
- for (Activity activity: getActivitiesListeningForLayoutChanges()) {
- if (token.equals(activity.getWindow().getAttributes().token)) {
+ for (Context context: getContextsListeningForLayoutChanges()) {
+ if (token.equals(Context.getToken(context))) {
return true;
}
}
@@ -138,10 +186,10 @@
}
private void onDisplayFeaturesChanged(List<CommonFoldingFeature> storedFeatures) {
- for (Activity activity : getActivitiesListeningForLayoutChanges()) {
+ for (Context context : getContextsListeningForLayoutChanges()) {
// Get the WindowLayoutInfo from the activity and pass the value to the layoutConsumer.
- Consumer<WindowLayoutInfo> layoutConsumer = mWindowLayoutChangeListeners.get(activity);
- WindowLayoutInfo newWindowLayout = getWindowLayoutInfo(activity, storedFeatures);
+ Consumer<WindowLayoutInfo> layoutConsumer = mWindowLayoutChangeListeners.get(context);
+ WindowLayoutInfo newWindowLayout = getWindowLayoutInfo(context, storedFeatures);
layoutConsumer.accept(newWindowLayout);
}
}
@@ -149,11 +197,12 @@
/**
* Translates the {@link DisplayFeature} into a {@link WindowLayoutInfo} when a
* valid state is found.
- * @param activity a proxy for the {@link android.view.Window} that contains the
+ * @param context a proxy for the {@link android.view.Window} that contains the
+ * {@link DisplayFeature}.
*/
- private WindowLayoutInfo getWindowLayoutInfo(
- @NonNull Activity activity, List<CommonFoldingFeature> storedFeatures) {
- List<DisplayFeature> displayFeatureList = getDisplayFeatures(activity, storedFeatures);
+ private WindowLayoutInfo getWindowLayoutInfo(@NonNull @UiContext Context context,
+ List<CommonFoldingFeature> storedFeatures) {
+ List<DisplayFeature> displayFeatureList = getDisplayFeatures(context, storedFeatures);
return new WindowLayoutInfo(displayFeatureList);
}
@@ -170,18 +219,18 @@
* bounds are not valid, constructing a {@link FoldingFeature} will throw an
* {@link IllegalArgumentException} since this can cause negative UI effects down stream.
*
- * @param activity a proxy for the {@link android.view.Window} that contains the
+ * @param context a proxy for the {@link android.view.Window} that contains the
* {@link DisplayFeature}.
* are within the {@link android.view.Window} of the {@link Activity}
*/
private List<DisplayFeature> getDisplayFeatures(
- @NonNull Activity activity, List<CommonFoldingFeature> storedFeatures) {
+ @NonNull @UiContext Context context, List<CommonFoldingFeature> storedFeatures) {
List<DisplayFeature> features = new ArrayList<>();
- if (!shouldReportDisplayFeatures(activity)) {
+ if (!shouldReportDisplayFeatures(context)) {
return features;
}
- int displayId = activity.getDisplay().getDisplayId();
+ int displayId = context.getDisplay().getDisplayId();
for (CommonFoldingFeature baseFeature : storedFeatures) {
Integer state = convertToExtensionState(baseFeature.getState());
if (state == null) {
@@ -189,9 +238,9 @@
}
Rect featureRect = baseFeature.getRect();
rotateRectToDisplayRotation(displayId, featureRect);
- transformToWindowSpaceRect(activity, featureRect);
+ transformToWindowSpaceRect(context, featureRect);
- if (!isRectZero(featureRect)) {
+ if (!isZero(featureRect)) {
// TODO(b/228641877): Remove guarding when fixed.
features.add(new FoldingFeature(featureRect, baseFeature.getType(), state));
}
@@ -203,15 +252,21 @@
* Checks whether display features should be reported for the activity.
* TODO(b/238948678): Support reporting display features in all windowing modes.
*/
- private boolean shouldReportDisplayFeatures(@NonNull Activity activity) {
- int displayId = activity.getDisplay().getDisplayId();
+ private boolean shouldReportDisplayFeatures(@NonNull @UiContext Context context) {
+ int displayId = context.getDisplay().getDisplayId();
if (displayId != DEFAULT_DISPLAY) {
// Display features are not supported on secondary displays.
return false;
}
- final int taskWindowingMode = ActivityClient.getInstance().getTaskWindowingMode(
- activity.getActivityToken());
- if (taskWindowingMode == -1) {
+ final int windowingMode;
+ if (context instanceof Activity) {
+ windowingMode = ActivityClient.getInstance().getTaskWindowingMode(
+ context.getActivityToken());
+ } else {
+ windowingMode = context.getResources().getConfiguration().windowConfiguration
+ .getWindowingMode();
+ }
+ if (windowingMode == -1) {
// If we cannot determine the task windowing mode for any reason, it is likely that we
// won't be able to determine its position correctly as well. DisplayFeatures' bounds
// in this case can't be computed correctly, so we should skip.
@@ -219,36 +274,43 @@
}
// It is recommended not to report any display features in multi-window mode, since it
// won't be possible to synchronize the display feature positions with window movement.
- return !WindowConfiguration.inMultiWindowMode(taskWindowingMode);
+ return !WindowConfiguration.inMultiWindowMode(windowingMode);
}
- /**
- * Returns {@link true} if a {@link Rect} has zero width and zero height,
- * {@code false} otherwise.
- */
- private boolean isRectZero(Rect rect) {
- return rect.width() == 0 && rect.height() == 0;
+ private void onDisplayFeaturesChangedIfListening(@NonNull IBinder token) {
+ if (isListeningForLayoutChanges(token)) {
+ mFoldingFeatureProducer.getData(
+ WindowLayoutComponentImpl.this::onDisplayFeaturesChanged);
+ }
}
private final class NotifyOnConfigurationChanged extends EmptyLifecycleCallbacksAdapter {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
super.onActivityCreated(activity, savedInstanceState);
- onDisplayFeaturesChangedIfListening(activity);
+ onDisplayFeaturesChangedIfListening(activity.getActivityToken());
}
@Override
public void onActivityConfigurationChanged(Activity activity) {
super.onActivityConfigurationChanged(activity);
- onDisplayFeaturesChangedIfListening(activity);
+ onDisplayFeaturesChangedIfListening(activity.getActivityToken());
+ }
+ }
+
+ private final class WindowContextConfigListener implements ComponentCallbacks {
+ final IBinder mToken;
+
+ WindowContextConfigListener(IBinder token) {
+ mToken = token;
}
- private void onDisplayFeaturesChangedIfListening(Activity activity) {
- IBinder token = activity.getWindow().getAttributes().token;
- if (token == null || isListeningForLayoutChanges(token)) {
- mFoldingFeatureProducer.getData(
- WindowLayoutComponentImpl.this::onDisplayFeaturesChanged);
- }
+ @Override
+ public void onConfigurationChanged(@NonNull Configuration newConfig) {
+ onDisplayFeaturesChangedIfListening(mToken);
}
+
+ @Override
+ public void onLowMemory() {}
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java
index 0da44ac..cbaa277 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java
@@ -16,6 +16,7 @@
package androidx.window.util;
+import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import java.util.LinkedHashSet;
@@ -25,25 +26,45 @@
/**
* Base class that provides the implementation for the callback mechanism of the
- * {@link DataProducer} API.
+ * {@link DataProducer} API. This class is thread safe for adding, removing, and notifying
+ * consumers.
*
* @param <T> The type of data this producer returns through {@link DataProducer#getData}.
*/
public abstract class BaseDataProducer<T> implements DataProducer<T> {
+
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
private final Set<Consumer<T>> mCallbacks = new LinkedHashSet<>();
+ /**
+ * Adds a callback to the set of callbacks listening for data. Data is delivered through
+ * {@link BaseDataProducer#notifyDataChanged(Object)}. This method is thread safe. Callers
+ * should ensure that callbacks are thread safe.
+ * @param callback that will receive data from the producer.
+ */
@Override
public final void addDataChangedCallback(@NonNull Consumer<T> callback) {
- mCallbacks.add(callback);
- Optional<T> currentData = getCurrentData();
- currentData.ifPresent(callback);
- onListenersChanged(mCallbacks);
+ synchronized (mLock) {
+ mCallbacks.add(callback);
+ Optional<T> currentData = getCurrentData();
+ currentData.ifPresent(callback);
+ onListenersChanged(mCallbacks);
+ }
}
+ /**
+ * Removes a callback to the set of callbacks listening for data. This method is thread safe
+ * for adding.
+ * @param callback that was registered in
+ * {@link BaseDataProducer#addDataChangedCallback(Consumer)}.
+ */
@Override
public final void removeDataChangedCallback(@NonNull Consumer<T> callback) {
- mCallbacks.remove(callback);
- onListenersChanged(mCallbacks);
+ synchronized (mLock) {
+ mCallbacks.remove(callback);
+ onListenersChanged(mCallbacks);
+ }
}
protected void onListenersChanged(Set<Consumer<T>> callbacks) {}
@@ -56,11 +77,14 @@
/**
* Called to notify all registered consumers that the data provided
- * by {@link DataProducer#getData} has changed.
+ * by {@link DataProducer#getData} has changed. Calls to this are thread save but callbacks need
+ * to ensure thread safety.
*/
protected void notifyDataChanged(T value) {
- for (Consumer<T> callback : mCallbacks) {
- callback.accept(value);
+ synchronized (mLock) {
+ for (Consumer<T> callback : mCallbacks) {
+ callback.accept(value);
+ }
}
}
}
\ No newline at end of file
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
index 2a593f1..31bf963 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
@@ -21,14 +21,15 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
-import android.app.Activity;
+import android.content.Context;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.view.DisplayInfo;
import android.view.Surface;
+import android.view.WindowManager;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
+import androidx.annotation.UiContext;
/**
* Util class for both Sidecar and Extensions.
@@ -86,12 +87,9 @@
}
/** Transforms rectangle from absolute coordinate space to the window coordinate space. */
- public static void transformToWindowSpaceRect(Activity activity, Rect inOutRect) {
- Rect windowRect = getWindowBounds(activity);
- if (windowRect == null) {
- inOutRect.setEmpty();
- return;
- }
+ public static void transformToWindowSpaceRect(@NonNull @UiContext Context context,
+ Rect inOutRect) {
+ Rect windowRect = getWindowBounds(context);
if (!Rect.intersects(inOutRect, windowRect)) {
inOutRect.setEmpty();
return;
@@ -103,9 +101,9 @@
/**
* Gets the current window bounds in absolute coordinates.
*/
- @Nullable
- private static Rect getWindowBounds(@NonNull Activity activity) {
- return activity.getWindowManager().getCurrentWindowMetrics().getBounds();
+ @NonNull
+ private static Rect getWindowBounds(@NonNull @UiContext Context context) {
+ return context.getSystemService(WindowManager.class).getCurrentWindowMetrics().getBounds();
}
/**
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
index 21cf7a6..58a627b 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
@@ -20,7 +20,6 @@
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -33,9 +32,9 @@
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Point;
-import android.os.Handler;
import android.platform.test.annotations.Presubmit;
import android.window.TaskFragmentInfo;
+import android.window.TaskFragmentTransaction;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -66,10 +65,7 @@
private WindowContainerTransaction mTransaction;
@Mock
private JetpackTaskFragmentOrganizer.TaskFragmentCallback mCallback;
- @Mock
private SplitController mSplitController;
- @Mock
- private Handler mHandler;
private JetpackTaskFragmentOrganizer mOrganizer;
@Before
@@ -77,8 +73,9 @@
MockitoAnnotations.initMocks(this);
mOrganizer = new JetpackTaskFragmentOrganizer(Runnable::run, mCallback);
mOrganizer.registerOrganizer();
+ mSplitController = new SplitController();
spyOn(mOrganizer);
- doReturn(mHandler).when(mSplitController).getHandler();
+ spyOn(mSplitController);
}
@Test
@@ -129,6 +126,14 @@
WINDOWING_MODE_UNDEFINED);
}
+ @Test
+ public void testOnTransactionReady() {
+ final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
+ mOrganizer.onTransactionReady(transaction);
+
+ verify(mCallback).onTransactionReady(transaction);
+ }
+
private TaskFragmentInfo createMockInfo(TaskFragmentContainer container) {
return new TaskFragmentInfo(container.getTaskFragmentToken(),
mock(WindowContainerToken.class), new Configuration(), 0 /* runningActivityCount */,
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 07758d2..58870a6 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -19,6 +19,13 @@
import static android.app.ActivityManager.START_CANCELED;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.window.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENTED_TO_TASK;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_ERROR;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_INFO_CHANGED;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_VANISHED;
+import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.SPLIT_RATIO;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUNDS;
@@ -67,6 +74,8 @@
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.window.TaskFragmentInfo;
+import android.window.TaskFragmentOrganizer;
+import android.window.TaskFragmentTransaction;
import android.window.WindowContainerTransaction;
import androidx.test.core.app.ApplicationProvider;
@@ -118,7 +127,7 @@
mSplitPresenter = mSplitController.mPresenter;
spyOn(mSplitController);
spyOn(mSplitPresenter);
- doNothing().when(mSplitPresenter).applyTransaction(any());
+ doNothing().when(mSplitPresenter).applyTransaction(any(), anyInt(), anyBoolean());
final Configuration activityConfig = new Configuration();
activityConfig.windowConfiguration.setBounds(TASK_BOUNDS);
activityConfig.windowConfiguration.setMaxBounds(TASK_BOUNDS);
@@ -921,7 +930,8 @@
@Test
public void testResolveActivityToContainer_inUnknownTaskFragment() {
- doReturn(new Binder()).when(mSplitController).getInitialTaskFragmentToken(mActivity);
+ doReturn(new Binder()).when(mSplitController)
+ .getTaskFragmentTokenFromActivityClientRecord(mActivity);
// No need to handle when the new launched activity is in an unknown TaskFragment.
assertTrue(mSplitController.resolveActivityToContainer(mTransaction, mActivity,
@@ -980,6 +990,104 @@
assertTrue(taskContainer.mSplitContainers.isEmpty());
}
+ @Test
+ public void testOnTransactionReady_taskFragmentAppeared() {
+ final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
+ final TaskFragmentInfo info = mock(TaskFragmentInfo.class);
+ transaction.addChange(new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_APPEARED)
+ .setTaskId(TASK_ID)
+ .setTaskFragmentToken(new Binder())
+ .setTaskFragmentInfo(info));
+ mSplitController.onTransactionReady(transaction);
+
+ verify(mSplitController).onTaskFragmentAppeared(any(), eq(info));
+ verify(mSplitPresenter).onTransactionHandled(eq(transaction.getTransactionToken()), any(),
+ anyInt(), anyBoolean());
+ }
+
+ @Test
+ public void testOnTransactionReady_taskFragmentInfoChanged() {
+ final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
+ final TaskFragmentInfo info = mock(TaskFragmentInfo.class);
+ transaction.addChange(new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_INFO_CHANGED)
+ .setTaskId(TASK_ID)
+ .setTaskFragmentToken(new Binder())
+ .setTaskFragmentInfo(info));
+ mSplitController.onTransactionReady(transaction);
+
+ verify(mSplitController).onTaskFragmentInfoChanged(any(), eq(info));
+ verify(mSplitPresenter).onTransactionHandled(eq(transaction.getTransactionToken()), any(),
+ anyInt(), anyBoolean());
+ }
+
+ @Test
+ public void testOnTransactionReady_taskFragmentVanished() {
+ final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
+ final TaskFragmentInfo info = mock(TaskFragmentInfo.class);
+ transaction.addChange(new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_VANISHED)
+ .setTaskId(TASK_ID)
+ .setTaskFragmentToken(new Binder())
+ .setTaskFragmentInfo(info));
+ mSplitController.onTransactionReady(transaction);
+
+ verify(mSplitController).onTaskFragmentVanished(any(), eq(info));
+ verify(mSplitPresenter).onTransactionHandled(eq(transaction.getTransactionToken()), any(),
+ anyInt(), anyBoolean());
+ }
+
+ @Test
+ public void testOnTransactionReady_taskFragmentParentInfoChanged() {
+ final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
+ final Configuration taskConfig = new Configuration();
+ transaction.addChange(new TaskFragmentTransaction.Change(
+ TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED)
+ .setTaskId(TASK_ID)
+ .setTaskConfiguration(taskConfig));
+ mSplitController.onTransactionReady(transaction);
+
+ verify(mSplitController).onTaskFragmentParentInfoChanged(any(), eq(TASK_ID),
+ eq(taskConfig));
+ verify(mSplitPresenter).onTransactionHandled(eq(transaction.getTransactionToken()), any(),
+ anyInt(), anyBoolean());
+ }
+
+ @Test
+ public void testOnTransactionReady_taskFragmentParentError() {
+ final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
+ final IBinder errorToken = new Binder();
+ final TaskFragmentInfo info = mock(TaskFragmentInfo.class);
+ final int opType = HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT;
+ final Exception exception = new SecurityException("test");
+ final Bundle errorBundle = TaskFragmentOrganizer.putErrorInfoInBundle(exception, info,
+ opType);
+ transaction.addChange(new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_ERROR)
+ .setErrorCallbackToken(errorToken)
+ .setErrorBundle(errorBundle));
+ mSplitController.onTransactionReady(transaction);
+
+ verify(mSplitController).onTaskFragmentError(any(), eq(errorToken), eq(info), eq(opType),
+ eq(exception));
+ verify(mSplitPresenter).onTransactionHandled(eq(transaction.getTransactionToken()), any(),
+ anyInt(), anyBoolean());
+ }
+
+ @Test
+ public void testOnTransactionReady_activityReparentedToTask() {
+ final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
+ final Intent intent = mock(Intent.class);
+ final IBinder activityToken = new Binder();
+ transaction.addChange(new TaskFragmentTransaction.Change(TYPE_ACTIVITY_REPARENTED_TO_TASK)
+ .setTaskId(TASK_ID)
+ .setActivityIntent(intent)
+ .setActivityToken(activityToken));
+ mSplitController.onTransactionReady(transaction);
+
+ verify(mSplitController).onActivityReparentedToTask(any(), eq(TASK_ID), eq(intent),
+ eq(activityToken));
+ verify(mSplitPresenter).onTransactionHandled(eq(transaction.getTransactionToken()), any(),
+ anyInt(), anyBoolean());
+ }
+
/** Creates a mock activity in the organizer process. */
private Activity createMockActivity() {
final Activity activity = mock(Activity.class);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
index 3fdf8e5..25f0e25 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
@@ -39,6 +39,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -234,10 +235,8 @@
assertEquals(RESULT_EXPANDED, mPresenter.expandSplitContainerIfNeeded(mTransaction,
splitContainer, mActivity, secondaryActivity, null /* secondaryIntent */));
- verify(mPresenter).expandTaskFragment(eq(mTransaction),
- eq(primaryTf.getTaskFragmentToken()));
- verify(mPresenter).expandTaskFragment(eq(mTransaction),
- eq(secondaryTf.getTaskFragmentToken()));
+ verify(mPresenter).expandTaskFragment(mTransaction, primaryTf.getTaskFragmentToken());
+ verify(mPresenter).expandTaskFragment(mTransaction, secondaryTf.getTaskFragmentToken());
clearInvocations(mPresenter);
@@ -245,10 +244,28 @@
splitContainer, mActivity, null /* secondaryActivity */,
new Intent(ApplicationProvider.getApplicationContext(),
MinimumDimensionActivity.class)));
- verify(mPresenter).expandTaskFragment(eq(mTransaction),
- eq(primaryTf.getTaskFragmentToken()));
- verify(mPresenter).expandTaskFragment(eq(mTransaction),
- eq(secondaryTf.getTaskFragmentToken()));
+ verify(mPresenter).expandTaskFragment(mTransaction, primaryTf.getTaskFragmentToken());
+ verify(mPresenter).expandTaskFragment(mTransaction, secondaryTf.getTaskFragmentToken());
+ }
+
+ @Test
+ public void testCreateNewSplitContainer_secondaryAbovePrimary() {
+ final Activity secondaryActivity = createMockActivity();
+ final TaskFragmentContainer bottomTf = mController.newContainer(secondaryActivity, TASK_ID);
+ final TaskFragmentContainer primaryTf = mController.newContainer(mActivity, TASK_ID);
+ final SplitPairRule rule = new SplitPairRule.Builder(pair ->
+ pair.first == mActivity && pair.second == secondaryActivity, pair -> false,
+ metrics -> true)
+ .setShouldClearTop(false)
+ .build();
+
+ mPresenter.createNewSplitContainer(mTransaction, mActivity, secondaryActivity, rule);
+
+ assertEquals(primaryTf, mController.getContainerWithActivity(mActivity));
+ final TaskFragmentContainer secondaryTf = mController.getContainerWithActivity(
+ secondaryActivity);
+ assertNotEquals(bottomTf, secondaryTf);
+ assertTrue(secondaryTf.isAbove(primaryTf));
}
private Activity createMockActivity() {
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index 6cbecff..082774e 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -288,6 +288,18 @@
}
@Test
+ public void testIsAbove() {
+ final TaskContainer taskContainer = new TaskContainer(TASK_ID);
+ final TaskFragmentContainer container0 = new TaskFragmentContainer(null /* activity */,
+ mIntent, taskContainer, mController);
+ final TaskFragmentContainer container1 = new TaskFragmentContainer(null /* activity */,
+ mIntent, taskContainer, mController);
+
+ assertTrue(container1.isAbove(container0));
+ assertFalse(container0.isAbove(container1));
+ }
+
+ @Test
public void testGetBottomMostActivity() {
final TaskContainer taskContainer = new TaskContainer(TASK_ID);
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
@@ -304,6 +316,25 @@
assertEquals(activity, container.getBottomMostActivity());
}
+ @Test
+ public void testOnActivityDestroyed() {
+ final TaskContainer taskContainer = new TaskContainer(TASK_ID);
+ final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
+ mIntent, taskContainer, mController);
+ container.addPendingAppearedActivity(mActivity);
+ final List<IBinder> activities = new ArrayList<>();
+ activities.add(mActivity.getActivityToken());
+ doReturn(activities).when(mInfo).getActivities();
+ container.setInfo(mTransaction, mInfo);
+
+ assertTrue(container.hasActivity(mActivity.getActivityToken()));
+
+ taskContainer.onActivityDestroyed(mActivity);
+
+ // It should not contain the destroyed Activity.
+ assertFalse(container.hasActivity(mActivity.getActivityToken()));
+ }
+
/** Creates a mock activity in the organizer process. */
private Activity createMockActivity() {
final Activity activity = mock(Activity.class);
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_letterboxed_app.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_letterboxed_app.xml
deleted file mode 100644
index 6fcd1de..0000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_letterboxed_app.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/letterbox_education_dialog_icon_size"
- android:height="@dimen/letterbox_education_dialog_icon_size"
- android:viewportWidth="48"
- android:viewportHeight="48">
- <path
- android:fillColor="@color/letterbox_education_accent_primary"
- android:fillType="evenOdd"
- android:pathData="M2 8C0.895431 8 0 8.89543 0 10V38C0 39.1046 0.895431 40 2 40H46C47.1046 40 48 39.1046 48 38V10C48 8.89543 47.1046 8 46 8H2ZM44 12H4V36H44V12Z" />
- <path
- android:fillColor="@color/letterbox_education_accent_primary"
- android:pathData="M 17 14 L 31 14 Q 32 14 32 15 L 32 33 Q 32 34 31 34 L 17 34 Q 16 34 16 33 L 16 15 Q 16 14 17 14 Z" />
-</vector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml
new file mode 100644
index 0000000..ddfb5c2
--- /dev/null
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/letterbox_education_dialog_title_icon_width"
+ android:height="@dimen/letterbox_education_dialog_title_icon_height"
+ android:viewportWidth="45"
+ android:viewportHeight="44">
+
+ <path
+ android:fillColor="@color/letterbox_education_accent_primary"
+ android:pathData="M11 40H19C19 42.2 17.2 44 15 44C12.8 44 11 42.2 11 40ZM7 38L23 38V34L7 34L7 38ZM30 19C30 26.64 24.68 30.72 22.46 32L7.54 32C5.32 30.72 0 26.64 0 19C0 10.72 6.72 4 15 4C23.28 4 30 10.72 30 19ZM26 19C26 12.94 21.06 8 15 8C8.94 8 4 12.94 4 19C4 23.94 6.98 26.78 8.7 28L21.3 28C23.02 26.78 26 23.94 26 19ZM39.74 14.74L37 16L39.74 17.26L41 20L42.26 17.26L45 16L42.26 14.74L41 12L39.74 14.74ZM35 12L36.88 7.88L41 6L36.88 4.12L35 0L33.12 4.12L29 6L33.12 7.88L35 12Z" />
+</vector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml
index cbfcfd0..22a8f39 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml
@@ -15,18 +15,16 @@
~ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/letterbox_education_dialog_icon_size"
- android:height="@dimen/letterbox_education_dialog_icon_size"
- android:viewportWidth="48"
- android:viewportHeight="48">
+ android:width="@dimen/letterbox_education_dialog_icon_width"
+ android:height="@dimen/letterbox_education_dialog_icon_height"
+ android:viewportWidth="40"
+ android:viewportHeight="32">
+
<path
android:fillColor="@color/letterbox_education_text_secondary"
android:fillType="evenOdd"
- android:pathData="M2 8C0.895431 8 0 8.89543 0 10V38C0 39.1046 0.895431 40 2 40H46C47.1046 40 48 39.1046 48 38V10C48 8.89543 47.1046 8 46 8H2ZM44 12H4V36H44V12Z" />
+ android:pathData="M4 0C1.79086 0 0 1.79086 0 4V28C0 30.2091 1.79086 32 4 32H36C38.2091 32 40 30.2091 40 28V4C40 1.79086 38.2091 0 36 0H4ZM36 4H4V28H36V4Z" />
<path
android:fillColor="@color/letterbox_education_text_secondary"
- android:pathData="M 14 22 H 30 V 26 H 14 V 22 Z" />
- <path
- android:fillColor="@color/letterbox_education_text_secondary"
- android:pathData="M26 16L34 24L26 32V16Z" />
+ android:pathData="M19.98 8L17.16 10.82L20.32 14L12 14V18H20.32L17.14 21.18L19.98 24L28 16.02L19.98 8Z" />
</vector>
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_screen_rotation.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_screen_rotation.xml
deleted file mode 100644
index 469eb1e..0000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_screen_rotation.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/letterbox_education_dialog_icon_size"
- android:height="@dimen/letterbox_education_dialog_icon_size"
- android:viewportWidth="48"
- android:viewportHeight="48">
- <path
- android:fillColor="@color/letterbox_education_text_secondary"
- android:fillType="evenOdd"
- android:pathData="M22.56 2H26C37.02 2 46 10.98 46 22H42C42 14.44 36.74 8.1 29.7 6.42L31.74 10L28.26 12L22.56 2ZM22 46H25.44L19.74 36L16.26 38L18.3 41.58C11.26 39.9 6 33.56 6 26H2C2 37.02 10.98 46 22 46ZM20.46 12L36 27.52L27.54 36L12 20.48L20.46 12ZM17.64 9.18C18.42 8.4 19.44 8 20.46 8C21.5 8 22.52 8.4 23.3 9.16L38.84 24.7C40.4 26.26 40.4 28.78 38.84 30.34L30.36 38.82C29.58 39.6 28.56 40 27.54 40C26.52 40 25.5 39.6 24.72 38.82L9.18 23.28C7.62 21.72 7.62 19.2 9.18 17.64L17.64 9.18Z" />
-</vector>
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml
index dcb8aed..15e65f7 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml
@@ -15,18 +15,12 @@
~ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/letterbox_education_dialog_icon_size"
- android:height="@dimen/letterbox_education_dialog_icon_size"
- android:viewportWidth="48"
- android:viewportHeight="48">
+ android:width="@dimen/letterbox_education_dialog_icon_width"
+ android:height="@dimen/letterbox_education_dialog_icon_height"
+ android:viewportWidth="40"
+ android:viewportHeight="32">
+
<path
android:fillColor="@color/letterbox_education_text_secondary"
- android:fillType="evenOdd"
- android:pathData="M2 8C0.895431 8 0 8.89543 0 10V38C0 39.1046 0.895431 40 2 40H46C47.1046 40 48 39.1046 48 38V10C48 8.89543 47.1046 8 46 8H2ZM44 12H4V36H44V12Z" />
- <path
- android:fillColor="@color/letterbox_education_text_secondary"
- android:pathData="M6 16C6 14.8954 6.89543 14 8 14H21C22.1046 14 23 14.8954 23 16V32C23 33.1046 22.1046 34 21 34H8C6.89543 34 6 33.1046 6 32V16Z" />
- <path
- android:fillColor="@color/letterbox_education_text_secondary"
- android:pathData="M25 16C25 14.8954 25.8954 14 27 14H40C41.1046 14 42 14.8954 42 16V32C42 33.1046 41.1046 34 40 34H27C25.8954 34 25 33.1046 25 32V16Z" />
+ android:pathData="M40 28L40 4C40 1.8 38.2 -7.86805e-08 36 -1.74846e-07L26 -6.11959e-07C23.8 -7.08124e-07 22 1.8 22 4L22 28C22 30.2 23.8 32 26 32L36 32C38.2 32 40 30.2 40 28ZM14 28L4 28L4 4L14 4L14 28ZM18 28L18 4C18 1.8 16.2 -1.04033e-06 14 -1.1365e-06L4 -1.57361e-06C1.8 -1.66978e-06 -7.86805e-08 1.8 -1.74846e-07 4L-1.22392e-06 28C-1.32008e-06 30.2 1.8 32 4 32L14 32C16.2 32 18 30.2 18 28Z" />
</vector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
index cd1d99a..c65f24d 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
@@ -26,7 +26,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:layout_marginBottom="12dp"/>
+ android:layout_marginBottom="20dp"/>
<TextView
android:id="@+id/letterbox_education_dialog_action_text"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
index 9592376..3a44eb9 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
@@ -50,13 +50,16 @@
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
- android:padding="24dp">
+ android:paddingTop="32dp"
+ android:paddingBottom="32dp"
+ android:paddingLeft="56dp"
+ android:paddingRight="56dp">
<ImageView
- android:layout_width="@dimen/letterbox_education_dialog_icon_size"
- android:layout_height="@dimen/letterbox_education_dialog_icon_size"
- android:layout_marginBottom="12dp"
- android:src="@drawable/letterbox_education_ic_letterboxed_app"/>
+ android:layout_width="@dimen/letterbox_education_dialog_title_icon_width"
+ android:layout_height="@dimen/letterbox_education_dialog_title_icon_height"
+ android:layout_marginBottom="17dp"
+ android:src="@drawable/letterbox_education_ic_light_bulb"/>
<TextView
android:id="@+id/letterbox_education_dialog_title"
@@ -68,16 +71,6 @@
android:textColor="@color/compat_controls_text"
android:textSize="24sp"/>
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:lineSpacingExtra="4sp"
- android:text="@string/letterbox_education_dialog_subtext"
- android:textAlignment="center"
- android:textColor="@color/letterbox_education_text_secondary"
- android:textSize="14sp"/>
-
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -88,16 +81,16 @@
<com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogActionLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- app:icon="@drawable/letterbox_education_ic_screen_rotation"
- app:text="@string/letterbox_education_screen_rotation_text"/>
+ app:icon="@drawable/letterbox_education_ic_reposition"
+ app:text="@string/letterbox_education_reposition_text"/>
<com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogActionLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart=
"@dimen/letterbox_education_dialog_space_between_actions"
- app:icon="@drawable/letterbox_education_ic_reposition"
- app:text="@string/letterbox_education_reposition_text"/>
+ app:icon="@drawable/letterbox_education_ic_split_screen"
+ app:text="@string/letterbox_education_split_screen_text"/>
</LinearLayout>
@@ -105,7 +98,7 @@
android:id="@+id/letterbox_education_dialog_dismiss_button"
android:layout_width="match_parent"
android:layout_height="56dp"
- android:layout_marginTop="48dp"
+ android:layout_marginTop="40dp"
android:background=
"@drawable/letterbox_education_dismiss_button_background_ripple"
android:text="@string/letterbox_education_got_it"
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index 6959a59..aacc596 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamerakwessies?\nTik om aan te pas"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nie opgelos nie?\nTik om terug te stel"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Geen kamerakwessies nie? Tik om toe te maak."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Sommige programme werk beter in portret"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Probeer een van hierdie opsies om jou spasie ten beste te benut"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Draai jou toestel om dit volskerm te maak"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dubbeltik langs ’n program om dit te herposisioneer"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Het dit"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Vou uit vir meer inligting."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maksimeer"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Maak klein"</string>
<string name="close_button_text" msgid="2913281996024033299">"Maak toe"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index fe22b2c..02fdc42 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"የካሜራ ችግሮች አሉ?\nዳግም ለማበጀት መታ ያድርጉ"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"አልተስተካከለም?\nለማህደር መታ ያድርጉ"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ምንም የካሜራ ችግሮች የሉም? ለማሰናበት መታ ያድርጉ።"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"አንዳንድ መተግበሪያዎች በቁም ፎቶ ውስጥ በተሻለ ሁኔታ ይሰራሉ"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ቦታዎን በአግባቡ ለመጠቀም ከእነዚህ አማራጮች ውስጥ አንዱን ይሞክሩ"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ወደ የሙሉ ገጽ ዕይታ ለመሄድ መሣሪያዎን ያሽከርክሩት"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ቦታውን ለመቀየር ከመተግበሪያው ቀጥሎ ላይ ሁለቴ መታ ያድርጉ"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"ገባኝ"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ለተጨማሪ መረጃ ይዘርጉ።"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"አስፋ"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"አሳንስ"</string>
<string name="close_button_text" msgid="2913281996024033299">"ዝጋ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 2be6f39..5003f79 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"هل هناك مشاكل في الكاميرا؟\nانقر لإعادة الضبط."</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ألم يتم حل المشكلة؟\nانقر للعودة"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"أليس هناك مشاكل في الكاميرا؟ انقر للإغلاق."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"تعمل بعض التطبيقات على أكمل وجه في الشاشات العمودية"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"جرِّب تنفيذ أحد هذه الخيارات للاستفادة من مساحتك إلى أقصى حد."</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"قم بتدوير الشاشة للانتقال إلى وضع ملء الشاشة."</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"انقر مرتين بجانب التطبيق لتغيير موضعه."</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"حسنًا"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"التوسيع للحصول على مزيد من المعلومات"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"تكبير"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"تصغير"</string>
<string name="close_button_text" msgid="2913281996024033299">"إغلاق"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index 098ee84..b849345 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"কেমেৰাৰ কোনো সমস্যা হৈছে নেকি?\nপুনৰ খাপ খোৱাবলৈ টিপক"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"এইটো সমাধান কৰা নাই নেকি?\nপূৰ্বাৱস্থালৈ নিবলৈ টিপক"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"কেমেৰাৰ কোনো সমস্যা নাই নেকি? অগ্ৰাহ্য কৰিবলৈ টিপক।"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"কিছুমান এপে প’ৰ্ট্ৰেইট ম’ডত বেছি ভালকৈ কাম কৰে"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"আপোনাৰ spaceৰ পৰা পাৰ্যমানে উপকৃত হ’বলৈ ইয়াৰে এটা বিকল্প চেষ্টা কৰি চাওক"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"পূৰ্ণ স্ক্ৰীনলৈ যাবলৈ আপোনাৰ ডিভাইচটো ঘূৰাওক"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"এপ্টোৰ স্থান সলনি কৰিবলৈ ইয়াৰ কাষত দুবাৰ টিপক"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"বুজি পালোঁ"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"অধিক তথ্যৰ বাবে বিস্তাৰ কৰক।"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"সৰ্বাধিক মাত্ৰালৈ বঢ়াওক"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"মিনিমাইজ কৰক"</string>
<string name="close_button_text" msgid="2913281996024033299">"বন্ধ কৰক"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index 2f49ae6..0c7f74c 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamera problemi var?\nBərpa etmək üçün toxunun"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Düzəltməmisiniz?\nGeri qaytarmaq üçün toxunun"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kamera problemi yoxdur? Qapatmaq üçün toxunun."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Bəzi tətbiqlər portret rejimində daha yaxşı işləyir"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Məkanınızdan maksimum yararlanmaq üçün bu seçimlərdən birini sınayın"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Tam ekrana keçmək üçün cihazınızı fırladın"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Tətbiqin yerini dəyişmək üçün yanına iki dəfə toxunun"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Anladım"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Ətraflı məlumat üçün genişləndirin."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Böyüdün"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Kiçildin"</string>
<string name="close_button_text" msgid="2913281996024033299">"Bağlayın"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index 0656fe1..a9fcb66 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Imate problema sa kamerom?\nDodirnite da biste ponovo uklopili"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problem nije rešen?\nDodirnite da biste vratili"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemate problema sa kamerom? Dodirnite da biste odbacili."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Neke aplikacije najbolje funkcionišu u uspravnom režimu"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Isprobajte jednu od ovih opcija da biste na najbolji način iskoristili prostor"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotirajte uređaj za prikaz preko celog ekrana"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvaput dodirnite pored aplikacije da biste promenili njenu poziciju"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Važi"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Proširite za još informacija."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Uvećajte"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Umanjite"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zatvorite"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index 702f0ab..8fa2de5 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Праблемы з камерай?\nНацісніце, каб пераабсталяваць"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не ўдалося выправіць?\nНацісніце, каб аднавіць"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ніякіх праблем з камерай? Націсніце, каб адхіліць."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Некаторыя праграмы лепш за ўсё працуюць у кніжнай арыентацыі"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Каб эфектыўна выкарыстоўваць прастору, паспрабуйце адзін з гэтых варыянтаў"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Каб перайсці ў поўнаэкранны рэжым, павярніце прыладу"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Двойчы націсніце побач з праграмай, каб перамясціць яе"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Зразумела"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Разгарнуць для дадатковай інфармацыі"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Разгарнуць"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Згарнуць"</string>
<string name="close_button_text" msgid="2913281996024033299">"Закрыць"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index 0de16d3..60ea63e 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Имате проблеми с камерата?\nДокоснете за ремонтиране"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Проблемът не се отстрани?\nДокоснете за връщане в предишното състояние"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нямате проблеми с камерата? Докоснете, за да отхвърлите."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Някои приложения работят най-добре във вертикален режим"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Изпробвайте една от следните опции, за да се възползвате максимално от мястото на екрана"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Завъртете екрана си, за да преминете в режим на цял екран"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Докоснете два пъти дадено приложение, за да промените позицията му"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Разбрах"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Разгъване за още информация."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Увеличаване"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Намаляване"</string>
<string name="close_button_text" msgid="2913281996024033299">"Затваряне"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index 9a48d18..8e262c3 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ক্যামেরা সংক্রান্ত সমস্যা?\nরিফিট করতে ট্যাপ করুন"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"এখনও সমাধান হয়নি?\nরিভার্ট করার জন্য ট্যাপ করুন"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ক্যামেরা সংক্রান্ত সমস্যা নেই? বাতিল করতে ট্যাপ করুন।"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"কিছু অ্যাপ \'পোর্ট্রেট\' মোডে সবচেয়ে ভাল কাজ করে"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"আপনার স্পেস সবচেয়ে ভালভাবে কাজে লাগাতে এইসব বিকল্পের মধ্যে কোনও একটি ব্যবহার করে দেখুন"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"\'ফুল স্ক্রিন\' মোডে যেতে ডিভাইস ঘোরান"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"কোনও অ্যাপের পাশে ডবল ট্যাপ করে সেটির জায়গা পরিবর্তন করুন"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"বুঝেছি"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"আরও তথ্যের জন্য বড় করুন।"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"বড় করুন"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"ছোট করুন"</string>
<string name="close_button_text" msgid="2913281996024033299">"বন্ধ করুন"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index 11431d5..8a4521f 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi s kamerom?\nDodirnite da ponovo namjestite"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nije popravljeno?\nDodirnite da vratite"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nema problema s kamerom? Dodirnite da odbacite."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Određene aplikacije najbolje funkcioniraju u uspravnom načinu rada"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Isprobajte jednu od ovih opcija da maksimalno iskoristite prostor"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Zarotirajte uređaj da aktivirate prikaz preko cijelog ekrana"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvaput dodirnite pored aplikacije da promijenite njen položaj"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Razumijem"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Proširite za više informacija."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maksimiziranje"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimiziranje"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zatvaranje"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index ca0a421..fe4cb5d 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Tens problemes amb la càmera?\nToca per resoldre\'ls"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"El problema no s\'ha resolt?\nToca per desfer els canvis"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No tens cap problema amb la càmera? Toca per ignorar."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Algunes aplicacions funcionen millor en posició vertical"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prova una d\'aquestes opcions per treure el màxim profit de l\'espai"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Gira el dispositiu per passar a pantalla completa"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Fes doble toc al costat d\'una aplicació per canviar-ne la posició"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Entesos"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Desplega per obtenir més informació."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximitza"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimitza"</string>
<string name="close_button_text" msgid="2913281996024033299">"Tanca"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index e8772fe..1508b5a 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problémy s fotoaparátem?\nKlepnutím vyřešíte"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nepomohlo to?\nKlepnutím se vrátíte"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Žádné problémy s fotoaparátem? Klepnutím zavřete."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Některé aplikace fungují nejlépe na výšku"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Pokud chcete maximálně využít prostor, vyzkoušejte jednu z těchto možností"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Otočením zařízení přejděte do režimu celé obrazovky"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvojitým klepnutím vedle aplikace změňte její umístění"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Rozbalením zobrazíte další informace."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximalizovat"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimalizovat"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zavřít"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index 2b55d4d..05d2148 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Har du problemer med dit kamera?\nTryk for at gendanne det oprindelige format"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Løste det ikke problemet?\nTryk for at fortryde"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Har du ingen problemer med dit kamera? Tryk for at afvise."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Nogle apps fungerer bedst i stående format"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prøv én af disse muligheder for at få mest muligt ud af dit rum"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Drej din enhed for at gå til fuld skærm"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Tryk to gange ud for en app for at ændre dens placering"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Udvid for at få flere oplysninger."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maksimér"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimer"</string>
<string name="close_button_text" msgid="2913281996024033299">"Luk"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index 03eee02..406bf3e 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Probleme mit der Kamera?\nZum Anpassen tippen."</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Das Problem ist nicht behoben?\nZum Rückgängigmachen tippen."</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Keine Probleme mit der Kamera? Zum Schließen tippen."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Einige Apps funktionieren am besten im Hochformat"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Mithilfe dieser Möglichkeiten kannst du dein Display optimal nutzen"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Gerät drehen, um zum Vollbildmodus zu wechseln"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Neben einer App doppeltippen, um die Position zu ändern"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Ok"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Für weitere Informationen maximieren."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximieren"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimieren"</string>
<string name="close_button_text" msgid="2913281996024033299">"Schließen"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index 49bfdf1..a34acb2 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Προβλήματα με την κάμερα;\nΠατήστε για επιδιόρθωση."</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Δεν διορθώθηκε;\nΠατήστε για επαναφορά."</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Δεν αντιμετωπίζετε προβλήματα με την κάμερα; Πατήστε για παράβλεψη."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Ορισμένες εφαρμογές λειτουργούν καλύτερα σε κατακόρυφο προσανατολισμό"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Δοκιμάστε μία από αυτές τις επιλογές για να αξιοποιήσετε στο έπακρο τον χώρο σας."</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Περιστρέψτε τη συσκευή σας για μετάβαση σε πλήρη οθόνη."</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Πατήστε δύο φορές δίπλα σε μια εφαρμογή για να αλλάξετε τη θέση της."</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Το κατάλαβα"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Ανάπτυξη για περισσότερες πληροφορίες."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Μεγιστοποίηση"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Ελαχιστοποίηση"</string>
<string name="close_button_text" msgid="2913281996024033299">"Κλείσιμο"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
index 081a01a..9c798b8 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
@@ -76,12 +76,12 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Some apps work best in portrait"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Try one of these options to make the most of your space"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotate your device to go full screen"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Double-tap next to an app to reposition it"</string>
+ <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"See and do more"</string>
+ <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Drag in another app for split-screen"</string>
+ <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Double-tap outside an app to reposition it"</string>
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Got it"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expand for more information."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximise"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimise"</string>
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
index 081a01a..9c798b8 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
@@ -76,12 +76,12 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Some apps work best in portrait"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Try one of these options to make the most of your space"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotate your device to go full screen"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Double-tap next to an app to reposition it"</string>
+ <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"See and do more"</string>
+ <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Drag in another app for split-screen"</string>
+ <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Double-tap outside an app to reposition it"</string>
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Got it"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expand for more information."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximise"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimise"</string>
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
index 081a01a..9c798b8 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
@@ -76,12 +76,12 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Some apps work best in portrait"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Try one of these options to make the most of your space"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotate your device to go full screen"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Double-tap next to an app to reposition it"</string>
+ <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"See and do more"</string>
+ <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Drag in another app for split-screen"</string>
+ <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Double-tap outside an app to reposition it"</string>
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Got it"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expand for more information."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximise"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimise"</string>
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
index 081a01a..9c798b8 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
@@ -76,12 +76,12 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Some apps work best in portrait"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Try one of these options to make the most of your space"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotate your device to go full screen"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Double-tap next to an app to reposition it"</string>
+ <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"See and do more"</string>
+ <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Drag in another app for split-screen"</string>
+ <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Double-tap outside an app to reposition it"</string>
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Got it"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expand for more information."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximise"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimise"</string>
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
index afc14b8..5ff5c58 100644
--- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
@@ -76,12 +76,12 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Some apps work best in portrait"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Try one of these options to make the most of your space"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotate your device to go full screen"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Double-tap next to an app to reposition it"</string>
+ <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"See and do more"</string>
+ <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Drag in another app for split-screen"</string>
+ <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Double-tap outside an app to reposition it"</string>
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Got it"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expand for more information."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximize"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimize"</string>
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index b376b78..2482584 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"¿Tienes problemas con la cámara?\nPresiona para reajustarla"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"¿No se resolvió?\nPresiona para revertir los cambios"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"¿No tienes problemas con la cámara? Presionar para descartar."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Algunas apps funcionan mejor en modo vertical"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prueba estas opciones para aprovechar al máximo tu espacio"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rota el dispositivo para ver la pantalla completa"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Presiona dos veces junto a una app para cambiar su posición"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expande para obtener más información."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
<string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index 79c1f90..0aa35be 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"¿Problemas con la cámara?\nToca para reajustar"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"¿No se ha solucionado?\nToca para revertir"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"¿No hay problemas con la cámara? Toca para cerrar."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Algunas aplicaciones funcionan mejor en vertical"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prueba una de estas opciones para sacar el máximo partido al espacio de tu pantalla"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Gira el dispositivo para ir al modo de pantalla completa"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toca dos veces junto a una aplicación para cambiar su posición"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Mostrar más información"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
<string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index a7fead6..c9e53c7 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kas teil on kaameraprobleeme?\nPuudutage ümberpaigutamiseks."</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Kas probleemi ei lahendatud?\nPuudutage ennistamiseks."</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kas kaameraprobleeme pole? Puudutage loobumiseks."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Mõni rakendus töötab kõige paremini vertikaalpaigutuses"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Proovige ühte neist valikutest, et oma ruumi parimal moel kasutada"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Pöörake seadet, et aktiveerida täisekraanirežiim"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Topeltpuudutage rakenduse kõrval, et selle asendit muuta"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Selge"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Laiendage lisateabe saamiseks."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maksimeeri"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimeeri"</string>
<string name="close_button_text" msgid="2913281996024033299">"Sule"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index e7530c9..888b086 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Arazoak dauzkazu kamerarekin?\nBerriro doitzeko, sakatu hau."</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ez al da konpondu?\nLeheneratzeko, sakatu hau."</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ez daukazu arazorik kamerarekin? Baztertzeko, sakatu hau."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Aplikazio batzuk orientazio bertikalean funtzionatzen dute hobekien"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Pantailako eremuari ahalik eta etekinik handiena ateratzeko, probatu aukera hauetakoren bat"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Pantaila osoko modua erabiltzeko, biratu gailua"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Aplikazioaren posizioa aldatzeko, sakatu birritan haren ondoko edozein toki"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Ados"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Informazio gehiago lortzeko, zabaldu hau."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximizatu"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimizatu"</string>
<string name="close_button_text" msgid="2913281996024033299">"Itxi"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index 66a657e..1d137d1 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"دوربین مشکل دارد؟\nبرای تنظیم مجدد اندازه ضربه بزنید"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"مشکل برطرف نشد؟\nبرای برگرداندن ضربه بزنید"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"دوربین مشکلی ندارد؟ برای بستن ضربه بزنید."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"برخیاز برنامهها در حالت عمودی عملکرد بهتری دارند"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"با امتحان کردن یکی از این گزینهها، بیشترین بهره را از فضایتان ببرید"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"برای رفتن به حالت تمام صفحه، دستگاهتان را بچرخانید"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"در کنار برنامه دوضربه بزنید تا جابهجا شود"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"متوجهام"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"برای اطلاعات بیشتر، گسترده کنید."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"بزرگ کردن"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"کوچک کردن"</string>
<string name="close_button_text" msgid="2913281996024033299">"بستن"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index eaf369a..0c04489 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Onko kameran kanssa ongelmia?\nKorjaa napauttamalla"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Eikö ongelma ratkennut?\nKumoa napauttamalla"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ei ongelmia kameran kanssa? Hylkää napauttamalla."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Osa sovelluksista toimii parhaiten pystytilassa"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Kokeile jotakin näistä vaihtoehdoista, jotta saat parhaan hyödyn näytön tilasta"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Käännä laitetta, niin se siirtyy koko näytön tilaan"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Kaksoisnapauta sovellusta, jos haluat siirtää sitä"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Katso lisätietoja laajentamalla."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Suurenna"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Pienennä"</string>
<string name="close_button_text" msgid="2913281996024033299">"Sulje"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index 8f614c5..34037bf 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problèmes d\'appareil photo?\nTouchez pour réajuster"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problème non résolu?\nTouchez pour rétablir"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Aucun problème d\'appareil photo? Touchez pour ignorer."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Certaines applications fonctionnent mieux en mode portrait"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Essayez l\'une de ces options pour tirer le meilleur parti de votre espace"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Faites pivoter votre appareil pour passer en plein écran"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Touchez deux fois à côté d\'une application pour la repositionner"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Développer pour en savoir plus."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Agrandir"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Réduire"</string>
<string name="close_button_text" msgid="2913281996024033299">"Fermer"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index ec3e1b3..d717268 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problèmes d\'appareil photo ?\nAppuyez pour réajuster"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problème non résolu ?\nAppuyez pour rétablir"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Aucun problème d\'appareil photo ? Appuyez pour ignorer."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Certaines applis fonctionnent mieux en mode Portrait"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Essayez l\'une de ces options pour exploiter pleinement l\'espace"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Faites pivoter l\'appareil pour passer en plein écran"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Appuyez deux fois à côté d\'une appli pour la repositionner"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Développez pour obtenir plus d\'informations"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Agrandir"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Réduire"</string>
<string name="close_button_text" msgid="2913281996024033299">"Fermer"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index 651353d..d5500a1 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Tes problemas coa cámara?\nToca para reaxustala"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Non se solucionaron os problemas?\nToca para reverter o seu tratamento"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Non hai problemas coa cámara? Tocar para ignorar."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Algunhas aplicacións funcionan mellor en modo vertical"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Proba unha destas opcións para sacar o máximo proveito do espazo da pantalla"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Xira o dispositivo para ver o contido en pantalla completa"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toca dúas veces a carón dunha aplicación para cambiala de posición"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Despregar para obter máis información."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
<string name="close_button_text" msgid="2913281996024033299">"Pechar"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index 3543be0b..e48f62b 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"કૅમેરામાં સમસ્યાઓ છે?\nફરીથી ફિટ કરવા માટે ટૅપ કરો"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"સુધારો નથી થયો?\nપહેલાંના પર પાછું ફેરવવા માટે ટૅપ કરો"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"કૅમેરામાં કોઈ સમસ્યા નથી? છોડી દેવા માટે ટૅપ કરો."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"અમુક ઍપ પોર્ટ્રેટ મોડમાં શ્રેષ્ઠ રીતે કાર્ય કરે છે"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"તમારી સ્પેસનો વધુને વધુ લાભ લેવા માટે, આ વિકલ્પોમાંથી કોઈ એક અજમાવો"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"પૂર્ણ સ્ક્રીન મોડ લાગુ કરવા માટે, તમારા ડિવાઇસને ફેરવો"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"કોઈ ઍપની જગ્યા બદલવા માટે, તેની બાજુમાં બે વાર ટૅપ કરો"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"સમજાઈ ગયું"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"વધુ માહિતી માટે મોટું કરો."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"મોટું કરો"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"નાનું કરો"</string>
<string name="close_button_text" msgid="2913281996024033299">"બંધ કરો"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index 87ac5d6..43c9894 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"क्या कैमरे से जुड़ी कोई समस्या है?\nफिर से फ़िट करने के लिए टैप करें"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"क्या समस्या ठीक नहीं हुई?\nपहले जैसा करने के लिए टैप करें"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"क्या कैमरे से जुड़ी कोई समस्या नहीं है? खारिज करने के लिए टैप करें."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"कुछ ऐप्लिकेशन, पोर्ट्रेट मोड में सबसे अच्छी तरह काम करते हैं"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"जगह का पूरा इस्तेमाल करने के लिए, इनमें से किसी एक विकल्प को आज़माएं"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"फ़ुल स्क्रीन मोड में जाने के लिए, डिवाइस को घुमाएं"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"किसी ऐप्लिकेशन की जगह बदलने के लिए, उसके बगल में दो बार टैप करें"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"ठीक है"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ज़्यादा जानकारी के लिए बड़ा करें."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"बड़ा करें"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"विंडो छोटी करें"</string>
<string name="close_button_text" msgid="2913281996024033299">"बंद करें"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index cb4f424..951901b 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi s fotoaparatom?\nDodirnite za popravak"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problem nije riješen?\nDodirnite za vraćanje"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemate problema s fotoaparatom? Dodirnite za odbacivanje."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Neke aplikacije najbolje funkcioniraju u portretnom usmjerenju"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Isprobajte jednu od ovih opcija da biste maksimalno iskoristili prostor"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Zakrenite uređaj radi prikaza na cijelom zaslonu"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvaput dodirnite pored aplikacije da biste joj promijenili položaj"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Shvaćam"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Proširite da biste saznali više."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maksimiziraj"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimiziraj"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zatvori"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index 635f4da..bfe1849 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamerával kapcsolatos problémába ütközött?\nKoppintson a megoldáshoz."</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nem sikerült a hiba kijavítása?\nKoppintson a visszaállításhoz."</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nincsenek problémái kamerával? Koppintson az elvetéshez."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Egyes alkalmazások álló tájolásban működnek a leghatékonyabban"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Próbálja ki az alábbi beállítások egyikét, hogy a legjobban ki tudja használni képernyő területét"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"A teljes képernyős mód elindításához forgassa el az eszközt"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Koppintson duplán az alkalmazás mellett az áthelyezéséhez"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Értem"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Kibontással további információkhoz juthat."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Teljes méret"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Kis méret"</string>
<string name="close_button_text" msgid="2913281996024033299">"Bezárás"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index da382c1..b5b37e2 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Տեսախցիկի հետ կապված խնդիրնե՞ր կան։\nՀպեք՝ վերակարգավորելու համար։"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Չհաջողվե՞ց շտկել։\nՀպեք՝ փոփոխությունները չեղարկելու համար։"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Տեսախցիկի հետ կապված խնդիրներ չկա՞ն։ Փակելու համար հպեք։"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Որոշ հավելվածներ լավագույնս աշխատում են դիմանկարի ռեժիմում"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Փորձեք այս տարբերակներից մեկը՝ տարածքը հնարավորինս արդյունավետ օգտագործելու համար"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Պտտեք սարքը՝ լիաէկրան ռեժիմին անցնելու համար"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Կրկնակի հպեք հավելվածի կողքին՝ այն տեղափոխելու համար"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Եղավ"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Ծավալեք՝ ավելին իմանալու համար։"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Ծավալել"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Ծալել"</string>
<string name="close_button_text" msgid="2913281996024033299">"Փակել"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index cd79539..fed0215 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Masalah kamera?\nKetuk untuk memperbaiki"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Tidak dapat diperbaiki?\nKetuk untuk mengembalikan"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Tidak ada masalah kamera? Ketuk untuk menutup."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Beberapa aplikasi berfungsi paling baik dalam mode potret"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Coba salah satu opsi berikut untuk mengoptimalkan area layar Anda"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Putar perangkat untuk tampilan layar penuh"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Ketuk dua kali di samping aplikasi untuk mengubah posisinya"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Oke"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Luaskan untuk melihat informasi selengkapnya."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maksimalkan"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimalkan"</string>
<string name="close_button_text" msgid="2913281996024033299">"Tutup"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index 37141b7..b43aa3b 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Myndavélavesen?\nÝttu til að breyta stærð"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ennþá vesen?\nÝttu til að afturkalla"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ekkert myndavélavesen? Ýttu til að hunsa."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Sum forrit virka best í skammsniði"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prófaðu einhvern af eftirfarandi valkostum til að nýta plássið sem best"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Snúðu tækinu til að nota allan skjáinn"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Ýttu tvisvar við hlið forritsins til að færa það"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Ég skil"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Stækka til að sjá frekari upplýsingar."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Stækka"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minnka"</string>
<string name="close_button_text" msgid="2913281996024033299">"Loka"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index a2aff15..ed2f2ac 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi con la fotocamera?\nTocca per risolverli"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Il problema non si è risolto?\nTocca per ripristinare"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nessun problema con la fotocamera? Tocca per ignorare."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Alcune app funzionano in modo ottimale in verticale"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prova una di queste opzioni per ottimizzare lo spazio a tua disposizione"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Ruota il dispositivo per passare alla modalità a schermo intero"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Tocca due volte accanto a un\'app per riposizionarla"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Espandi per avere ulteriori informazioni."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Ingrandisci"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Riduci a icona"</string>
<string name="close_button_text" msgid="2913281996024033299">"Chiudi"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index 0e500ea..246fcc0 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"בעיות במצלמה?\nאפשר להקיש כדי לבצע התאמה מחדש"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"הבעיה לא נפתרה?\nאפשר להקיש כדי לחזור לגרסה הקודמת"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"אין בעיות במצלמה? אפשר להקיש כדי לסגור."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"חלק מהאפליקציות פועלות בצורה הטובה ביותר במצב תצוגה לאורך"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"כדי להפיק את המרב משטח המסך, ניתן לנסות את אחת מהאפשרויות האלה"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"מסובבים את המכשיר כדי לעבור לתצוגה במסך מלא"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"מקישים הקשה כפולה ליד אפליקציה כדי למקם אותה מחדש"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"הבנתי"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"מרחיבים כדי לקבל מידע נוסף."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"הגדלה"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"מזעור"</string>
<string name="close_button_text" msgid="2913281996024033299">"סגירה"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index 34ed9c7..beb13c4 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"カメラに関する問題の場合は、\nタップすると修正できます"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"修正されなかった場合は、\nタップすると元に戻ります"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"カメラに関する問題でない場合は、タップすると閉じます。"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"アプリによっては縦向きにすると正常に動作します"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"スペースを最大限に活用するには、以下の方法のいずれかをお試しください"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"全画面表示にするにはデバイスを回転させてください"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"位置を変えるにはアプリの横をダブルタップしてください"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"開くと詳細が表示されます。"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"最小化"</string>
<string name="close_button_text" msgid="2913281996024033299">"閉じる"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index 14b26c1..86d47cd 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"კამერად პრობლემები აქვს?\nშეეხეთ გამოსასწორებლად"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"არ გამოსწორდა?\nშეეხეთ წინა ვერსიის დასაბრუნებლად"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"კამერას პრობლემები არ აქვს? შეეხეთ უარყოფისთვის."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"ზოგიერთი აპი უკეთ მუშაობს პორტრეტის რეჟიმში"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"გამოცადეთ ამ ვარიანტებიდან ერთ-ერთი, რათა მაქსიმალურად ისარგებლოთ თქვენი მეხსიერებით"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"მოატრიალეთ თქვენი მოწყობილობა სრული ეკრანის გასაშლელად"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ორმაგად შეეხეთ აპის გვერდითა სივრცეს, რათა ის სხვაგან გადაიტანოთ"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"გასაგებია"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"დამატებითი ინფორმაციისთვის გააფართოეთ."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"მაქსიმალურად გაშლა"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"ჩაკეცვა"</string>
<string name="close_button_text" msgid="2913281996024033299">"დახურვა"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index c42efdc..31bb209 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерада қателер шықты ма?\nЖөндеу үшін түртіңіз."</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Жөнделмеді ме?\nҚайтару үшін түртіңіз."</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерада қателер шықпады ма? Жабу үшін түртіңіз."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Кейбір қолданба портреттік режимде жақсы жұмыс істейді"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Экранды тиімді пайдалану үшін мына опциялардың бірін байқап көріңіз."</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Толық экранға ауысу үшін құрылғыңызды бұрыңыз."</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Қолданбаның орнын ауыстыру үшін жанынан екі рет түртіңіз."</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Түсінікті"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Толығырақ ақпарат алу үшін терезені жайыңыз."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Жаю"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Кішірейту"</string>
<string name="close_button_text" msgid="2913281996024033299">"Жабу"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index 302b25e..38bbbd8 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"មានបញ្ហាពាក់ព័ន្ធនឹងកាមេរ៉ាឬ?\nចុចដើម្បីដោះស្រាយ"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"មិនបានដោះស្រាយបញ្ហានេះទេឬ?\nចុចដើម្បីត្រឡប់"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"មិនមានបញ្ហាពាក់ព័ន្ធនឹងកាមេរ៉ាទេឬ? ចុចដើម្បីច្រានចោល។"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"កម្មវិធីមួយចំនួនដំណើរការបានប្រសើរបំផុតក្នុងទិសដៅបញ្ឈរ"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"សាកល្បងជម្រើសមួយក្នុងចំណោមទាំងនេះ ដើម្បីទទួលបានអត្ថប្រយោជន៍ច្រើនបំផុតពីកន្លែងទំនេររបស់អ្នក"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"បង្វិលឧបករណ៍របស់អ្នក ដើម្បីចូលប្រើអេក្រង់ពេញ"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ចុចពីរដងនៅជាប់កម្មវិធីណាមួយ ដើម្បីប្ដូរទីតាំងកម្មវិធីនោះ"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"យល់ហើយ"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ពង្រីកដើម្បីទទួលបានព័ត៌មានបន្ថែម។"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"ពង្រីក"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"បង្រួម"</string>
<string name="close_button_text" msgid="2913281996024033299">"បិទ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index 2b3aa07..2d0656e 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ಕ್ಯಾಮರಾ ಸಮಸ್ಯೆಗಳಿವೆಯೇ?\nಮರುಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ಅದನ್ನು ಸರಿಪಡಿಸಲಿಲ್ಲವೇ?\nಹಿಂತಿರುಗಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ಕ್ಯಾಮರಾ ಸಮಸ್ಯೆಗಳಿಲ್ಲವೇ? ವಜಾಗೊಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"ಕೆಲವು ಆ್ಯಪ್ಗಳು ಪೋರ್ಟ್ರೇಟ್ ಮೋಡ್ನಲ್ಲಿ ಅತ್ಯುತ್ತಮವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತವೆ"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ನಿಮ್ಮ ಸ್ಥಳಾವಕಾಶದ ಅತಿಹೆಚ್ಚು ಪ್ರಯೋಜನ ಪಡೆಯಲು ಈ ಆಯ್ಕೆಗಳಲ್ಲಿ ಒಂದನ್ನು ಬಳಸಿ ನೋಡಿ"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ಪೂರ್ಣ ಸ್ಕ್ರೀನ್ಗೆ ಹೋಗಲು ನಿಮ್ಮ ಸಾಧನವನ್ನು ತಿರುಗಿಸಿ"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ಆ್ಯಪ್ ಒಂದರ ಸ್ಥಾನವನ್ನು ಬದಲಾಯಿಸಲು ಅದರ ಪಕ್ಕದಲ್ಲಿ ಡಬಲ್-ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"ಸರಿ"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ಇನ್ನಷ್ಟು ಮಾಹಿತಿಗಾಗಿ ವಿಸ್ತೃತಗೊಳಿಸಿ."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"ಹಿಗ್ಗಿಸಿ"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"ಕುಗ್ಗಿಸಿ"</string>
<string name="close_button_text" msgid="2913281996024033299">"ಮುಚ್ಚಿರಿ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index 5505955..dadf3f6 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"카메라 문제가 있나요?\n해결하려면 탭하세요."</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"해결되지 않았나요?\n되돌리려면 탭하세요."</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"카메라에 문제가 없나요? 닫으려면 탭하세요."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"일부 앱은 세로 모드에서 가장 잘 작동함"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"공간을 최대한 이용할 수 있도록 이 옵션 중 하나를 시도해 보세요."</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"전체 화면 모드로 전환하려면 기기를 회전하세요."</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"앱 위치를 조정하려면 앱 옆을 두 번 탭하세요."</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"확인"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"추가 정보는 펼쳐서 확인하세요."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"최대화"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"최소화"</string>
<string name="close_button_text" msgid="2913281996024033299">"닫기"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index d45a984..edd13d5 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерада маселелер келип чыктыбы?\nОңдоо үчүн таптаңыз"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Оңдолгон жокпу?\nАртка кайтаруу үчүн таптаңыз"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерада маселе жокпу? Этибарга албоо үчүн таптаңыз."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Айрым колдонмолорду тигинен иштетүү туура болот"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Иш чөйрөсүнүн бардык мүмкүнчүлүктөрүн пайдалануу үчүн бул параметрлердин бирин колдонуп көрүңүз"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Толук экран режимине өтүү үчүн түзмөктү буруңуз"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Колдонмонун ракурсун өзгөртүү үчүн анын тушуна эки жолу басыңыз"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Түшүндүм"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Толук маалымат алуу үчүн жайып көрүңүз."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Чоңойтуу"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Кичирейтүү"</string>
<string name="close_button_text" msgid="2913281996024033299">"Жабуу"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index 0eeee90..8d54e48 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ມີບັນຫາກ້ອງຖ່າຍຮູບບໍ?\nແຕະເພື່ອປັບໃໝ່"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ບໍ່ໄດ້ແກ້ໄຂມັນບໍ?\nແຕະເພື່ອແປງກັບຄືນ"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ບໍ່ມີບັນຫາກ້ອງຖ່າຍຮູບບໍ? ແຕະເພື່ອປິດໄວ້."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"ແອັບບາງຢ່າງເຮັດວຽກໄດ້ດີທີ່ສຸດໃນໂໝດລວງຕັ້ງ"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ໃຫ້ລອງຕົວເລືອກໃດໜຶ່ງເຫຼົ່ານີ້ເພື່ອໃຊ້ປະໂຫຍດຈາກພື້ນທີ່ຂອງທ່ານໃຫ້ໄດ້ສູງສຸດ"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ໝຸນອຸປະກອນຂອງທ່ານເພື່ອໃຊ້ແບບເຕັມຈໍ"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ແຕະສອງເທື່ອໃສ່ຖັດຈາກແອັບໃດໜຶ່ງເພື່ອຈັດຕຳແໜ່ງຂອງມັນຄືນໃໝ່"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"ເຂົ້າໃຈແລ້ວ"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ຂະຫຍາຍເພື່ອເບິ່ງຂໍ້ມູນເພີ່ມເຕີມ."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"ຂະຫຍາຍໃຫຍ່ສຸດ"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"ຫຍໍ້ລົງ"</string>
<string name="close_button_text" msgid="2913281996024033299">"ປິດ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index fc118e2..a7a5e55 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Iškilo problemų dėl kameros?\nPalieskite, kad pritaikytumėte iš naujo"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nepavyko pataisyti?\nPalieskite, kad grąžintumėte"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nėra jokių problemų dėl kameros? Palieskite, kad atsisakytumėte."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Kai kurios programos geriausiai veikia stačiuoju režimu"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Pabandykite naudoti vieną iš šių parinkčių, kad išnaudotumėte visą vietą"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Pasukite įrenginį, kad įjungtumėte viso ekrano režimą"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dukart palieskite šalia programos, kad pakeistumėte jos poziciją"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Supratau"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Išskleiskite, jei reikia daugiau informacijos."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Padidinti"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Sumažinti"</string>
<string name="close_button_text" msgid="2913281996024033299">"Uždaryti"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index cd2af07..c7f2677 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Vai ir problēmas ar kameru?\nPieskarieties, lai tās novērstu."</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Vai problēma netika novērsta?\nPieskarieties, lai atjaunotu."</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Vai nav problēmu ar kameru? Pieskarieties, lai nerādītu."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Dažas lietotnes vislabāk darbojas portreta režīmā"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Izmēģiniet vienu no šīm iespējām, lai efektīvi izmantotu pieejamo vietu"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Pagrieziet ierīci, lai aktivizētu pilnekrāna režīmu"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Veiciet dubultskārienu blakus lietotnei, lai manītu tās pozīciju"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Labi"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Izvērsiet, lai iegūtu plašāku informāciju."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maksimizēt"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimizēt"</string>
<string name="close_button_text" msgid="2913281996024033299">"Aizvērt"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index c0dff00..7331a6c 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблеми со камерата?\nДопрете за да се совпадне повторно"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не се поправи?\nДопрете за враќање"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нема проблеми со камерата? Допрете за отфрлање."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Некои апликации најдобро работат во режим на портрет"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Испробајте една од опцииве за да го извлечете максимумот од вашиот простор"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Ротирајте го уредот за да отворите на цел екран"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Допрете двапати до некоја апликација за да ја преместите"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Сфатив"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Проширете за повеќе информации."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Зголеми"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Минимизирај"</string>
<string name="close_button_text" msgid="2913281996024033299">"Затвори"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index 52ea1c7..f548ca5 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ക്യാമറ പ്രശ്നങ്ങളുണ്ടോ?\nശരിയാക്കാൻ ടാപ്പ് ചെയ്യുക"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"അത് പരിഹരിച്ചില്ലേ?\nപുനഃസ്ഥാപിക്കാൻ ടാപ്പ് ചെയ്യുക"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ക്യാമറാ പ്രശ്നങ്ങളൊന്നുമില്ലേ? നിരസിക്കാൻ ടാപ്പ് ചെയ്യുക."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"ചില ആപ്പുകൾ പോർട്രെയ്റ്റിൽ മികച്ച രീതിയിൽ പ്രവർത്തിക്കുന്നു"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"നിങ്ങളുടെ ഇടം പരമാവധി പ്രയോജനപ്പെടുത്താൻ ഈ ഓപ്ഷനുകളിലൊന്ന് പരീക്ഷിക്കുക"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"പൂർണ്ണ സ്ക്രീനിലേക്ക് മാറാൻ ഈ ഉപകരണം റൊട്ടേറ്റ് ചെയ്യുക"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ഒരു ആപ്പിന്റെ സ്ഥാനം മാറ്റാൻ, അതിന് തൊട്ടടുത്ത് ഡബിൾ ടാപ്പ് ചെയ്യുക"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"മനസ്സിലായി"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"കൂടുതൽ വിവരങ്ങൾക്ക് വികസിപ്പിക്കുക."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"വലുതാക്കുക"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"ചെറുതാക്കുക"</string>
<string name="close_button_text" msgid="2913281996024033299">"അടയ്ക്കുക"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index fd4c4aa..c202558 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерын асуудал гарсан уу?\nДахин тааруулахын тулд товшино уу"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Үүнийг засаагүй юу?\nБуцаахын тулд товшино уу"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерын асуудал байхгүй юу? Хаахын тулд товшино уу."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Зарим апп нь босоо чиглэлд хамгийн сайн ажилладаг"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Орон зайгаа сайтар ашиглахын тулд эдгээр сонголтуудын аль нэгийг туршиж үзээрэй"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Төхөөрөмжөө бүтэн дэлгэцээр үзэхийн тулд эргүүлнэ"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Аппыг дахин байрлуулахын тулд хажууд нь хоёр товшино"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Ойлголоо"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Нэмэлт мэдээлэл авах бол дэлгэнэ үү."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Томруулах"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Багасгах"</string>
<string name="close_button_text" msgid="2913281996024033299">"Хаах"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index b9a165e..b9131f1 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"कॅमेराशी संबंधित काही समस्या आहेत का?\nपुन्हा फिट करण्यासाठी टॅप करा"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"निराकरण झाले नाही?\nरिव्हर्ट करण्यासाठी कृपया टॅप करा"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"कॅमेराशी संबंधित कोणत्याही समस्या नाहीत का? डिसमिस करण्यासाठी टॅप करा."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"काही ॲप्स पोर्ट्रेटमध्ये सर्वोत्तम काम करतात"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"तुमच्या स्पेसचा पुरेपूर वापर करण्यासाठी, यांपैकी एक पर्याय वापरून पहा"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"फुल स्क्रीन करण्यासाठी, तुमचे डिव्हाइस फिरवा"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ॲपची स्थिती पुन्हा बदलण्यासाठी, त्याच्या शेजारी दोनदा टॅप करा"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"समजले"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"अधिक माहितीसाठी विस्तार करा."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"मोठे करा"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"लहान करा"</string>
<string name="close_button_text" msgid="2913281996024033299">"बंद करा"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index 3d81c9a..6ce08e0 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Isu kamera?\nKetik untuk memuatkan semula"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Isu tidak dibetulkan?\nKetik untuk kembali"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Tiada isu kamera? Ketik untuk mengetepikan."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Sesetengah apl berfungsi paling baik dalam mod potret"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Cuba salah satu daripada pilihan ini untuk memanfaatkan ruang anda sepenuhnya"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Putar peranti anda untuk beralih ke skrin penuh"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Ketik dua kali bersebelahan apl untuk menempatkan semula apl"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Kembangkan untuk mendapatkan maklumat lanjut."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maksimumkan"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimumkan"</string>
<string name="close_button_text" msgid="2913281996024033299">"Tutup"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index 50adfe9..d7df466 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ကင်မရာပြဿနာလား။\nပြင်ဆင်ရန် တို့ပါ"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ကောင်းမသွားဘူးလား။\nပြန်ပြောင်းရန် တို့ပါ"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ကင်မရာပြဿနာ မရှိဘူးလား။ ပယ်ရန် တို့ပါ။"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"အချို့အက်ပ်များသည် ဒေါင်လိုက်တွင် အကောင်းဆုံးလုပ်ဆောင်သည်"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"သင့်နေရာကို အကောင်းဆုံးအသုံးပြုနိုင်ရန် ဤရွေးစရာများထဲမှ တစ်ခုကို စမ်းကြည့်ပါ"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ဖန်သားပြင်အပြည့်လုပ်ရန် သင့်စက်ကို လှည့်နိုင်သည်"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"အက်ပ်နေရာပြန်ချရန် ၎င်းဘေးတွင် နှစ်ချက်တို့နိုင်သည်"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"ရပြီ"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"နောက်ထပ်အချက်အလက်များအတွက် ချဲ့နိုင်သည်။"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"ချဲ့ရန်"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"ချုံ့ရန်"</string>
<string name="close_button_text" msgid="2913281996024033299">"ပိတ်ရန်"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index 74e066e..86e8381 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Har du kameraproblemer?\nTrykk for å tilpasse"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ble ikke problemet løst?\nTrykk for å gå tilbake"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Har du ingen kameraproblemer? Trykk for å lukke."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Noen apper fungerer best i stående format"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prøv et av disse alternativene for å få mest mulig ut av plassen din"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Roter enheten for å starte fullskjerm"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dobbelttrykk ved siden av en app for å flytte den"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Greit"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Vis for å få mer informasjon."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maksimer"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimer"</string>
<string name="close_button_text" msgid="2913281996024033299">"Lukk"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index b257f9e..3a0cc76 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"क्यामेरासम्बन्धी समस्या देखियो?\nसमस्या हल गर्न ट्याप गर्नुहोस्"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"समस्या हल भएन?\nपहिलेको जस्तै बनाउन ट्याप गर्नुहोस्"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"क्यामेरासम्बन्धी कुनै पनि समस्या छैन? खारेज गर्न ट्याप गर्नुहोस्।"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"केही एपहरूले पोर्ट्रेटमा राम्रोसँग काम गर्छन्"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"तपाईं स्क्रिनको अधिकतम ठाउँ प्रयोग गर्न चाहनुहुन्छ भने यीमध्ये कुनै विकल्प प्रयोग गरी हेर्नुहोस्"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"तपाईं फुल स्क्रिन मोड हेर्न चाहनुहुन्छ भने आफ्नो डिभाइस रोटेट गर्नुहोस्"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"तपाईं जुन एपको स्थिति मिलाउन चाहनुहुन्छ सोही एपको छेउमा डबल ट्याप गर्नुहोस्"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"बुझेँ"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"थप जानकारी प्राप्त गर्न चाहनुहुन्छ भने एक्स्पान्ड गर्नुहोस्।"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"ठुलो बनाउनुहोस्"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"मिनिमाइज गर्नुहोस्"</string>
<string name="close_button_text" msgid="2913281996024033299">"बन्द गर्नुहोस्"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index 6ea24a8..cfd7b5f 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Cameraproblemen?\nTik om opnieuw passend te maken."</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Is dit geen oplossing?\nTik om terug te zetten."</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Geen cameraproblemen? Tik om te sluiten."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Sommige apps werken het best in de staande stand"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Probeer een van deze opties om optimaal gebruik te maken van je ruimte"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Draai je apparaat om naar volledig scherm te schakelen"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dubbeltik naast een app om deze opnieuw te positioneren"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Uitvouwen voor meer informatie."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximaliseren"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimaliseren"</string>
<string name="close_button_text" msgid="2913281996024033299">"Sluiten"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index f8c9248..a24b3a4 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"କ୍ୟାମେରାରେ ସମସ୍ୟା ଅଛି?\nପୁଣି ଫିଟ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ଏହାର ସମାଧାନ ହୋଇନାହିଁ?\nଫେରିଯିବା ପାଇଁ ଟାପ କରନ୍ତୁ"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"କ୍ୟାମେରାରେ କିଛି ସମସ୍ୟା ନାହିଁ? ଖାରଜ କରିବାକୁ ଟାପ କରନ୍ତୁ।"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"କିଛି ଆପ ପୋର୍ଟ୍ରେଟରେ ସବୁଠାରୁ ଭଲ କାମ କରେ"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ଆପଣଙ୍କ ସ୍ପେସରୁ ଅଧିକ ଲାଭ ପାଇବାକୁ ଏହି ବିକଳ୍ପଗୁଡ଼ିକ ମଧ୍ୟରୁ ଗୋଟିଏ ବ୍ୟବହାର କରି ଦେଖନ୍ତୁ"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ପୂର୍ଣ୍ଣ-ସ୍କ୍ରିନ ବ୍ୟବହାର କରିବାକୁ ଆପଣଙ୍କ ଡିଭାଇସକୁ ରୋଟେଟ କରନ୍ତୁ"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ଏକ ଆପକୁ ରିପୋଜିସନ କରିବା ପାଇଁ ଏହା ପାଖରେ ଦୁଇଥର-ଟାପ କରନ୍ତୁ"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"ବୁଝିଗଲି"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ଅଧିକ ସୂଚନା ପାଇଁ ବିସ୍ତାର କରନ୍ତୁ।"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"ବଡ଼ କରନ୍ତୁ"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"ଛୋଟ କରନ୍ତୁ"</string>
<string name="close_button_text" msgid="2913281996024033299">"ବନ୍ଦ କରନ୍ତୁ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index b80da0b..5777a96 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ਕੀ ਕੈਮਰੇ ਸੰਬੰਧੀ ਸਮੱਸਿਆਵਾਂ ਹਨ?\nਮੁੜ-ਫਿੱਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ਕੀ ਇਹ ਠੀਕ ਨਹੀਂ ਹੋਈ?\nਵਾਪਸ ਉਹੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ਕੀ ਕੈਮਰੇ ਸੰਬੰਧੀ ਕੋਈ ਸਮੱਸਿਆ ਨਹੀਂ ਹੈ? ਖਾਰਜ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"ਕੁਝ ਐਪਾਂ ਪੋਰਟਰੇਟ ਵਿੱਚ ਬਿਹਤਰ ਕੰਮ ਕਰਦੀਆਂ ਹਨ"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ਆਪਣੀ ਜਗ੍ਹਾ ਦਾ ਵੱਧ ਤੋਂ ਵੱਧ ਲਾਹਾ ਲੈਣ ਲਈ ਇਨ੍ਹਾਂ ਵਿਕਲਪਾਂ ਵਿੱਚੋਂ ਕੋਈ ਇੱਕ ਵਰਤ ਕੇ ਦੇਖੋ"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ਪੂਰੀ-ਸਕ੍ਰੀਨ ਮੋਡ \'ਤੇ ਜਾਣ ਲਈ ਆਪਣੇ ਡੀਵਾਈਸ ਨੂੰ ਘੁਮਾਓ"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ਕਿਸੇ ਐਪ ਦੀ ਜਗ੍ਹਾ ਬਦਲਣ ਲਈ ਉਸ ਦੇ ਅੱਗੇ ਡਬਲ ਟੈਪ ਕਰੋ"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"ਸਮਝ ਲਿਆ"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਵਿਸਤਾਰ ਕਰੋ।"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"ਵੱਡਾ ਕਰੋ"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"ਛੋਟਾ ਕਰੋ"</string>
<string name="close_button_text" msgid="2913281996024033299">"ਬੰਦ ਕਰੋ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index bdd44dd..ce498b2 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemy z aparatem?\nKliknij, aby dopasować"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Naprawa się nie udała?\nKliknij, aby cofnąć"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Brak problemów z aparatem? Kliknij, aby zamknąć"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Niektóre aplikacje działają najlepiej w orientacji pionowej"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Wypróbuj jedną z tych opcji, aby jak najlepiej wykorzystać miejsce"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Obróć urządzenie, aby przejść do pełnego ekranu"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Kliknij dwukrotnie obok aplikacji, aby ją przenieść"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Rozwiń, aby wyświetlić więcej informacji."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maksymalizuj"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimalizuj"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zamknij"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index b9e41ea..4e19956 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmera?\nToque para ajustar o enquadramento"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"O problema não foi corrigido?\nToque para reverter"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Não tem problemas com a câmera? Toque para dispensar."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Alguns apps funcionam melhor em modo retrato"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Tente uma destas opções para aproveitar seu espaço ao máximo"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Gire o dispositivo para entrar no modo de tela cheia"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toque duas vezes ao lado de um app para reposicionar"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendi"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Abra para ver mais informações."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
<string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index c1e57d8..4215627 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmara?\nToque aqui para reajustar"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Não foi corrigido?\nToque para reverter"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nenhum problema com a câmara? Toque para ignorar."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Algumas apps funcionam melhor no modo vertical"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Experimente uma destas opções para aproveitar ao máximo o seu espaço"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rode o dispositivo para ficar em ecrã inteiro"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toque duas vezes junto a uma app para a reposicionar"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expandir para obter mais informações"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
<string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index b9e41ea..4e19956 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmera?\nToque para ajustar o enquadramento"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"O problema não foi corrigido?\nToque para reverter"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Não tem problemas com a câmera? Toque para dispensar."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Alguns apps funcionam melhor em modo retrato"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Tente uma destas opções para aproveitar seu espaço ao máximo"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Gire o dispositivo para entrar no modo de tela cheia"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toque duas vezes ao lado de um app para reposicionar"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendi"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Abra para ver mais informações."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
<string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index c49bf9d..535b021 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Aveți probleme cu camera foto?\nAtingeți pentru a reîncadra"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nu ați remediat problema?\nAtingeți pentru a reveni"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nu aveți probleme cu camera foto? Atingeți pentru a închide."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Unele aplicații funcționează cel mai bine în orientarea portret"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Încercați una dintre aceste opțiuni pentru a profita din plin de spațiu"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotiți dispozitivul pentru a trece în modul ecran complet"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Atingeți de două ori lângă o aplicație pentru a o repoziționa"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Extindeți pentru mai multe informații"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximizați"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimizează"</string>
<string name="close_button_text" msgid="2913281996024033299">"Închideți"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index ffe031d..e094b6b 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблемы с камерой?\nНажмите, чтобы исправить."</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не помогло?\nНажмите, чтобы отменить изменения."</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нет проблем с камерой? Нажмите, чтобы закрыть."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Некоторые приложения лучше работают в вертикальном режиме"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Чтобы эффективно использовать экранное пространство, выполните одно из следующих действий:"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Чтобы перейти в полноэкранный режим, поверните устройство."</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Чтобы переместить приложение, нажмите на него дважды."</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"ОК"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Развернуть, чтобы узнать больше."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Развернуть"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Свернуть"</string>
<string name="close_button_text" msgid="2913281996024033299">"Закрыть"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index b27e1b9..d52b8f6 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"කැමරා ගැටලුද?\nයළි සවි කිරීමට තට්ටු කරන්න"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"එය විසඳුවේ නැතිද?\nප්රතිවර්තනය කිරීමට තට්ටු කරන්න"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"කැමරා ගැටලු නොමැතිද? ඉවත දැමීමට තට්ටු කරන්න"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"සමහර යෙදුම් ප්රතිමූර්තිය තුළ හොඳින්ම ක්රියා කරයි"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ඔබගේ ඉඩෙන් උපරිම ප්රයෝජන ගැනීමට මෙම විකල්පවලින් එකක් උත්සාහ කරන්න"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"සම්පූර්ණ තිරයට යාමට ඔබගේ උපාංගය කරකවන්න"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"එය නැවත ස්ථානගත කිරීමට යෙදුමකට යාබදව දෙවරක් තට්ටු කරන්න"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"තේරුණා"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"වැඩිදුර තොරතුරු සඳහා දිග හරින්න"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"විහිදන්න"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"කුඩා කරන්න"</string>
<string name="close_button_text" msgid="2913281996024033299">"වසන්න"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index b5bedf7..0dc8af5 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problémy s kamerou?\nKlepnutím znova upravte."</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nevyriešilo sa to?\nKlepnutím sa vráťte."</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemáte problémy s kamerou? Klepnutím zatvoríte."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Niektoré aplikácie fungujú najlepšie v režime na výšku"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Vyskúšajte jednu z týchto možností a využívajte svoj priestor naplno"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Otočením zariadenia prejdete do režimu celej obrazovky"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvojitým klepnutím vedľa aplikácie zmeníte jej pozíciu"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Dobre"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Po rozbalení sa dozviete viac."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maximalizovať"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimalizovať"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zavrieť"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index ac926b9..49902da 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Težave s fotoaparatom?\nDotaknite se za vnovično prilagoditev"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"To ni odpravilo težave?\nDotaknite se za povrnitev"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nimate težav s fotoaparatom? Dotaknite se za opustitev."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Nekatere aplikacije najbolje delujejo v navpični postavitvi"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Poskusite eno od teh možnosti za čim boljši izkoristek prostora"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Če želite preklopiti v celozaslonski način, zasukajte napravo."</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvakrat se dotaknite ob aplikaciji, če jo želite prestaviti."</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"V redu"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Razširitev za več informacij"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maksimiraj"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimiraj"</string>
<string name="close_button_text" msgid="2913281996024033299">"Zapri"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index 07c52fe..765a6d9 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Ka probleme me kamerën?\nTrokit për ta ripërshtatur"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nuk u rregullua?\nTrokit për ta rikthyer"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nuk ka probleme me kamerën? Trokit për ta shpërfillur."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Disa aplikacione funksionojnë më mirë në modalitetin vertikal"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Provo një nga këto opsione për ta shfrytëzuar sa më mirë hapësirën"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rrotullo ekranin për të kaluar në ekran të plotë"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Trokit dy herë pranë një aplikacioni për ta ripozicionuar"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"E kuptova"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Zgjeroje për më shumë informacion."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Maksimizo"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimizo"</string>
<string name="close_button_text" msgid="2913281996024033299">"Mbyll"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index 0289dd1..1d7a122 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Имате проблема са камером?\nДодирните да бисте поново уклопили"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Проблем није решен?\nДодирните да бисте вратили"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Немате проблема са камером? Додирните да бисте одбацили."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Неке апликације најбоље функционишу у усправном режиму"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Испробајте једну од ових опција да бисте на најбољи начин искористили простор"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Ротирајте уређај за приказ преко целог екрана"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Двапут додирните поред апликације да бисте променили њену позицију"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Важи"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Проширите за још информација."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Увећајте"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Умањите"</string>
<string name="close_button_text" msgid="2913281996024033299">"Затворите"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index cfdb1dd..90e894d 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problem med kameran?\nTryck för att anpassa på nytt"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Löstes inte problemet?\nTryck för att återställa"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Inga problem med kameran? Tryck för att ignorera."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Vissa appar fungerar bäst i stående läge"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Testa med ett av dessa alternativ för att få ut mest möjliga av ytan"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotera skärmen för att gå över till helskärmsläge"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Tryck snabbt två gånger bredvid en app för att flytta den"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Utöka för mer information."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Utöka"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Minimera"</string>
<string name="close_button_text" msgid="2913281996024033299">"Stäng"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index 383e9bb..e445f2a 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Je, kuna hitilafu za kamera?\nGusa ili urekebishe"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Umeshindwa kurekebisha?\nGusa ili urejeshe nakala ya awali"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Je, hakuna hitilafu za kamera? Gusa ili uondoe."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Baadhi ya programu hufanya kazi vizuri zaidi zikiwa wima"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Jaribu moja kati ya chaguo hizi ili utumie nafasi ya skrini yako kwa ufanisi"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Zungusha kifaa chako ili uende kwenye hali ya skrini nzima"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Gusa mara mbili karibu na programu ili uihamishe"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Nimeelewa"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Panua ili upate maelezo zaidi."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Panua"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Punguza"</string>
<string name="close_button_text" msgid="2913281996024033299">"Funga"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index cc512f3..2f0ed7d 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"கேமரா தொடர்பான சிக்கல்களா?\nமீண்டும் பொருத்த தட்டவும்"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"சிக்கல்கள் சரிசெய்யப்படவில்லையா?\nமாற்றியமைக்க தட்டவும்"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"கேமரா தொடர்பான சிக்கல்கள் எதுவும் இல்லையா? நிராகரிக்க தட்டவும்."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"சில ஆப்ஸ் \'போர்ட்ரெய்ட்டில்\' சிறப்பாகச் செயல்படும்"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ஸ்பேஸ்களிலிருந்து அதிகப் பலன்களைப் பெற இந்த விருப்பங்களில் ஒன்றைப் பயன்படுத்துங்கள்"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"முழுத்திரைக்குச் செல்ல உங்கள் சாதனத்தைச் சுழற்றவும்"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ஆப்ஸை இடம் மாற்ற, ஆப்ஸுக்கு அடுத்து இருமுறை தட்டவும்"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"சரி"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"கூடுதல் தகவல்களுக்கு விரிவாக்கலாம்."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"பெரிதாக்கும்"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"சிறிதாக்கும்"</string>
<string name="close_button_text" msgid="2913281996024033299">"மூடும்"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index cdbe021..2b38018 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"కెమెరా సమస్యలు ఉన్నాయా?\nరీఫిట్ చేయడానికి ట్యాప్ చేయండి"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"దాని సమస్యను పరిష్కరించలేదా?\nపూర్వస్థితికి మార్చడానికి ట్యాప్ చేయండి"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"కెమెరా సమస్యలు లేవా? తీసివేయడానికి ట్యాప్ చేయండి."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"కొన్ని యాప్లు పోర్ట్రెయిట్లో ఉత్తమంగా పని చేస్తాయి"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"మీ ప్రదేశాన్ని ఎక్కువగా ఉపయోగించుకోవడానికి ఈ ఆప్షన్లలో ఒకదాన్ని ట్రై చేయండి"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ఫుల్ స్క్రీన్కు వెళ్లడానికి మీ పరికరాన్ని తిప్పండి"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"యాప్ స్థానాన్ని మార్చడానికి దాని పక్కన డబుల్-ట్యాప్ చేయండి"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"అర్థమైంది"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"మరింత సమాచారం కోసం విస్తరించండి."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"గరిష్టీకరించండి"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"కుదించండి"</string>
<string name="close_button_text" msgid="2913281996024033299">"మూసివేయండి"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml
index 136a81c..f317e4c 100644
--- a/libs/WindowManager/Shell/res/values-th/strings.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"หากพบปัญหากับกล้อง\nแตะเพื่อแก้ไข"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"หากไม่ได้แก้ไข\nแตะเพื่อเปลี่ยนกลับ"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"หากไม่พบปัญหากับกล้อง แตะเพื่อปิด"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"บางแอปทำงานได้ดีที่สุดในแนวตั้ง"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ลองใช้หนึ่งในตัวเลือกเหล่านี้เพื่อให้ได้ประโยชน์สูงสุดจากพื้นที่ว่าง"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"หมุนอุปกรณ์ให้แสดงเต็มหน้าจอ"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"แตะสองครั้งข้างแอปเพื่อเปลี่ยนตำแหน่ง"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"รับทราบ"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ขยายเพื่อดูข้อมูลเพิ่มเติม"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"ขยายใหญ่สุด"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"ย่อ"</string>
<string name="close_button_text" msgid="2913281996024033299">"ปิด"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index 4d32af3..d12875b 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"May mga isyu sa camera?\nI-tap para i-refit"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Hindi ito naayos?\nI-tap para i-revert"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Walang isyu sa camera? I-tap para i-dismiss."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"May ilang app na pinakamainam gamitin nang naka-portrait"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Subukan ang isa sa mga opsyong ito para masulit ang iyong space"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"I-rotate ang iyong device para mag-full screen"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Mag-double tap sa tabi ng isang app para iposisyon ito ulit"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"I-expand para sa higit pang impormasyon."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"I-maximize"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"I-minimize"</string>
<string name="close_button_text" msgid="2913281996024033299">"Isara"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index f3ab370..80d0716 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kameranızda sorun mu var?\nDüzeltmek için dokunun"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Bu işlem sorunu düzeltmedi mi?\nİşlemi geri almak için dokunun"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kameranızda sorun yok mu? Kapatmak için dokunun."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Bazı uygulamalar dikey modda en iyi performansı gösterir"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Alanınızı en verimli şekilde kullanmak için bu seçeneklerden birini deneyin"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Tam ekrana geçmek için cihazınızı döndürün"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Yeniden konumlandırmak için uygulamanın yanına iki kez dokunun"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Anladım"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Daha fazla bilgi için genişletin."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Ekranı Kapla"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Küçült"</string>
<string name="close_button_text" msgid="2913281996024033299">"Kapat"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index d7d82cb..07d0f44 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблеми з камерою?\nНатисніть, щоб пристосувати"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Проблему не вирішено?\nНатисніть, щоб скасувати зміни"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Немає проблем із камерою? Торкніться, щоб закрити."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Деякі додатки найкраще працюють у вертикальній орієнтації"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Щоб максимально ефективно використовувати місце на екрані, спробуйте виконати одну з наведених нижче дій"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Щоб перейти в повноекранний режим, поверніть пристрій"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Щоб перемістити додаток, двічі торкніться області поруч із ним"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"ОK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Розгорніть, щоб дізнатися більше."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Збільшити"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Згорнути"</string>
<string name="close_button_text" msgid="2913281996024033299">"Закрити"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index 4a8476a..4437041 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"کیمرے کے مسائل؟\nدوبارہ فٹ کرنے کیلئے تھپتھپائیں"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"یہ حل نہیں ہوا؟\nلوٹانے کیلئے تھپتھپائیں"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"کوئی کیمرے کا مسئلہ نہیں ہے؟ برخاست کرنے کیلئے تھپتھپائیں۔"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"کچھ ایپس پورٹریٹ میں بہترین کام کرتی ہیں"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"اپنی اسپیس کا زیادہ سے زیادہ فائدہ اٹھانے کے لیے ان اختیارات میں سے ایک کو آزمائیں"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"پوری اسکرین پر جانے کیلئے اپنا آلہ گھمائیں"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"کسی ایپ کی پوزیشن تبدیل کرنے کے لیے اس کے آگے دو بار تھپتھپائیں"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"سمجھ آ گئی"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"مزید معلومات کے لیے پھیلائیں۔"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"بڑا کریں"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"چھوٹا کریں"</string>
<string name="close_button_text" msgid="2913281996024033299">"بند کریں"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index 8a4eac3..78133b0 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamera nosozmi?\nQayta moslash uchun bosing"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Tuzatilmadimi?\nQaytarish uchun bosing"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kamera muammosizmi? Yopish uchun bosing."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Ayrim ilovalar tik holatda ishlashga eng mos"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Muhitdan yanada samarali foydalanish uchun quyidagilardan birini sinang"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Butun ekranda ochish uchun qurilmani buring"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Qayta joylash uchun keyingi ilova ustiga ikki marta bosing"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Batafsil axborot olish uchun kengaytiring."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Yoyish"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Kichraytirish"</string>
<string name="close_button_text" msgid="2913281996024033299">"Yopish"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index 2f8fe60..1e025b3 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Có vấn đề với máy ảnh?\nHãy nhấn để sửa lỗi"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Bạn chưa khắc phục vấn đề?\nHãy nhấn để hủy bỏ"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Không có vấn đề với máy ảnh? Hãy nhấn để đóng."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Một số ứng dụng hoạt động tốt nhất ở chế độ dọc"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Hãy thử một trong các tuỳ chọn sau để tận dụng không gian"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Xoay thiết bị để chuyển sang chế độ toàn màn hình"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Nhấn đúp vào bên cạnh ứng dụng để đặt lại vị trí"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Mở rộng để xem thêm thông tin."</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Phóng to"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Thu nhỏ"</string>
<string name="close_button_text" msgid="2913281996024033299">"Đóng"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index ab44fb1..f3ffcff 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"相机有问题?\n点按即可整修"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"没有解决此问题?\n点按即可恢复"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"相机没有问题?点按即可忽略。"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"某些应用在纵向模式下才能发挥最佳效果"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"这些选项都有助于您最大限度地利用屏幕空间,不妨从中择一试试"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"旋转设备即可进入全屏模式"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"在某个应用旁边连续点按两次,即可调整它的位置"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"知道了"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"展开即可了解详情。"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"最小化"</string>
<string name="close_button_text" msgid="2913281996024033299">"关闭"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index 8fb7ade..1585fec 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"相機有問題?\n輕按即可修正"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"未能修正問題?\n輕按即可還原"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"相機冇問題?㩒一下就可以即可閂咗佢。"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"部分應用程式需要使用直向模式才能發揮最佳效果"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"請嘗試以下選項,充分運用螢幕的畫面空間"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"旋轉裝置方向即可進入全螢幕模式"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"在應用程式旁輕按兩下即可調整位置"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"知道了"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"展開即可查看詳情。"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"最小化"</string>
<string name="close_button_text" msgid="2913281996024033299">"關閉"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index 45de415..e0bdf7e 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"相機有問題嗎?\n輕觸即可修正"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"未修正問題嗎?\n輕觸即可還原"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"相機沒問題嗎?輕觸即可關閉。"</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"某些應用程式在直向模式下才能發揮最佳效果"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"請試試這裡的任一方式,以充分運用螢幕畫面的空間"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"旋轉裝置方向即可進入全螢幕模式"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"在應用程式旁輕觸兩下即可調整位置"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"我知道了"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"展開即可查看詳細資訊。"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"最小化"</string>
<string name="close_button_text" msgid="2913281996024033299">"關閉"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index 7c31a16..07c2213 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -76,12 +76,15 @@
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Izinkinga zekhamera?\nThepha ukuze uyilinganise kabusha"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Akuyilungisanga?\nThepha ukuze ubuyele"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Azikho izinkinga zekhamera? Thepha ukuze ucashise."</string>
- <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Amanye ama-app asebenza ngcono uma eme ngobude"</string>
- <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Zama enye yalezi zinketho ukuze usebenzise isikhala sakho ngokugcwele"</string>
- <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Zungezisa idivayisi yakho ukuze uye esikrinini esigcwele"</string>
- <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Thepha kabili eduze kwe-app ukuze uyimise kabusha"</string>
+ <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) -->
+ <skip />
+ <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) -->
+ <skip />
+ <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) -->
+ <skip />
<string name="letterbox_education_got_it" msgid="4057634570866051177">"Ngiyezwa"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Nweba ukuze uthole ulwazi olwengeziwe"</string>
<string name="maximize_button_text" msgid="1650859196290301963">"Khulisa"</string>
+ <string name="minimize_button_text" msgid="271592547935841753">"Nciphisa"</string>
<string name="close_button_text" msgid="2913281996024033299">"Vala"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 1dac9ca..5696b8d 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -81,6 +81,9 @@
<!-- The width and height of the background for custom action in PiP menu. -->
<dimen name="pip_custom_close_bg_size">32dp</dimen>
+ <!-- Extra padding between picture-in-picture windows and any registered keep clear areas. -->
+ <dimen name="pip_keep_clear_areas_padding">16dp</dimen>
+
<dimen name="dismiss_target_x_size">24dp</dimen>
<dimen name="floating_dismiss_bottom_margin">50dp</dimen>
@@ -246,8 +249,17 @@
<!-- The corner radius of the letterbox education dialog. -->
<dimen name="letterbox_education_dialog_corner_radius">28dp</dimen>
- <!-- The size of an icon in the letterbox education dialog. -->
- <dimen name="letterbox_education_dialog_icon_size">48dp</dimen>
+ <!-- The width of the top icon in the letterbox education dialog. -->
+ <dimen name="letterbox_education_dialog_title_icon_width">45dp</dimen>
+
+ <!-- The height of the top icon in the letterbox education dialog. -->
+ <dimen name="letterbox_education_dialog_title_icon_height">44dp</dimen>
+
+ <!-- The width of an icon in the letterbox education dialog. -->
+ <dimen name="letterbox_education_dialog_icon_width">40dp</dimen>
+
+ <!-- The height of an icon in the letterbox education dialog. -->
+ <dimen name="letterbox_education_dialog_icon_height">32dp</dimen>
<!-- The fixed width of the dialog if there is enough space in the parent. -->
<dimen name="letterbox_education_dialog_width">472dp</dimen>
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml
index 96778a9..1d1162d 100644
--- a/libs/WindowManager/Shell/res/values/strings.xml
+++ b/libs/WindowManager/Shell/res/values/strings.xml
@@ -172,16 +172,13 @@
<string name="camera_compat_dismiss_button_description">No camera issues? Tap to dismiss.</string>
<!-- The title of the letterbox education dialog. [CHAR LIMIT=NONE] -->
- <string name="letterbox_education_dialog_title">Some apps work best in portrait</string>
+ <string name="letterbox_education_dialog_title">See and do more</string>
- <!-- The subtext of the letterbox education dialog. [CHAR LIMIT=NONE] -->
- <string name="letterbox_education_dialog_subtext">Try one of these options to make the most of your space</string>
-
- <!-- Description of the rotate screen action. [CHAR LIMIT=NONE] -->
- <string name="letterbox_education_screen_rotation_text">Rotate your device to go full screen</string>
+ <!-- Description of the split screen action. [CHAR LIMIT=NONE] -->
+ <string name="letterbox_education_split_screen_text">Drag in another app for split-screen</string>
<!-- Description of the reposition app action. [CHAR LIMIT=NONE] -->
- <string name="letterbox_education_reposition_text">Double-tap next to an app to reposition it</string>
+ <string name="letterbox_education_reposition_text">Double-tap outside an app to reposition it</string>
<!-- Button text for dismissing the letterbox education dialog. [CHAR LIMIT=20] -->
<string name="letterbox_education_got_it">Got it</string>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java
new file mode 100644
index 0000000..d276002
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell;
+
+import com.android.wm.shell.protolog.ShellProtoLogImpl;
+import com.android.wm.shell.sysui.ShellCommandHandler;
+import com.android.wm.shell.sysui.ShellInit;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+/**
+ * Controls the {@link ShellProtoLogImpl} in WMShell via adb shell commands.
+ *
+ * Use with {@code adb shell dumpsys activity service SystemUIService WMShell protolog ...}.
+ */
+public class ProtoLogController implements ShellCommandHandler.ShellCommandActionHandler {
+ private final ShellCommandHandler mShellCommandHandler;
+ private final ShellProtoLogImpl mShellProtoLog;
+
+ public ProtoLogController(ShellInit shellInit,
+ ShellCommandHandler shellCommandHandler) {
+ shellInit.addInitCallback(this::onInit, this);
+ mShellCommandHandler = shellCommandHandler;
+ mShellProtoLog = ShellProtoLogImpl.getSingleInstance();
+ }
+
+ void onInit() {
+ mShellCommandHandler.addCommandCallback("protolog", this, this);
+ }
+
+ @Override
+ public boolean onShellCommand(String[] args, PrintWriter pw) {
+ switch (args[0]) {
+ case "status": {
+ pw.println(mShellProtoLog.getStatus());
+ return true;
+ }
+ case "start": {
+ mShellProtoLog.startProtoLog(pw);
+ return true;
+ }
+ case "stop": {
+ mShellProtoLog.stopProtoLog(pw, true /* writeToFile */);
+ return true;
+ }
+ case "enable-text": {
+ String[] groups = Arrays.copyOfRange(args, 1, args.length);
+ int result = mShellProtoLog.startTextLogging(groups, pw);
+ if (result == 0) {
+ pw.println("Starting logging on groups: " + Arrays.toString(groups));
+ return true;
+ }
+ return false;
+ }
+ case "disable-text": {
+ String[] groups = Arrays.copyOfRange(args, 1, args.length);
+ int result = mShellProtoLog.stopTextLogging(groups, pw);
+ if (result == 0) {
+ pw.println("Stopping logging on groups: " + Arrays.toString(groups));
+ return true;
+ }
+ return false;
+ }
+ case "enable": {
+ String[] groups = Arrays.copyOfRange(args, 1, args.length);
+ return mShellProtoLog.startTextLogging(groups, pw) == 0;
+ }
+ case "disable": {
+ String[] groups = Arrays.copyOfRange(args, 1, args.length);
+ return mShellProtoLog.stopTextLogging(groups, pw) == 0;
+ }
+ default: {
+ pw.println("Invalid command: " + args[0]);
+ printShellCommandHelp(pw, "");
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public void printShellCommandHelp(PrintWriter pw, String prefix) {
+ pw.println(prefix + "status");
+ pw.println(prefix + " Get current ProtoLog status.");
+ pw.println(prefix + "start");
+ pw.println(prefix + " Start proto logging.");
+ pw.println(prefix + "stop");
+ pw.println(prefix + " Stop proto logging and flush to file.");
+ pw.println(prefix + "enable [group...]");
+ pw.println(prefix + " Enable proto logging for given groups.");
+ pw.println(prefix + "disable [group...]");
+ pw.println(prefix + " Disable proto logging for given groups.");
+ pw.println(prefix + "enable-text [group...]");
+ pw.println(prefix + " Enable logcat logging for given groups.");
+ pw.println(prefix + "disable-text [group...]");
+ pw.println(prefix + " Disable logcat logging for given groups.");
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index d3e46f8..33ecdd8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -16,6 +16,9 @@
package com.android.wm.shell.back;
+import static android.view.RemoteAnimationTarget.MODE_CLOSING;
+import static android.view.RemoteAnimationTarget.MODE_OPENING;
+
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
@@ -27,8 +30,6 @@
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
-import android.graphics.Point;
-import android.graphics.PointF;
import android.hardware.HardwareBuffer;
import android.hardware.input.InputManager;
import android.net.Uri;
@@ -47,8 +48,11 @@
import android.view.MotionEvent;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
+import android.window.BackAnimationAdaptor;
import android.window.BackEvent;
import android.window.BackNavigationInfo;
+import android.window.IBackAnimationRunner;
+import android.window.IBackNaviAnimationController;
import android.window.IOnBackInvokedCallback;
import com.android.internal.annotations.VisibleForTesting;
@@ -76,22 +80,15 @@
private static final int PROGRESS_THRESHOLD = SystemProperties
.getInt(PREDICTIVE_BACK_PROGRESS_THRESHOLD_PROP, -1);
private final AtomicBoolean mEnableAnimations = new AtomicBoolean(false);
+ // TODO (b/241808055) Find a appropriate time to remove during refactor
+ private static final boolean USE_TRANSITION =
+ SystemProperties.getInt("persist.wm.debug.predictive_back_ani_trans", 1) != 0;
/**
* Max duration to wait for a transition to finish before accepting another gesture start
* request.
*/
private static final long MAX_TRANSITION_DURATION = 2000;
- /**
- * Location of the initial touch event of the back gesture.
- */
- private final PointF mInitTouchLocation = new PointF();
-
- /**
- * Raw delta between {@link #mInitTouchLocation} and the last touch location.
- */
- private final Point mTouchEventDelta = new Point();
-
/** True when a back gesture is ongoing */
private boolean mBackGestureStarted = false;
@@ -119,6 +116,15 @@
mTransitionInProgress = false;
};
+ private RemoteAnimationTarget mAnimationTarget;
+ IBackAnimationRunner mIBackAnimationRunner;
+ private IBackNaviAnimationController mBackAnimationController;
+ private BackAnimationAdaptor mBackAnimationAdaptor;
+
+ private boolean mWaitingAnimationStart;
+ private final TouchTracker mTouchTracker = new TouchTracker();
+ private final CachingBackDispatcher mCachingBackDispatcher = new CachingBackDispatcher();
+
@VisibleForTesting
final IWindowFocusObserver mFocusObserver = new IWindowFocusObserver.Stub() {
@Override
@@ -137,6 +143,92 @@
}
};
+ /**
+ * Helper class to record the touch location for gesture start and latest.
+ */
+ private static class TouchTracker {
+ /**
+ * Location of the latest touch event
+ */
+ private float mLatestTouchX;
+ private float mLatestTouchY;
+ private int mSwipeEdge;
+
+ /**
+ * Location of the initial touch event of the back gesture.
+ */
+ private float mInitTouchX;
+ private float mInitTouchY;
+
+ void update(float touchX, float touchY, int swipeEdge) {
+ mLatestTouchX = touchX;
+ mLatestTouchY = touchY;
+ mSwipeEdge = swipeEdge;
+ }
+
+ void setGestureStartLocation(float touchX, float touchY) {
+ mInitTouchX = touchX;
+ mInitTouchY = touchY;
+ }
+
+ int getDeltaFromGestureStart(float touchX) {
+ return Math.round(touchX - mInitTouchX);
+ }
+
+ void reset() {
+ mInitTouchX = 0;
+ mInitTouchY = 0;
+ }
+ }
+
+ /**
+ * Cache the temporary callback and trigger result if gesture was finish before received
+ * BackAnimationRunner#onAnimationStart/cancel, so there can continue play the animation.
+ */
+ private class CachingBackDispatcher {
+ private IOnBackInvokedCallback mOnBackCallback;
+ private boolean mTriggerBack;
+ // Whether we are waiting to receive onAnimationStart
+ private boolean mWaitingAnimation;
+
+ void startWaitingAnimation() {
+ mWaitingAnimation = true;
+ }
+
+ boolean set(IOnBackInvokedCallback callback, boolean triggerBack) {
+ if (mWaitingAnimation) {
+ mOnBackCallback = callback;
+ mTriggerBack = triggerBack;
+ return true;
+ }
+ return false;
+ }
+
+ boolean consume() {
+ boolean consumed = false;
+ if (mWaitingAnimation && mOnBackCallback != null) {
+ if (mTriggerBack) {
+ final BackEvent backFinish = new BackEvent(
+ mTouchTracker.mLatestTouchX, mTouchTracker.mLatestTouchY, 1,
+ mTouchTracker.mSwipeEdge, mAnimationTarget);
+ dispatchOnBackProgressed(mBackToLauncherCallback, backFinish);
+ dispatchOnBackInvoked(mOnBackCallback);
+ } else {
+ final BackEvent backFinish = new BackEvent(
+ mTouchTracker.mLatestTouchX, mTouchTracker.mLatestTouchY, 0,
+ mTouchTracker.mSwipeEdge, mAnimationTarget);
+ dispatchOnBackProgressed(mBackToLauncherCallback, backFinish);
+ dispatchOnBackCancelled(mOnBackCallback);
+ }
+ startTransition();
+ consumed = true;
+ }
+ mOnBackCallback = null;
+ mWaitingAnimation = false;
+ return consumed;
+ }
+ }
+
public BackAnimationController(
@NonNull ShellInit shellInit,
@NonNull @ShellMainThread ShellExecutor shellExecutor,
@@ -272,6 +364,9 @@
@VisibleForTesting
void setBackToLauncherCallback(IOnBackInvokedCallback callback) {
mBackToLauncherCallback = callback;
+ if (USE_TRANSITION) {
+ createAdaptor();
+ }
}
private void clearBackToLauncherCallback() {
@@ -280,15 +375,18 @@
@VisibleForTesting
void onBackToLauncherAnimationFinished() {
- if (mBackNavigationInfo != null) {
- IOnBackInvokedCallback callback = mBackNavigationInfo.getOnBackInvokedCallback();
- if (mTriggerBack) {
+ final boolean triggerBack = mTriggerBack;
+ IOnBackInvokedCallback callback = mBackNavigationInfo != null
+ ? mBackNavigationInfo.getOnBackInvokedCallback() : null;
+ // Make sure the notification sequence should be controller > client.
+ finishAnimation();
+ if (callback != null) {
+ if (triggerBack) {
dispatchOnBackInvoked(callback);
} else {
dispatchOnBackCancelled(callback);
}
}
- finishAnimation();
}
/**
@@ -300,6 +398,8 @@
if (mTransitionInProgress) {
return;
}
+
+ mTouchTracker.update(touchX, touchY, swipeEdge);
if (keyAction == MotionEvent.ACTION_DOWN) {
if (!mBackGestureStarted) {
mShouldStartOnNextMoveEvent = true;
@@ -330,13 +430,13 @@
finishAnimation();
}
- mInitTouchLocation.set(touchX, touchY);
+ mTouchTracker.setGestureStartLocation(touchX, touchY);
mBackGestureStarted = true;
try {
boolean requestAnimation = mEnableAnimations.get();
- mBackNavigationInfo =
- mActivityTaskManager.startBackNavigation(requestAnimation, mFocusObserver);
+ mBackNavigationInfo = mActivityTaskManager.startBackNavigation(requestAnimation,
+ mFocusObserver, mBackAnimationAdaptor);
onBackNavigationInfoReceived(mBackNavigationInfo);
} catch (RemoteException remoteException) {
Log.e(TAG, "Failed to initAnimation", remoteException);
@@ -352,6 +452,7 @@
}
int backType = backNavigationInfo.getType();
IOnBackInvokedCallback targetCallback = null;
+ final boolean dispatchToLauncher = shouldDispatchToLauncher(backType);
if (backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
HardwareBuffer hardwareBuffer = backNavigationInfo.getScreenshotHardwareBuffer();
if (hardwareBuffer != null) {
@@ -359,12 +460,17 @@
backNavigationInfo.getTaskWindowConfiguration());
}
mTransaction.apply();
- } else if (shouldDispatchToLauncher(backType)) {
+ } else if (dispatchToLauncher) {
targetCallback = mBackToLauncherCallback;
+ if (USE_TRANSITION) {
+ mCachingBackDispatcher.startWaitingAnimation();
+ }
} else if (backType == BackNavigationInfo.TYPE_CALLBACK) {
targetCallback = mBackNavigationInfo.getOnBackInvokedCallback();
}
- dispatchOnBackStarted(targetCallback);
+ if (!USE_TRANSITION || !dispatchToLauncher) {
+ dispatchOnBackStarted(targetCallback);
+ }
}
/**
@@ -403,24 +509,33 @@
if (!mBackGestureStarted || mBackNavigationInfo == null) {
return;
}
- int deltaX = Math.round(touchX - mInitTouchLocation.x);
+ int deltaX = mTouchTracker.getDeltaFromGestureStart(touchX);
float progressThreshold = PROGRESS_THRESHOLD >= 0 ? PROGRESS_THRESHOLD : mProgressThreshold;
float progress = Math.min(Math.max(Math.abs(deltaX) / progressThreshold, 0), 1);
- int backType = mBackNavigationInfo.getType();
- RemoteAnimationTarget animationTarget = mBackNavigationInfo.getDepartingAnimationTarget();
+ if (USE_TRANSITION) {
+ if (mBackAnimationController != null && mAnimationTarget != null) {
+ final BackEvent backEvent = new BackEvent(
+ touchX, touchY, progress, swipeEdge, mAnimationTarget);
+ dispatchOnBackProgressed(mBackToLauncherCallback, backEvent);
+ }
+ } else {
+ int backType = mBackNavigationInfo.getType();
+ RemoteAnimationTarget animationTarget =
+ mBackNavigationInfo.getDepartingAnimationTarget();
- BackEvent backEvent = new BackEvent(
- touchX, touchY, progress, swipeEdge, animationTarget);
- IOnBackInvokedCallback targetCallback = null;
- if (shouldDispatchToLauncher(backType)) {
- targetCallback = mBackToLauncherCallback;
- } else if (backType == BackNavigationInfo.TYPE_CROSS_TASK
- || backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
- // TODO(208427216) Run the actual animation
- } else if (backType == BackNavigationInfo.TYPE_CALLBACK) {
- targetCallback = mBackNavigationInfo.getOnBackInvokedCallback();
+ BackEvent backEvent = new BackEvent(
+ touchX, touchY, progress, swipeEdge, animationTarget);
+ IOnBackInvokedCallback targetCallback = null;
+ if (shouldDispatchToLauncher(backType)) {
+ targetCallback = mBackToLauncherCallback;
+ } else if (backType == BackNavigationInfo.TYPE_CROSS_TASK
+ || backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
+ // TODO(208427216) Run the actual animation
+ } else if (backType == BackNavigationInfo.TYPE_CALLBACK) {
+ targetCallback = mBackNavigationInfo.getOnBackInvokedCallback();
+ }
+ dispatchOnBackProgressed(targetCallback, backEvent);
}
- dispatchOnBackProgressed(targetCallback, backEvent);
}
private void injectBackKey() {
@@ -474,6 +589,9 @@
IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher
? mBackToLauncherCallback
: mBackNavigationInfo.getOnBackInvokedCallback();
+ if (mCachingBackDispatcher.set(targetCallback, mTriggerBack)) {
+ return;
+ }
if (shouldDispatchToLauncher) {
startTransition();
}
@@ -493,7 +611,8 @@
&& mBackToLauncherCallback != null
&& mEnableAnimations.get()
&& mBackNavigationInfo != null
- && mBackNavigationInfo.getDepartingAnimationTarget() != null;
+ && ((USE_TRANSITION && mBackNavigationInfo.isPrepareRemoteAnimation())
+ || mBackNavigationInfo.getDepartingAnimationTarget() != null);
}
private static void dispatchOnBackStarted(IOnBackInvokedCallback callback) {
@@ -558,8 +677,7 @@
private void finishAnimation() {
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishAnimation()");
- mTouchEventDelta.set(0, 0);
- mInitTouchLocation.set(0, 0);
+ mTouchTracker.reset();
BackNavigationInfo backNavigationInfo = mBackNavigationInfo;
boolean triggerBack = mTriggerBack;
mBackNavigationInfo = null;
@@ -569,19 +687,33 @@
return;
}
- RemoteAnimationTarget animationTarget = backNavigationInfo.getDepartingAnimationTarget();
- if (animationTarget != null) {
- if (animationTarget.leash != null && animationTarget.leash.isValid()) {
- mTransaction.remove(animationTarget.leash);
+ if (!USE_TRANSITION) {
+ RemoteAnimationTarget animationTarget = backNavigationInfo
+ .getDepartingAnimationTarget();
+ if (animationTarget != null) {
+ if (animationTarget.leash != null && animationTarget.leash.isValid()) {
+ mTransaction.remove(animationTarget.leash);
+ }
}
+ SurfaceControl screenshotSurface = backNavigationInfo.getScreenshotSurface();
+ if (screenshotSurface != null && screenshotSurface.isValid()) {
+ mTransaction.remove(screenshotSurface);
+ }
+ mTransaction.apply();
}
- SurfaceControl screenshotSurface = backNavigationInfo.getScreenshotSurface();
- if (screenshotSurface != null && screenshotSurface.isValid()) {
- mTransaction.remove(screenshotSurface);
- }
- mTransaction.apply();
stopTransition();
backNavigationInfo.onBackNavigationFinished(triggerBack);
+ if (USE_TRANSITION) {
+ final IBackNaviAnimationController controller = mBackAnimationController;
+ if (controller != null) {
+ try {
+ controller.finish(triggerBack);
+ } catch (RemoteException r) {
+ // Oh no!
+ }
+ }
+ mBackAnimationController = null;
+ }
}
private void startTransition() {
@@ -599,4 +731,50 @@
mShellExecutor.removeCallbacks(mResetTransitionRunnable);
mTransitionInProgress = false;
}
+
+ private void createAdaptor() {
+ mIBackAnimationRunner = new IBackAnimationRunner.Stub() {
+ @Override
+ public void onAnimationCancelled() {
+ // no op for now
+ }
+ @Override // Binder interface
+ public void onAnimationStart(IBackNaviAnimationController controller, int type,
+ RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
+ RemoteAnimationTarget[] nonApps) {
+ mShellExecutor.execute(() -> {
+ mBackAnimationController = controller;
+ for (int i = 0; i < apps.length; i++) {
+ final RemoteAnimationTarget target = apps[i];
+ if (MODE_CLOSING == target.mode) {
+ mAnimationTarget = target;
+ } else if (MODE_OPENING == target.mode) {
+ // TODO Home activity should handle the visibility for itself
+ // once it finish relayout for orientation change
+ SurfaceControl.Transaction tx =
+ new SurfaceControl.Transaction();
+ tx.setAlpha(target.leash, 1);
+ tx.apply();
+ }
+ }
+ // TODO animation target should be passed at onBackStarted
+ dispatchOnBackStarted(mBackToLauncherCallback);
+ // TODO This is Workaround for LauncherBackAnimationController, there will need
+ // to dispatch onBackProgressed twice(startBack & updateBackProgress) to
+ // initialize the animation data, for now that would happen when onMove
+ // called, but there will no expected animation if the down -> up gesture
+ // happen very fast which ACTION_MOVE only happen once.
+ final BackEvent backInit = new BackEvent(
+ mTouchTracker.mLatestTouchX, mTouchTracker.mLatestTouchY, 0,
+ mTouchTracker.mSwipeEdge, mAnimationTarget);
+ dispatchOnBackProgressed(mBackToLauncherCallback, backInit);
+ if (!mCachingBackDispatcher.consume()) {
+ dispatchOnBackProgressed(mBackToLauncherCallback, backInit);
+ }
+ });
+ }
+ };
+ mBackAnimationAdaptor = new BackAnimationAdaptor(mIBackAnimationRunner,
+ BackNavigationInfo.TYPE_RETURN_TO_HOME);
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index dcbb272..d63c25d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1387,9 +1387,6 @@
if (update.selectionChanged && mStackView != null) {
mStackView.setSelectedBubble(update.selectedBubble);
- if (update.selectedBubble != null) {
- mSysuiProxy.updateNotificationSuppression(update.selectedBubble.getKey());
- }
}
// Expanding? Apply this last.
@@ -1448,7 +1445,6 @@
// in the shade, it is essentially removed.
Bubble bubbleChild = mBubbleData.getAnyBubbleWithkey(child.getKey());
if (bubbleChild != null) {
- mSysuiProxy.removeNotificationEntry(bubbleChild.getKey());
bubbleChild.setSuppressNotification(true);
bubbleChild.setShowDot(false /* show */);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 5bf88b1..aeaf6ed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -111,6 +111,9 @@
public static final boolean HOME_GESTURE_ENABLED =
SystemProperties.getBoolean("persist.wm.debug.bubbles_home_gesture", true);
+ public static final boolean ENABLE_FLING_TO_DISMISS_BUBBLE =
+ SystemProperties.getBoolean("persist.wm.debug.fling_to_dismiss_bubble", true);
+
private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleStackView" : TAG_BUBBLES;
/** How far the flyout needs to be dragged before it's dismissed regardless of velocity. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
index 0e97e9e..453b34e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
@@ -278,12 +278,8 @@
void notifyMaybeCancelSummary(String key);
- void removeNotificationEntry(String key);
-
void updateNotificationBubbleButton(String key);
- void updateNotificationSuppression(String key);
-
void onStackExpandChanged(boolean shouldExpand);
void onManageMenuExpandChanged(boolean menuExpanded);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
index ae434bc..b91062f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
@@ -19,6 +19,7 @@
import static android.view.View.LAYOUT_DIRECTION_RTL;
import static com.android.wm.shell.bubbles.BubblePositioner.NUM_VISIBLE_WHEN_RESTING;
+import static com.android.wm.shell.bubbles.BubbleStackView.ENABLE_FLING_TO_DISMISS_BUBBLE;
import static com.android.wm.shell.bubbles.BubbleStackView.HOME_GESTURE_ENABLED;
import android.content.res.Resources;
@@ -366,6 +367,7 @@
mMagnetizedBubbleDraggingOut.setMagnetListener(listener);
mMagnetizedBubbleDraggingOut.setHapticsEnabled(true);
mMagnetizedBubbleDraggingOut.setFlingToTargetMinVelocity(FLING_TO_DISMISS_MIN_VELOCITY);
+ mMagnetizedBubbleDraggingOut.setFlingToTargetEnabled(ENABLE_FLING_TO_DISMISS_BUBBLE);
}
private void springBubbleTo(View bubble, float x, float y) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
index 4e2cbfd..961722b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
@@ -17,6 +17,7 @@
package com.android.wm.shell.bubbles.animation;
import static com.android.wm.shell.bubbles.BubblePositioner.NUM_VISIBLE_WHEN_RESTING;
+import static com.android.wm.shell.bubbles.BubbleStackView.ENABLE_FLING_TO_DISMISS_BUBBLE;
import android.content.ContentResolver;
import android.content.res.Resources;
@@ -1028,6 +1029,7 @@
};
mMagnetizedStack.setHapticsEnabled(true);
mMagnetizedStack.setFlingToTargetMinVelocity(FLING_TO_DISMISS_MIN_VELOCITY);
+ mMagnetizedStack.setFlingToTargetEnabled(ENABLE_FLING_TO_DISMISS_BUBBLE);
}
final ContentResolver contentResolver = mLayout.getContext().getContentResolver();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 83ba909..4c85d20 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -148,9 +148,7 @@
mDimNonImeSide = resources.getBoolean(R.bool.config_dimNonImeAttachedSide);
- mInvisibleBounds.set(mRootBounds);
- mInvisibleBounds.offset(isLandscape() ? mRootBounds.right : 0,
- isLandscape() ? 0 : mRootBounds.bottom);
+ updateInvisibleRect();
}
private int getDividerInsets(Resources resources, Display display) {
@@ -274,6 +272,14 @@
: (float) ((mBounds1.bottom + mBounds2.top) / 2f) / mBounds2.bottom));
}
+ private void updateInvisibleRect() {
+ mInvisibleBounds.set(mRootBounds.left, mRootBounds.top,
+ isLandscape() ? mRootBounds.right / 2 : mRootBounds.right,
+ isLandscape() ? mRootBounds.bottom : mRootBounds.bottom / 2);
+ mInvisibleBounds.offset(isLandscape() ? mRootBounds.right : 0,
+ isLandscape() ? 0 : mRootBounds.bottom);
+ }
+
/** Applies new configuration, returns {@code false} if there's no effect to the layout. */
public boolean updateConfiguration(Configuration configuration) {
// Update the split bounds when necessary. Besides root bounds changed, split bounds need to
@@ -299,10 +305,7 @@
mRotation = rotation;
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
initDividerPosition(mTempRect);
-
- mInvisibleBounds.set(mRootBounds);
- mInvisibleBounds.offset(isLandscape() ? mRootBounds.right : 0,
- isLandscape() ? 0 : mRootBounds.bottom);
+ updateInvisibleRect();
return true;
}
@@ -520,11 +523,9 @@
final Rect insets = stableInsets != null ? stableInsets : getDisplayInsets(context);
// Make split axis insets value same as the larger one to avoid bounds1 and bounds2
- // have difference after split switching for solving issues on non-resizable app case.
- if (isLandscape) {
- final int largerInsets = Math.max(insets.left, insets.right);
- insets.set(largerInsets, insets.top, largerInsets, insets.bottom);
- } else {
+ // have difference for avoiding size-compat mode when switching unresizable apps in
+ // landscape while they are letterboxed.
+ if (!isLandscape) {
final int largerInsets = Math.max(insets.top, insets.bottom);
insets.set(insets.left, largerInsets, insets.right, largerInsets);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index ceaa64e..c39602032 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -27,6 +27,7 @@
import com.android.internal.logging.UiEventLogger;
import com.android.launcher3.icons.IconProvider;
+import com.android.wm.shell.ProtoLogController;
import com.android.wm.shell.RootDisplayAreaOrganizer;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -85,6 +86,7 @@
import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
import com.android.wm.shell.unfold.UnfoldAnimationController;
import com.android.wm.shell.unfold.UnfoldTransitionHandler;
+import com.android.wm.shell.windowdecor.WindowDecorViewModel;
import java.util.Optional;
@@ -294,25 +296,33 @@
// Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
@BindsOptionalOf
@DynamicOverride
- abstract FullscreenTaskListener optionalFullscreenTaskListener();
+ abstract FullscreenTaskListener<?> optionalFullscreenTaskListener();
@WMSingleton
@Provides
- static FullscreenTaskListener provideFullscreenTaskListener(
- @DynamicOverride Optional<FullscreenTaskListener> fullscreenTaskListener,
+ static FullscreenTaskListener<?> provideFullscreenTaskListener(
+ @DynamicOverride Optional<FullscreenTaskListener<?>> fullscreenTaskListener,
ShellInit shellInit,
ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue,
- Optional<RecentTasksController> recentTasksOptional) {
+ Optional<RecentTasksController> recentTasksOptional,
+ Optional<WindowDecorViewModel<?>> windowDecorViewModelOptional) {
if (fullscreenTaskListener.isPresent()) {
return fullscreenTaskListener.get();
} else {
return new FullscreenTaskListener(shellInit, shellTaskOrganizer, syncQueue,
- recentTasksOptional);
+ recentTasksOptional, windowDecorViewModelOptional);
}
}
//
+ // Window Decoration
+ //
+
+ @BindsOptionalOf
+ abstract WindowDecorViewModel<?> optionalWindowDecorViewModel();
+
+ //
// Unfold transition
//
@@ -680,7 +690,7 @@
Optional<SplitScreenController> splitScreenOptional,
Optional<Pip> pipOptional,
Optional<PipTouchHandler> pipTouchHandlerOptional,
- FullscreenTaskListener fullscreenTaskListener,
+ FullscreenTaskListener<?> fullscreenTaskListener,
Optional<UnfoldAnimationController> unfoldAnimationController,
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
Optional<FreeformComponents> freeformComponents,
@@ -690,6 +700,7 @@
Optional<ActivityEmbeddingController> activityEmbeddingOptional,
Transitions transitions,
StartingWindowController startingWindow,
+ ProtoLogController protoLogController,
@ShellCreateTriggerOverride Optional<Object> overriddenCreateTrigger) {
return new Object();
}
@@ -705,4 +716,12 @@
static ShellCommandHandler provideShellCommandHandler() {
return new ShellCommandHandler();
}
+
+ @WMSingleton
+ @Provides
+ static ProtoLogController provideProtoLogController(
+ ShellInit shellInit,
+ ShellCommandHandler shellCommandHandler) {
+ return new ProtoLogController(shellInit, shellCommandHandler);
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 4fe3255..b7656de 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -49,12 +49,14 @@
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ShellBackgroundThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
-import com.android.wm.shell.desktopmode.DesktopModeConstants;
+import com.android.wm.shell.desktopmode.DesktopMode;
import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.freeform.FreeformComponents;
import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.freeform.FreeformTaskTransitionHandler;
+import com.android.wm.shell.freeform.FreeformTaskTransitionObserver;
+import com.android.wm.shell.fullscreen.FullscreenTaskListener;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
@@ -70,9 +72,9 @@
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip.PipTransitionState;
import com.android.wm.shell.pip.PipUiEventLogger;
+import com.android.wm.shell.pip.phone.PhonePipKeepClearAlgorithm;
import com.android.wm.shell.pip.phone.PhonePipMenuController;
import com.android.wm.shell.pip.phone.PipController;
-import com.android.wm.shell.pip.phone.PipKeepClearAlgorithm;
import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.pip.phone.PipTouchHandler;
import com.android.wm.shell.recents.RecentTasksController;
@@ -206,8 +208,10 @@
@DynamicOverride
static FreeformComponents provideFreeformComponents(
FreeformTaskListener<?> taskListener,
- FreeformTaskTransitionHandler transitionHandler) {
- return new FreeformComponents(taskListener, Optional.of(transitionHandler));
+ FreeformTaskTransitionHandler transitionHandler,
+ FreeformTaskTransitionObserver transitionObserver) {
+ return new FreeformComponents(
+ taskListener, Optional.of(transitionHandler), Optional.of(transitionObserver));
}
@WMSingleton
@@ -229,18 +233,22 @@
@WMSingleton
@Provides
static FreeformTaskTransitionHandler provideFreeformTaskTransitionHandler(
+ ShellInit shellInit,
+ Transitions transitions,
+ WindowDecorViewModel<?> windowDecorViewModel) {
+ return new FreeformTaskTransitionHandler(shellInit, transitions, windowDecorViewModel);
+ }
+
+ @WMSingleton
+ @Provides
+ static FreeformTaskTransitionObserver provideFreeformTaskTransitionObserver(
Context context,
ShellInit shellInit,
Transitions transitions,
- WindowDecorViewModel<?> windowDecorViewModel,
+ FullscreenTaskListener<?> fullscreenTaskListener,
FreeformTaskListener<?> freeformTaskListener) {
- // TODO(b/238217847): Temporarily add this check here until we can remove the dynamic
- // override for this controller from the base module
- ShellInit init = FreeformComponents.isFreeformEnabled(context)
- ? shellInit
- : null;
- return new FreeformTaskTransitionHandler(init, transitions,
- windowDecorViewModel, freeformTaskListener);
+ return new FreeformTaskTransitionObserver(
+ context, shellInit, transitions, fullscreenTaskListener, freeformTaskListener);
}
//
@@ -312,7 +320,7 @@
DisplayController displayController,
PipAppOpsListener pipAppOpsListener,
PipBoundsAlgorithm pipBoundsAlgorithm,
- PipKeepClearAlgorithm pipKeepClearAlgorithm,
+ PhonePipKeepClearAlgorithm pipKeepClearAlgorithm,
PipBoundsState pipBoundsState,
PipMotionHelper pipMotionHelper,
PipMediaController pipMediaController,
@@ -349,15 +357,17 @@
@WMSingleton
@Provides
- static PipKeepClearAlgorithm providePipKeepClearAlgorithm() {
- return new PipKeepClearAlgorithm();
+ static PhonePipKeepClearAlgorithm providePhonePipKeepClearAlgorithm(Context context) {
+ return new PhonePipKeepClearAlgorithm(context);
}
@WMSingleton
@Provides
static PipBoundsAlgorithm providesPipBoundsAlgorithm(Context context,
- PipBoundsState pipBoundsState, PipSnapAlgorithm pipSnapAlgorithm) {
- return new PipBoundsAlgorithm(context, pipBoundsState, pipSnapAlgorithm);
+ PipBoundsState pipBoundsState, PipSnapAlgorithm pipSnapAlgorithm,
+ PhonePipKeepClearAlgorithm pipKeepClearAlgorithm) {
+ return new PipBoundsAlgorithm(context, pipBoundsState, pipSnapAlgorithm,
+ pipKeepClearAlgorithm);
}
// Handler is used by Icon.loadDrawableAsync
@@ -589,7 +599,7 @@
RootDisplayAreaOrganizer rootDisplayAreaOrganizer,
@ShellMainThread Handler mainHandler
) {
- if (DesktopModeConstants.IS_FEATURE_ENABLED) {
+ if (DesktopMode.IS_SUPPORTED) {
return Optional.of(new DesktopModeController(context, shellInit, shellTaskOrganizer,
rootDisplayAreaOrganizer,
mainHandler));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java
new file mode 100644
index 0000000..64cec2a
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.desktopmode;
+
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.internal.protolog.common.ProtoLog;
+
+/**
+ * Constants for desktop mode feature
+ */
+public class DesktopMode {
+
+ /**
+ * Flag to indicate whether desktop mode is available on the device
+ */
+ public static final boolean IS_SUPPORTED = SystemProperties.getBoolean(
+ "persist.wm.debug.desktop_mode", false);
+
+ /**
+ * Check if desktop mode is active
+ *
+ * @return {@code true} if active
+ */
+ public static boolean isActive(Context context) {
+ if (!IS_SUPPORTED) {
+ return false;
+ }
+ try {
+ int result = Settings.System.getIntForUser(context.getContentResolver(),
+ Settings.System.DESKTOP_MODE, UserHandle.USER_CURRENT);
+ ProtoLog.d(WM_SHELL_DESKTOP_MODE, "isDesktopModeEnabled=%s", result);
+ return result != 0;
+ } catch (Settings.SettingNotFoundException e) {
+ ProtoLog.e(WM_SHELL_DESKTOP_MODE, "Failed to read DESKTOP_MODE setting %s", e);
+ return false;
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
index 5849e16..295035f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
@@ -65,8 +65,8 @@
}
@VisibleForTesting
- void updateDesktopModeEnabled(boolean enabled) {
- ProtoLog.d(WM_SHELL_DESKTOP_MODE, "updateDesktopModeState: enabled=%s", enabled);
+ void updateDesktopModeActive(boolean active) {
+ ProtoLog.d(WM_SHELL_DESKTOP_MODE, "updateDesktopModeActive: active=%s", active);
int displayId = mContext.getDisplayId();
@@ -75,7 +75,7 @@
// container value)
wct.merge(mShellTaskOrganizer.prepareClearFreeformForTasks(displayId), true /* transfer */);
int targetWindowingMode;
- if (enabled) {
+ if (active) {
targetWindowingMode = WINDOWING_MODE_FREEFORM;
} else {
targetWindowingMode = WINDOWING_MODE_FULLSCREEN;
@@ -118,20 +118,8 @@
}
private void desktopModeSettingChanged() {
- boolean enabled = isDesktopModeEnabled();
- updateDesktopModeEnabled(enabled);
- }
-
- private boolean isDesktopModeEnabled() {
- try {
- int result = Settings.System.getIntForUser(mContext.getContentResolver(),
- Settings.System.DESKTOP_MODE, UserHandle.USER_CURRENT);
- ProtoLog.d(WM_SHELL_DESKTOP_MODE, "isDesktopModeEnabled=%s", result);
- return result != 0;
- } catch (Settings.SettingNotFoundException e) {
- ProtoLog.e(WM_SHELL_DESKTOP_MODE, "Failed to read DESKTOP_MODE setting %s", e);
- return false;
- }
+ boolean enabled = DesktopMode.isActive(mContext);
+ updateDesktopModeActive(enabled);
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformComponents.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformComponents.java
index 41e1b1d..eee5aae 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformComponents.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformComponents.java
@@ -33,16 +33,19 @@
*/
public class FreeformComponents {
public final ShellTaskOrganizer.TaskListener mTaskListener;
- public final Optional<Transitions.TransitionHandler> mTaskTransitionHandler;
+ public final Optional<Transitions.TransitionHandler> mTransitionHandler;
+ public final Optional<Transitions.TransitionObserver> mTransitionObserver;
/**
* Creates an instance with the given components.
*/
public FreeformComponents(
ShellTaskOrganizer.TaskListener taskListener,
- Optional<Transitions.TransitionHandler> taskTransitionHandler) {
+ Optional<Transitions.TransitionHandler> transitionHandler,
+ Optional<Transitions.TransitionObserver> transitionObserver) {
mTaskListener = taskListener;
- mTaskTransitionHandler = taskTransitionHandler;
+ mTransitionHandler = transitionHandler;
+ mTransitionObserver = transitionObserver;
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index ab66107..8dcdda1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -187,12 +187,14 @@
RunningTaskInfo taskInfo,
SurfaceControl.Transaction startT,
SurfaceControl.Transaction finishT) {
- T windowDecor = mWindowDecorOfVanishedTasks.get(taskInfo.taskId);
- mWindowDecorOfVanishedTasks.remove(taskInfo.taskId);
+ T windowDecor;
final State<T> state = mTasks.get(taskInfo.taskId);
if (state != null) {
- windowDecor = windowDecor == null ? state.mWindowDecoration : windowDecor;
+ windowDecor = state.mWindowDecoration;
state.mWindowDecoration = null;
+ } else {
+ windowDecor =
+ mWindowDecorOfVanishedTasks.removeReturnOld(taskInfo.taskId);
}
mWindowDecorationViewModel.setupWindowDecorationForTransition(
taskInfo, startT, finishT, windowDecor);
@@ -231,7 +233,8 @@
if (mWindowDecorOfVanishedTasks.size() == 0) {
return;
}
- Log.w(TAG, "Clearing window decors of vanished tasks. There could be visual defects "
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ "Clearing window decors of vanished tasks. There could be visual defects "
+ "if any of them is used later in transitions.");
for (int i = 0; i < mWindowDecorOfVanishedTasks.size(); ++i) {
releaseWindowDecor(mWindowDecorOfVanishedTasks.valueAt(i));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
index a1e9f93..fd4c85fa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
@@ -22,7 +22,6 @@
import android.app.ActivityManager;
import android.app.WindowConfiguration;
import android.os.IBinder;
-import android.util.Log;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.TransitionInfo;
@@ -40,16 +39,13 @@
import java.util.List;
/**
- * The {@link Transitions.TransitionHandler} that handles freeform task launches, closes,
- * maximizing and restoring transitions. It also reports transitions so that window decorations can
- * be a part of transitions.
+ * The {@link Transitions.TransitionHandler} that handles freeform task maximizing and restoring
+ * transitions.
*/
public class FreeformTaskTransitionHandler
implements Transitions.TransitionHandler, FreeformTaskTransitionStarter {
- private static final String TAG = "FreeformTH";
private final Transitions mTransitions;
- private final FreeformTaskListener<?> mFreeformTaskListener;
private final WindowDecorViewModel<?> mWindowDecorViewModel;
private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
@@ -57,19 +53,16 @@
public FreeformTaskTransitionHandler(
ShellInit shellInit,
Transitions transitions,
- WindowDecorViewModel<?> windowDecorViewModel,
- FreeformTaskListener<?> freeformTaskListener) {
+ WindowDecorViewModel<?> windowDecorViewModel) {
mTransitions = transitions;
- mFreeformTaskListener = freeformTaskListener;
mWindowDecorViewModel = windowDecorViewModel;
- if (shellInit != null && Transitions.ENABLE_SHELL_TRANSITIONS) {
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
shellInit.addInitCallback(this::onInit, this);
}
}
private void onInit() {
mWindowDecorViewModel.setFreeformTaskTransitionStarter(this);
- mTransitions.addHandler(this);
}
@Override
@@ -97,13 +90,19 @@
mPendingTransitionTokens.add(mTransitions.startTransition(type, wct, this));
}
+
+ @Override
+ public void startRemoveTransition(WindowContainerTransaction wct) {
+ final int type = WindowManager.TRANSIT_CLOSE;
+ mPendingTransitionTokens.add(mTransitions.startTransition(type, wct, this));
+ }
+
@Override
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startT,
@NonNull SurfaceControl.Transaction finishT,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
boolean transitionHandled = false;
- final ArrayList<AutoCloseable> windowDecorsInCloseTransitions = new ArrayList<>();
for (TransitionInfo.Change change : info.getChanges()) {
if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) {
continue;
@@ -115,22 +114,13 @@
}
switch (change.getMode()) {
- case WindowManager.TRANSIT_OPEN:
- transitionHandled |= startOpenTransition(change, startT, finishT);
- break;
- case WindowManager.TRANSIT_CLOSE:
- transitionHandled |= startCloseTransition(
- change, windowDecorsInCloseTransitions, startT, finishT);
- break;
case WindowManager.TRANSIT_CHANGE:
transitionHandled |= startChangeTransition(
- transition, info.getType(), change, startT, finishT);
+ transition, info.getType(), change);
break;
case WindowManager.TRANSIT_TO_BACK:
transitionHandled |= startMinimizeTransition(transition);
break;
- case WindowManager.TRANSIT_TO_FRONT:
- break;
}
}
@@ -142,56 +132,14 @@
startT.apply();
mTransitions.getMainExecutor().execute(
- () -> finishTransition(windowDecorsInCloseTransitions, finishCallback));
- return true;
- }
-
- private boolean startOpenTransition(
- TransitionInfo.Change change,
- SurfaceControl.Transaction startT,
- SurfaceControl.Transaction finishT) {
- if (change.getTaskInfo().getWindowingMode() != WINDOWING_MODE_FREEFORM) {
- return false;
- }
- mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
-
- // Intercepted transition to manage the window decorations. Let other handlers animate.
- return false;
- }
-
- private boolean startCloseTransition(
- TransitionInfo.Change change,
- ArrayList<AutoCloseable> windowDecors,
- SurfaceControl.Transaction startT,
- SurfaceControl.Transaction finishT) {
- if (change.getTaskInfo().getWindowingMode() != WINDOWING_MODE_FREEFORM) {
- return false;
- }
- final AutoCloseable windowDecor =
- mFreeformTaskListener.giveWindowDecoration(change.getTaskInfo(), startT, finishT);
- if (windowDecor != null) {
- windowDecors.add(windowDecor);
- }
-
- // Intercepted transition to manage the window decorations. Let other handlers animate.
- return false;
- }
-
- private boolean startMinimizeTransition(IBinder transition) {
- if (!mPendingTransitionTokens.contains(transition)) {
- return false;
- }
+ () -> finishCallback.onTransitionFinished(null, null));
return true;
}
private boolean startChangeTransition(
IBinder transition,
int type,
- TransitionInfo.Change change,
- SurfaceControl.Transaction startT,
- SurfaceControl.Transaction finishT) {
- AutoCloseable windowDecor = null;
-
+ TransitionInfo.Change change) {
if (!mPendingTransitionTokens.contains(transition)) {
return false;
}
@@ -200,63 +148,27 @@
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
if (type == Transitions.TRANSIT_MAXIMIZE
&& taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+ // TODO: Add maximize animations
handled = true;
- windowDecor = mFreeformTaskListener.giveWindowDecoration(
- change.getTaskInfo(), startT, finishT);
- // TODO(b/235638450): Let fullscreen task listener adopt the window decor.
}
if (type == Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE
&& taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+ // TODO: Add restore animations
handled = true;
- // TODO(b/235638450): Let fullscreen task listener transfer the window decor.
- mFreeformTaskListener.adoptWindowDecoration(change, startT, finishT, windowDecor);
}
- releaseWindowDecor(windowDecor);
-
return handled;
}
- private void finishTransition(
- ArrayList<AutoCloseable> windowDecorsInCloseTransitions,
- Transitions.TransitionFinishCallback finishCallback) {
- for (AutoCloseable windowDecor : windowDecorsInCloseTransitions) {
- releaseWindowDecor(windowDecor);
- }
- mFreeformTaskListener.onTaskTransitionFinished();
- // TODO(b/235638450): Dispatch it to fullscreen task listener.
- finishCallback.onTransitionFinished(null, null);
- }
-
- private void releaseWindowDecor(AutoCloseable windowDecor) {
- if (windowDecor == null) {
- return;
- }
- try {
- windowDecor.close();
- } catch (Exception e) {
- Log.e(TAG, "Failed to release window decoration.", e);
- }
+ private boolean startMinimizeTransition(IBinder transition) {
+ return mPendingTransitionTokens.contains(transition);
}
@Nullable
@Override
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@NonNull TransitionRequestInfo request) {
- final ActivityManager.RunningTaskInfo taskInfo = request.getTriggerTask();
- if (taskInfo == null || taskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
- return null;
- }
- switch (request.getType()) {
- case WindowManager.TRANSIT_OPEN:
- case WindowManager.TRANSIT_CLOSE:
- case WindowManager.TRANSIT_TO_FRONT:
- case WindowManager.TRANSIT_TO_BACK:
- return new WindowContainerTransaction();
- default:
- return null;
- }
+ return null;
}
-
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java
new file mode 100644
index 0000000..a780ec1
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.freeform;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.SurfaceControl;
+import android.view.WindowManager;
+import android.window.TransitionInfo;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.wm.shell.fullscreen.FullscreenTaskListener;
+import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.transition.Transitions;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The {@link Transitions.TransitionHandler} that handles freeform task launches, closes,
+ * maximizing and restoring transitions. It also reports transitions so that window decorations can
+ * be a part of transitions.
+ */
+public class FreeformTaskTransitionObserver implements Transitions.TransitionObserver {
+ private static final String TAG = "FreeformTO";
+
+ private final Transitions mTransitions;
+ private final FreeformTaskListener<?> mFreeformTaskListener;
+ private final FullscreenTaskListener<?> mFullscreenTaskListener;
+
+ private final Map<IBinder, List<AutoCloseable>> mTransitionToWindowDecors = new HashMap<>();
+
+ public FreeformTaskTransitionObserver(
+ Context context,
+ ShellInit shellInit,
+ Transitions transitions,
+ FullscreenTaskListener<?> fullscreenTaskListener,
+ FreeformTaskListener<?> freeformTaskListener) {
+ mTransitions = transitions;
+ mFreeformTaskListener = freeformTaskListener;
+ mFullscreenTaskListener = fullscreenTaskListener;
+ if (Transitions.ENABLE_SHELL_TRANSITIONS && FreeformComponents.isFreeformEnabled(context)) {
+ shellInit.addInitCallback(this::onInit, this);
+ }
+ }
+
+ @VisibleForTesting
+ void onInit() {
+ mTransitions.registerObserver(this);
+ }
+
+ @Override
+ public void onTransitionReady(
+ @NonNull IBinder transition,
+ @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction startT,
+ @NonNull SurfaceControl.Transaction finishT) {
+ final ArrayList<AutoCloseable> windowDecors = new ArrayList<>();
+ for (TransitionInfo.Change change : info.getChanges()) {
+ if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) {
+ continue;
+ }
+
+ final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+ if (taskInfo == null || taskInfo.taskId == -1) {
+ continue;
+ }
+
+ switch (change.getMode()) {
+ case WindowManager.TRANSIT_OPEN:
+ onOpenTransitionReady(change, startT, finishT);
+ break;
+ case WindowManager.TRANSIT_CLOSE: {
+ onCloseTransitionReady(change, windowDecors, startT, finishT);
+ break;
+ }
+ case WindowManager.TRANSIT_CHANGE:
+ onChangeTransitionReady(info.getType(), change, startT, finishT);
+ break;
+ }
+ }
+ if (!windowDecors.isEmpty()) {
+ mTransitionToWindowDecors.put(transition, windowDecors);
+ }
+ }
+
+ private void onOpenTransitionReady(
+ TransitionInfo.Change change,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ switch (change.getTaskInfo().getWindowingMode()){
+ case WINDOWING_MODE_FREEFORM:
+ mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
+ break;
+ case WINDOWING_MODE_FULLSCREEN:
+ mFullscreenTaskListener.createWindowDecoration(change, startT, finishT);
+ break;
+ }
+ }
+
+ private void onCloseTransitionReady(
+ TransitionInfo.Change change,
+ ArrayList<AutoCloseable> windowDecors,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ final AutoCloseable windowDecor;
+ switch (change.getTaskInfo().getWindowingMode()) {
+ case WINDOWING_MODE_FREEFORM:
+ windowDecor = mFreeformTaskListener.giveWindowDecoration(change.getTaskInfo(),
+ startT, finishT);
+ break;
+ case WINDOWING_MODE_FULLSCREEN:
+ windowDecor = mFullscreenTaskListener.giveWindowDecoration(change.getTaskInfo(),
+ startT, finishT);
+ break;
+ default:
+ windowDecor = null;
+ }
+ if (windowDecor != null) {
+ windowDecors.add(windowDecor);
+ }
+ }
+
+ private void onChangeTransitionReady(
+ int type,
+ TransitionInfo.Change change,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ AutoCloseable windowDecor = null;
+
+ boolean adopted = false;
+ final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+ if (type == Transitions.TRANSIT_MAXIMIZE
+ && taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+ windowDecor = mFreeformTaskListener.giveWindowDecoration(
+ change.getTaskInfo(), startT, finishT);
+ adopted = mFullscreenTaskListener.adoptWindowDecoration(
+ change, startT, finishT, windowDecor);
+ }
+
+ if (type == Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE
+ && taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+ windowDecor = mFullscreenTaskListener.giveWindowDecoration(
+ change.getTaskInfo(), startT, finishT);
+ adopted = mFreeformTaskListener.adoptWindowDecoration(
+ change, startT, finishT, windowDecor);
+ }
+
+ if (!adopted) {
+ releaseWindowDecor(windowDecor);
+ }
+ }
+
+ @Override
+ public void onTransitionStarting(@NonNull IBinder transition) {}
+
+ @Override
+ public void onTransitionMerged(@NonNull IBinder merged, @NonNull IBinder playing) {
+ final List<AutoCloseable> windowDecorsOfMerged = mTransitionToWindowDecors.get(merged);
+ if (windowDecorsOfMerged == null) {
+ // We are adding window decorations of the merged transition to them of the playing
+ // transition so if there is none of them there is nothing to do.
+ return;
+ }
+ mTransitionToWindowDecors.remove(merged);
+
+ final List<AutoCloseable> windowDecorsOfPlaying = mTransitionToWindowDecors.get(playing);
+ if (windowDecorsOfPlaying != null) {
+ windowDecorsOfPlaying.addAll(windowDecorsOfMerged);
+ } else {
+ mTransitionToWindowDecors.put(playing, windowDecorsOfMerged);
+ }
+ }
+
+ @Override
+ public void onTransitionFinished(@NonNull IBinder transition, boolean aborted) {
+ final List<AutoCloseable> windowDecors = mTransitionToWindowDecors.getOrDefault(
+ transition, Collections.emptyList());
+ mTransitionToWindowDecors.remove(transition);
+
+ for (AutoCloseable windowDecor : windowDecors) {
+ releaseWindowDecor(windowDecor);
+ }
+ mFullscreenTaskListener.onTaskTransitionFinished();
+ mFreeformTaskListener.onTaskTransitionFinished();
+ }
+
+ private static void releaseWindowDecor(AutoCloseable windowDecor) {
+ if (windowDecor == null) {
+ return;
+ }
+ try {
+ windowDecor.close();
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to release window decoration.", e);
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
index c947cf1..8da4c6a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
@@ -40,4 +40,12 @@
*
*/
void startMinimizedModeTransition(WindowContainerTransaction wct);
+
+ /**
+ * Starts close window transition
+ *
+ * @param wct the {@link WindowContainerTransaction} that closes the task
+ *
+ */
+ void startRemoveTransition(WindowContainerTransaction wct);
}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
index 0ba4afc..e9f9bb5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
@@ -16,16 +16,21 @@
package com.android.wm.shell.fullscreen;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
+import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.graphics.Point;
-import android.util.Slog;
+import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceControl;
+import android.window.TransitionInfo;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -34,36 +39,49 @@
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.windowdecor.WindowDecorViewModel;
import java.io.PrintWriter;
import java.util.Optional;
/**
* Organizes tasks presented in {@link android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN}.
+ * @param <T> the type of window decoration instance
*/
-public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
+public class FullscreenTaskListener<T extends AutoCloseable>
+ implements ShellTaskOrganizer.TaskListener {
private static final String TAG = "FullscreenTaskListener";
private final ShellTaskOrganizer mShellTaskOrganizer;
+
+ private final SparseArray<State<T>> mTasks = new SparseArray<>();
+ private final SparseArray<T> mWindowDecorOfVanishedTasks = new SparseArray<>();
+
+ private static class State<T extends AutoCloseable> {
+ RunningTaskInfo mTaskInfo;
+ SurfaceControl mLeash;
+ T mWindowDecoration;
+ }
private final SyncTransactionQueue mSyncQueue;
private final Optional<RecentTasksController> mRecentTasksOptional;
-
- private final SparseArray<TaskData> mDataByTaskId = new SparseArray<>();
-
+ private final Optional<WindowDecorViewModel<T>> mWindowDecorViewModelOptional;
/**
* This constructor is used by downstream products.
*/
public FullscreenTaskListener(SyncTransactionQueue syncQueue) {
- this(null /* shellInit */, null /* shellTaskOrganizer */, syncQueue, Optional.empty());
+ this(null /* shellInit */, null /* shellTaskOrganizer */, syncQueue, Optional.empty(),
+ Optional.empty());
}
public FullscreenTaskListener(ShellInit shellInit,
ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue,
- Optional<RecentTasksController> recentTasksOptional) {
+ Optional<RecentTasksController> recentTasksOptional,
+ Optional<WindowDecorViewModel<T>> windowDecorViewModelOptional) {
mShellTaskOrganizer = shellTaskOrganizer;
mSyncQueue = syncQueue;
mRecentTasksOptional = recentTasksOptional;
+ mWindowDecorViewModelOptional = windowDecorViewModelOptional;
// Note: Some derivative FullscreenTaskListener implementations do not use ShellInit
if (shellInit != null) {
shellInit.addInitCallback(this::onInit, this);
@@ -76,55 +94,207 @@
@Override
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
- if (mDataByTaskId.get(taskInfo.taskId) != null) {
+ if (mTasks.get(taskInfo.taskId) != null) {
throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId);
}
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
taskInfo.taskId);
final Point positionInParent = taskInfo.positionInParent;
- mDataByTaskId.put(taskInfo.taskId, new TaskData(leash, positionInParent));
+ final State<T> state = new State();
+ state.mLeash = leash;
+ state.mTaskInfo = taskInfo;
+ mTasks.put(taskInfo.taskId, state);
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
- mSyncQueue.runInSync(t -> {
- // Reset several properties back to fullscreen (PiP, for example, leaves all these
- // properties in a bad state).
- t.setWindowCrop(leash, null);
- t.setPosition(leash, positionInParent.x, positionInParent.y);
- t.setAlpha(leash, 1f);
- t.setMatrix(leash, 1, 0, 0, 1);
- t.show(leash);
- });
-
updateRecentsForVisibleFullscreenTask(taskInfo);
- }
-
- @Override
- public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
- if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
-
- updateRecentsForVisibleFullscreenTask(taskInfo);
-
- final TaskData data = mDataByTaskId.get(taskInfo.taskId);
- final Point positionInParent = taskInfo.positionInParent;
- if (!positionInParent.equals(data.positionInParent)) {
- data.positionInParent.set(positionInParent.x, positionInParent.y);
+ if (shouldShowWindowDecor(taskInfo) && mWindowDecorViewModelOptional.isPresent()) {
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ state.mWindowDecoration =
+ mWindowDecorViewModelOptional.get().createWindowDecoration(taskInfo,
+ leash, t, t);
+ t.apply();
+ } else {
mSyncQueue.runInSync(t -> {
- t.setPosition(data.surface, positionInParent.x, positionInParent.y);
+ // Reset several properties back to fullscreen (PiP, for example, leaves all these
+ // properties in a bad state).
+ t.setWindowCrop(leash, null);
+ t.setPosition(leash, positionInParent.x, positionInParent.y);
+ t.setAlpha(leash, 1f);
+ t.setMatrix(leash, 1, 0, 0, 1);
+ t.show(leash);
});
}
}
@Override
- public void onTaskVanished(RunningTaskInfo taskInfo) {
- if (mDataByTaskId.get(taskInfo.taskId) == null) {
- Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
+ public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
+ final State<T> state = mTasks.get(taskInfo.taskId);
+ final Point oldPositionInParent = state.mTaskInfo.positionInParent;
+ state.mTaskInfo = taskInfo;
+ if (state.mWindowDecoration != null) {
+ mWindowDecorViewModelOptional.get().onTaskInfoChanged(
+ state.mTaskInfo, state.mWindowDecoration);
+ }
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
+ updateRecentsForVisibleFullscreenTask(taskInfo);
+
+ final Point positionInParent = state.mTaskInfo.positionInParent;
+ if (!oldPositionInParent.equals(state.mTaskInfo.positionInParent)) {
+ mSyncQueue.runInSync(t -> {
+ t.setPosition(state.mLeash, positionInParent.x, positionInParent.y);
+ });
+ }
+ }
+
+ @Override
+ public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
+ final State<T> state = mTasks.get(taskInfo.taskId);
+ if (state == null) {
+ // This is possible if the transition happens before this method.
+ return;
+ }
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
+ taskInfo.taskId);
+ mTasks.remove(taskInfo.taskId);
+
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ // Save window decorations of closing tasks so that we can hand them over to the
+ // transition system if this method happens before the transition. In case where the
+ // transition didn't happen, it'd be cleared when the next transition finished.
+ if (state.mWindowDecoration != null) {
+ mWindowDecorOfVanishedTasks.put(taskInfo.taskId, state.mWindowDecoration);
+ }
+ return;
+ }
+ releaseWindowDecor(state.mWindowDecoration);
+ }
+
+ /**
+ * Creates a window decoration for a transition.
+ *
+ * @param change the change of this task transition that needs to have the task layer as the
+ * leash
+ */
+ public void createWindowDecoration(TransitionInfo.Change change,
+ SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
+ final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash());
+ if (!mWindowDecorViewModelOptional.isPresent()
+ || !shouldShowWindowDecor(state.mTaskInfo)) {
return;
}
- mDataByTaskId.remove(taskInfo.taskId);
+ state.mWindowDecoration = mWindowDecorViewModelOptional.get().createWindowDecoration(
+ state.mTaskInfo, state.mLeash, startT, finishT);
+ }
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
- taskInfo.taskId);
+ /**
+ * Adopt the incoming window decoration and lets the window decoration prepare for a transition.
+ *
+ * @param change the change of this task transition that needs to have the task layer as the
+ * leash
+ * @param startT the start transaction of this transition
+ * @param finishT the finish transaction of this transition
+ * @param windowDecor the window decoration to adopt
+ * @return {@code true} if it adopts the window decoration; {@code false} otherwise
+ */
+ public boolean adoptWindowDecoration(
+ TransitionInfo.Change change,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT,
+ @Nullable AutoCloseable windowDecor) {
+ if (!mWindowDecorViewModelOptional.isPresent()
+ || !shouldShowWindowDecor(change.getTaskInfo())) {
+ return false;
+ }
+ final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash());
+ state.mWindowDecoration = mWindowDecorViewModelOptional.get().adoptWindowDecoration(
+ windowDecor);
+ if (state.mWindowDecoration != null) {
+ mWindowDecorViewModelOptional.get().setupWindowDecorationForTransition(
+ state.mTaskInfo, startT, finishT, state.mWindowDecoration);
+ return true;
+ } else {
+ state.mWindowDecoration = mWindowDecorViewModelOptional.get().createWindowDecoration(
+ state.mTaskInfo, state.mLeash, startT, finishT);
+ return false;
+ }
+ }
+
+ /**
+ * Clear window decors of vanished tasks.
+ */
+ public void onTaskTransitionFinished() {
+ if (mWindowDecorOfVanishedTasks.size() == 0) {
+ return;
+ }
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ "Clearing window decors of vanished tasks. There could be visual defects "
+ + "if any of them is used later in transitions.");
+ for (int i = 0; i < mWindowDecorOfVanishedTasks.size(); ++i) {
+ releaseWindowDecor(mWindowDecorOfVanishedTasks.valueAt(i));
+ }
+ mWindowDecorOfVanishedTasks.clear();
+ }
+
+ /**
+ * Gives out the ownership of the task's window decoration. The given task is leaving (of has
+ * left) this task listener. This is the transition system asking for the ownership.
+ *
+ * @param taskInfo the maximizing task
+ * @return the window decor of the maximizing task if any
+ */
+ public T giveWindowDecoration(
+ ActivityManager.RunningTaskInfo taskInfo,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ T windowDecor;
+ final State<T> state = mTasks.get(taskInfo.taskId);
+ if (state != null) {
+ windowDecor = state.mWindowDecoration;
+ state.mWindowDecoration = null;
+ } else {
+ windowDecor =
+ mWindowDecorOfVanishedTasks.removeReturnOld(taskInfo.taskId);
+ }
+ if (mWindowDecorViewModelOptional.isPresent()) {
+ mWindowDecorViewModelOptional.get().setupWindowDecorationForTransition(
+ taskInfo, startT, finishT, windowDecor);
+ }
+
+ return windowDecor;
+ }
+
+ private State<T> createOrUpdateTaskState(ActivityManager.RunningTaskInfo taskInfo,
+ SurfaceControl leash) {
+ State<T> state = mTasks.get(taskInfo.taskId);
+ if (state != null) {
+ updateTaskInfo(taskInfo);
+ return state;
+ }
+
+ state = new State<T>();
+ state.mTaskInfo = taskInfo;
+ state.mLeash = leash;
+ mTasks.put(taskInfo.taskId, state);
+
+ return state;
+ }
+
+ private State<T> updateTaskInfo(ActivityManager.RunningTaskInfo taskInfo) {
+ final State<T> state = mTasks.get(taskInfo.taskId);
+ state.mTaskInfo = taskInfo;
+ return state;
+ }
+
+ private void releaseWindowDecor(T windowDecor) {
+ if (windowDecor == null) {
+ return;
+ }
+ try {
+ windowDecor.close();
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to release window decoration.", e);
+ }
}
private void updateRecentsForVisibleFullscreenTask(RunningTaskInfo taskInfo) {
@@ -148,17 +318,17 @@
}
private SurfaceControl findTaskSurface(int taskId) {
- if (!mDataByTaskId.contains(taskId)) {
+ if (!mTasks.contains(taskId)) {
throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
}
- return mDataByTaskId.get(taskId).surface;
+ return mTasks.get(taskId).mLeash;
}
@Override
public void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + this);
- pw.println(innerPrefix + mDataByTaskId.size() + " Tasks");
+ pw.println(innerPrefix + mTasks.size() + " Tasks");
}
@Override
@@ -166,16 +336,10 @@
return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_FULLSCREEN);
}
- /**
- * Per-task data for each managed task.
- */
- private static class TaskData {
- public final SurfaceControl surface;
- public final Point positionInParent;
-
- public TaskData(SurfaceControl surface, Point positionInParent) {
- this.surface = surface;
- this.positionInParent = positionInParent;
- }
+ private static boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
+ return taskInfo.getConfiguration().windowConfiguration.getDisplayWindowingMode()
+ == WINDOWING_MODE_FREEFORM;
}
+
+
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
index 2fdd121..e91987d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
@@ -316,11 +316,13 @@
true /* onTop */);
wct.reorder(rootToken, mEnabled /* onTop */);
mSyncQueue.queue(wct);
- final SurfaceControl rootLeash = mLaunchRootLeash;
- mSyncQueue.runInSync(t -> {
- t.setPosition(rootLeash, taskBounds.left, taskBounds.top);
- t.setWindowCrop(rootLeash, taskBounds.width(), taskBounds.height());
- });
+ if (mEnabled) {
+ final SurfaceControl rootLeash = mLaunchRootLeash;
+ mSyncQueue.runInSync(t -> {
+ t.setPosition(rootLeash, taskBounds.left, taskBounds.top);
+ t.setWindowCrop(rootLeash, taskBounds.width(), taskBounds.height());
+ });
+ }
}
private Rect calculateBounds() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
index e03421d..4def15d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
@@ -37,12 +37,13 @@
* @param activityInfo ActivityInfo tied to the Activity
* @param pictureInPictureParams PictureInPictureParams tied to the Activity
* @param launcherRotation Launcher rotation to calculate the PiP destination bounds
- * @param shelfHeight Shelf height of launcher to calculate the PiP destination bounds
+ * @param hotseatKeepClearArea Bounds of Hotseat to avoid used to calculate PiP destination
+ bounds
* @return destination bounds the PiP window should land into
*/
Rect startSwipePipToHome(in ComponentName componentName, in ActivityInfo activityInfo,
in PictureInPictureParams pictureInPictureParams,
- int launcherRotation, int shelfHeight) = 1;
+ int launcherRotation, in Rect hotseatKeepClearArea) = 1;
/**
* Notifies the swiping Activity to PiP onto home transition is finished
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
index 7397e52..cd61dbb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
@@ -47,6 +47,7 @@
private final @NonNull PipBoundsState mPipBoundsState;
private final PipSnapAlgorithm mSnapAlgorithm;
+ private final PipKeepClearAlgorithm mPipKeepClearAlgorithm;
private float mDefaultSizePercent;
private float mMinAspectRatioForMinSize;
@@ -60,9 +61,11 @@
protected Point mScreenEdgeInsets;
public PipBoundsAlgorithm(Context context, @NonNull PipBoundsState pipBoundsState,
- @NonNull PipSnapAlgorithm pipSnapAlgorithm) {
+ @NonNull PipSnapAlgorithm pipSnapAlgorithm,
+ @NonNull PipKeepClearAlgorithm pipKeepClearAlgorithm) {
mPipBoundsState = pipBoundsState;
mSnapAlgorithm = pipSnapAlgorithm;
+ mPipKeepClearAlgorithm = pipKeepClearAlgorithm;
reloadResources(context);
// Initialize the aspect ratio to the default aspect ratio. Don't do this in reload
// resources as it would clobber mAspectRatio when entering PiP from fullscreen which
@@ -129,8 +132,21 @@
return getDefaultBounds(INVALID_SNAP_FRACTION, null /* size */);
}
- /** Returns the destination bounds to place the PIP window on entry. */
+ /**
+ * Returns the destination bounds to place the PIP window on entry.
+ * If there are any keep clear areas registered, the position will try to avoid occluding them.
+ */
public Rect getEntryDestinationBounds() {
+ Rect entryBounds = getEntryDestinationBoundsIgnoringKeepClearAreas();
+ Rect insets = new Rect();
+ getInsetBounds(insets);
+ return mPipKeepClearAlgorithm.findUnoccludedPosition(entryBounds,
+ mPipBoundsState.getRestrictedKeepClearAreas(),
+ mPipBoundsState.getUnrestrictedKeepClearAreas(), insets);
+ }
+
+ /** Returns the destination bounds to place the PIP window on entry. */
+ public Rect getEntryDestinationBoundsIgnoringKeepClearAreas() {
final PipBoundsState.PipReentryState reentryState = mPipBoundsState.getReentryState();
final Rect destinationBounds = reentryState != null
@@ -138,9 +154,10 @@
: getDefaultBounds();
final boolean useCurrentSize = reentryState != null && reentryState.getSize() != null;
- return transformBoundsToAspectRatioIfValid(destinationBounds,
+ Rect aspectRatioBounds = transformBoundsToAspectRatioIfValid(destinationBounds,
mPipBoundsState.getAspectRatio(), false /* useCurrentMinEdgeSize */,
useCurrentSize);
+ return aspectRatioBounds;
}
/** Returns the current bounds adjusted to the new aspect ratio, if valid. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipKeepClearAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipKeepClearAlgorithm.java
new file mode 100644
index 0000000..e3495e1
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipKeepClearAlgorithm.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip;
+
+import android.graphics.Rect;
+
+import java.util.Set;
+
+/**
+ * Interface for interacting with keep clear algorithm used to move PiP window out of the way of
+ * keep clear areas.
+ */
+public interface PipKeepClearAlgorithm {
+
+ /**
+ * Adjust the position of picture in picture window based on the registered keep clear areas.
+ * @param pipBoundsState state of the PiP to use for the calculations
+ * @param pipBoundsAlgorithm algorithm implementation used to get the entry destination bounds
+ * @return
+ */
+ default Rect adjust(PipBoundsState pipBoundsState, PipBoundsAlgorithm pipBoundsAlgorithm) {
+ return pipBoundsState.getBounds();
+ }
+
+ /**
+ * Calculate the bounds so that none of the keep clear areas are occluded, while the bounds stay
+ * within the allowed bounds. If such position is not feasible, return original bounds.
+ * @param defaultBounds initial bounds used in the calculation
+ * @param restrictedKeepClearAreas registered restricted keep clear areas
+ * @param unrestrictedKeepClearAreas registered unrestricted keep clear areas
+ * @param allowedBounds bounds that define the allowed space for the output, result will always
+ * be inside those bounds
+ * @return bounds that don't cover any of the keep clear areas and are within allowed bounds
+ */
+ default Rect findUnoccludedPosition(Rect defaultBounds, Set<Rect> restrictedKeepClearAreas,
+ Set<Rect> unrestrictedKeepClearAreas, Rect allowedBounds) {
+ return defaultBounds;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java
index 1a4be3b..c6b5ce9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java
@@ -88,6 +88,11 @@
return isInPip(mState);
}
+ /** Returns true if activity has fully entered PiP mode. */
+ public boolean hasEnteredPip() {
+ return hasEnteredPip(mState);
+ }
+
public void setInSwipePipToHomeTransition(boolean inSwipePipToHomeTransition) {
mInSwipePipToHomeTransition = inSwipePipToHomeTransition;
}
@@ -120,6 +125,11 @@
return state >= TASK_APPEARED && state != EXITING_PIP;
}
+ /** Returns true if activity has fully entered PiP mode. */
+ public static boolean hasEnteredPip(@TransitionState int state) {
+ return state == ENTERED_PIP;
+ }
+
public interface OnPipTransitionStateChangedListener {
void onPipTransitionStateChanged(@TransitionState int oldState,
@TransitionState int newState);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
new file mode 100644
index 0000000..6dd02e4
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip.phone;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.util.ArraySet;
+import android.view.Gravity;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.pip.PipBoundsAlgorithm;
+import com.android.wm.shell.pip.PipBoundsState;
+import com.android.wm.shell.pip.PipKeepClearAlgorithm;
+
+import java.util.Set;
+
+/**
+ * Calculates the adjusted position that does not occlude keep clear areas.
+ */
+public class PhonePipKeepClearAlgorithm implements PipKeepClearAlgorithm {
+
+ protected int mKeepClearAreasPadding;
+
+ public PhonePipKeepClearAlgorithm(Context context) {
+ reloadResources(context);
+ }
+
+ private void reloadResources(Context context) {
+ final Resources res = context.getResources();
+ mKeepClearAreasPadding = res.getDimensionPixelSize(R.dimen.pip_keep_clear_areas_padding);
+ }
+
+ /**
+ * Adjusts the current position of PiP to avoid occluding keep clear areas. This will push PiP
+ * towards the closest edge and then apply calculations to avoid occluding keep clear areas.
+ */
+ public Rect adjust(PipBoundsState pipBoundsState, PipBoundsAlgorithm pipBoundsAlgorithm) {
+ Rect startingBounds = pipBoundsState.getBounds().isEmpty()
+ ? pipBoundsAlgorithm.getEntryDestinationBoundsIgnoringKeepClearAreas()
+ : pipBoundsState.getBounds();
+ float snapFraction = pipBoundsAlgorithm.getSnapFraction(startingBounds);
+ int verticalGravity;
+ int horizontalGravity;
+ if (snapFraction < 1.5f || snapFraction >= 3.5f) {
+ verticalGravity = Gravity.NO_GRAVITY;
+ } else {
+ verticalGravity = Gravity.BOTTOM;
+ }
+ if (snapFraction >= 0.5f && snapFraction < 2.5f) {
+ horizontalGravity = Gravity.RIGHT;
+ } else {
+ horizontalGravity = Gravity.LEFT;
+ }
+ // push the bounds based on the gravity
+ Rect insets = new Rect();
+ pipBoundsAlgorithm.getInsetBounds(insets);
+ if (pipBoundsState.isImeShowing()) {
+ insets.bottom -= pipBoundsState.getImeHeight();
+ }
+ Rect pushedBounds = new Rect(startingBounds);
+ if (verticalGravity == Gravity.BOTTOM) {
+ pushedBounds.offsetTo(pushedBounds.left,
+ insets.bottom - pushedBounds.height());
+ }
+ if (horizontalGravity == Gravity.RIGHT) {
+ pushedBounds.offsetTo(insets.right - pushedBounds.width(), pushedBounds.top);
+ } else {
+ pushedBounds.offsetTo(insets.left, pushedBounds.top);
+ }
+ return findUnoccludedPosition(pushedBounds, pipBoundsState.getRestrictedKeepClearAreas(),
+ pipBoundsState.getUnrestrictedKeepClearAreas(), insets);
+ }
+
+ /** Returns a new {@code Rect} that does not occlude the provided keep clear areas. */
+ public Rect findUnoccludedPosition(Rect defaultBounds, Set<Rect> restrictedKeepClearAreas,
+ Set<Rect> unrestrictedKeepClearAreas, Rect allowedBounds) {
+ if (restrictedKeepClearAreas.isEmpty() && unrestrictedKeepClearAreas.isEmpty()) {
+ return defaultBounds;
+ }
+ Set<Rect> keepClearAreas = new ArraySet<>();
+ if (!restrictedKeepClearAreas.isEmpty()) {
+ keepClearAreas.addAll(restrictedKeepClearAreas);
+ }
+ if (!unrestrictedKeepClearAreas.isEmpty()) {
+ keepClearAreas.addAll(unrestrictedKeepClearAreas);
+ }
+ Rect outBounds = new Rect(defaultBounds);
+ for (Rect r : keepClearAreas) {
+ Rect tmpRect = new Rect(r);
+ // add extra padding to the keep clear area
+ tmpRect.inset(-mKeepClearAreasPadding, -mKeepClearAreasPadding);
+ if (Rect.intersects(r, outBounds)) {
+ if (tryOffsetUp(outBounds, tmpRect, allowedBounds)) continue;
+ if (tryOffsetLeft(outBounds, tmpRect, allowedBounds)) continue;
+ if (tryOffsetDown(outBounds, tmpRect, allowedBounds)) continue;
+ if (tryOffsetRight(outBounds, tmpRect, allowedBounds)) continue;
+ }
+ }
+ return outBounds;
+ }
+
+ private static boolean tryOffsetLeft(Rect rectToMove, Rect rectToAvoid, Rect allowedBounds) {
+ return tryOffset(rectToMove, rectToAvoid, allowedBounds,
+ rectToAvoid.left - rectToMove.right, 0);
+ }
+
+ private static boolean tryOffsetRight(Rect rectToMove, Rect rectToAvoid, Rect allowedBounds) {
+ return tryOffset(rectToMove, rectToAvoid, allowedBounds,
+ rectToAvoid.right - rectToMove.left, 0);
+ }
+
+ private static boolean tryOffsetUp(Rect rectToMove, Rect rectToAvoid, Rect allowedBounds) {
+ return tryOffset(rectToMove, rectToAvoid, allowedBounds,
+ 0, rectToAvoid.top - rectToMove.bottom);
+ }
+
+ private static boolean tryOffsetDown(Rect rectToMove, Rect rectToAvoid, Rect allowedBounds) {
+ return tryOffset(rectToMove, rectToAvoid, allowedBounds,
+ 0, rectToAvoid.bottom - rectToMove.top);
+ }
+
+ private static boolean tryOffset(Rect rectToMove, Rect rectToAvoid, Rect allowedBounds,
+ int dx, int dy) {
+ Rect tmp = new Rect(rectToMove);
+ tmp.offset(dx, dy);
+ if (!Rect.intersects(rectToAvoid, tmp) && allowedBounds.contains(tmp)) {
+ rectToMove.offsetTo(tmp.left, tmp.top);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index ac3407d..6c9a6b6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -43,6 +43,7 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Pair;
@@ -79,6 +80,7 @@
import com.android.wm.shell.pip.PipAppOpsListener;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
+import com.android.wm.shell.pip.PipKeepClearAlgorithm;
import com.android.wm.shell.pip.PipMediaController;
import com.android.wm.shell.pip.PipParamsChangedForwarder;
import com.android.wm.shell.pip.PipSnapAlgorithm;
@@ -110,6 +112,14 @@
UserChangeListener {
private static final String TAG = "PipController";
+ private boolean mEnablePipKeepClearAlgorithm =
+ SystemProperties.getBoolean("persist.wm.debug.enable_pip_keep_clear_algorithm", false);
+
+ @VisibleForTesting
+ void setEnablePipKeepClearAlgorithm(boolean value) {
+ mEnablePipKeepClearAlgorithm = value;
+ }
+
private Context mContext;
protected ShellExecutor mMainExecutor;
private DisplayController mDisplayController;
@@ -262,7 +272,17 @@
public void onKeepClearAreasChanged(int displayId, Set<Rect> restricted,
Set<Rect> unrestricted) {
if (mPipBoundsState.getDisplayId() == displayId) {
- mPipBoundsState.setKeepClearAreas(restricted, unrestricted);
+ if (mEnablePipKeepClearAlgorithm) {
+ mPipBoundsState.setKeepClearAreas(restricted, unrestricted);
+ // only move if already in pip, other transitions account for keep clear
+ // areas
+ if (mPipTransitionState.hasEnteredPip()) {
+ Rect destBounds = mPipKeepClearAlgorithm.adjust(mPipBoundsState,
+ mPipBoundsAlgorithm);
+ mPipTaskOrganizer.scheduleAnimateResizePip(destBounds,
+ mEnterAnimationDuration, null);
+ }
+ }
}
}
};
@@ -759,8 +779,16 @@
private Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
PictureInPictureParams pictureInPictureParams,
- int launcherRotation, int shelfHeight) {
- setShelfHeightLocked(shelfHeight > 0 /* visible */, shelfHeight);
+ int launcherRotation, Rect hotseatKeepClearArea) {
+
+ if (mEnablePipKeepClearAlgorithm) {
+ // pre-emptively add the keep clear area for Hotseat, so that it is taken into account
+ // when calculating the entry destination bounds of PiP window
+ mPipBoundsState.getRestrictedKeepClearAreas().add(hotseatKeepClearArea);
+ } else {
+ int shelfHeight = hotseatKeepClearArea.height();
+ setShelfHeightLocked(shelfHeight > 0 /* visible */, shelfHeight);
+ }
onDisplayRotationChangedNotInPip(mContext, launcherRotation);
final Rect entryBounds = mPipTaskOrganizer.startSwipePipToHome(componentName, activityInfo,
pictureInPictureParams);
@@ -1059,12 +1087,12 @@
@Override
public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
PictureInPictureParams pictureInPictureParams, int launcherRotation,
- int shelfHeight) {
+ Rect keepClearArea) {
Rect[] result = new Rect[1];
executeRemoteCallWithTaskPermission(mController, "startSwipePipToHome",
(controller) -> {
result[0] = controller.startSwipePipToHome(componentName, activityInfo,
- pictureInPictureParams, launcherRotation, shelfHeight);
+ pictureInPictureParams, launcherRotation, keepClearArea);
}, true /* blocking */);
return result[0];
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithm.java
deleted file mode 100644
index 78084fa..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithm.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.pip.phone;
-
-import android.graphics.Rect;
-import android.util.ArraySet;
-
-import com.android.wm.shell.pip.PipBoundsAlgorithm;
-import com.android.wm.shell.pip.PipBoundsState;
-
-import java.util.Set;
-
-/**
- * Calculates the adjusted position that does not occlude keep clear areas.
- */
-public class PipKeepClearAlgorithm {
-
- /**
- * Adjusts the current position of PiP to avoid occluding keep clear areas. If the user has
- * moved PiP manually, the unmodified current position will be returned instead.
- */
- public Rect adjust(PipBoundsState boundsState, PipBoundsAlgorithm boundsAlgorithm) {
- if (boundsState.hasUserResizedPip()) {
- return boundsState.getBounds();
- }
- return adjust(boundsAlgorithm.getEntryDestinationBounds(),
- boundsState.getRestrictedKeepClearAreas(),
- boundsState.getUnrestrictedKeepClearAreas(), boundsState.getDisplayBounds());
- }
-
- /** Returns a new {@code Rect} that does not occlude the provided keep clear areas. */
- public Rect adjust(Rect defaultBounds, Set<Rect> restrictedKeepClearAreas,
- Set<Rect> unrestrictedKeepClearAreas, Rect displayBounds) {
- if (restrictedKeepClearAreas.isEmpty()) {
- return defaultBounds;
- }
- Set<Rect> keepClearAreas = new ArraySet<>();
- if (!restrictedKeepClearAreas.isEmpty()) {
- keepClearAreas.addAll(restrictedKeepClearAreas);
- }
- Rect outBounds = new Rect(defaultBounds);
- for (Rect r : keepClearAreas) {
- if (Rect.intersects(r, outBounds)) {
- if (tryOffsetUp(outBounds, r, displayBounds)) continue;
- if (tryOffsetLeft(outBounds, r, displayBounds)) continue;
- if (tryOffsetDown(outBounds, r, displayBounds)) continue;
- if (tryOffsetRight(outBounds, r, displayBounds)) continue;
- }
- }
- return outBounds;
- }
-
- private boolean tryOffsetLeft(Rect rectToMove, Rect rectToAvoid, Rect displayBounds) {
- return tryOffset(rectToMove, rectToAvoid, displayBounds,
- rectToAvoid.left - rectToMove.right, 0);
- }
-
- private boolean tryOffsetRight(Rect rectToMove, Rect rectToAvoid, Rect displayBounds) {
- return tryOffset(rectToMove, rectToAvoid, displayBounds,
- rectToAvoid.right - rectToMove.left, 0);
- }
-
- private boolean tryOffsetUp(Rect rectToMove, Rect rectToAvoid, Rect displayBounds) {
- return tryOffset(rectToMove, rectToAvoid, displayBounds,
- 0, rectToAvoid.top - rectToMove.bottom);
- }
-
- private boolean tryOffsetDown(Rect rectToMove, Rect rectToAvoid, Rect displayBounds) {
- return tryOffset(rectToMove, rectToAvoid, displayBounds,
- 0, rectToAvoid.bottom - rectToMove.top);
- }
-
- private boolean tryOffset(Rect rectToMove, Rect rectToAvoid, Rect displayBounds,
- int dx, int dy) {
- Rect tmp = new Rect(rectToMove);
- tmp.offset(dx, dy);
- if (!Rect.intersects(rectToAvoid, tmp) && displayBounds.contains(tmp)) {
- rectToMove.offsetTo(tmp.left, tmp.top);
- return true;
- }
- return false;
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
index 44d2202..afb64c9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
@@ -33,6 +33,7 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Debug;
+import android.os.SystemProperties;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.R;
@@ -58,6 +59,8 @@
public class PipMotionHelper implements PipAppOpsListener.Callback,
FloatingContentCoordinator.FloatingContent {
+ public static final boolean ENABLE_FLING_TO_DISMISS_PIP =
+ SystemProperties.getBoolean("persist.wm.debug.fling_to_dismiss_pip", true);
private static final String TAG = "PipMotionHelper";
private static final boolean DEBUG = false;
@@ -704,6 +707,7 @@
loc[1] = animatedPipBounds.top;
}
};
+ mMagnetizedPip.setFlingToTargetEnabled(ENABLE_FLING_TO_DISMISS_PIP);
}
return mMagnetizedPip;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java
index a2eadcd..ce34d2f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java
@@ -39,6 +39,7 @@
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
+import com.android.wm.shell.pip.PipKeepClearAlgorithm;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.tv.TvPipKeepClearAlgorithm.Placement;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -63,7 +64,8 @@
public TvPipBoundsAlgorithm(Context context,
@NonNull TvPipBoundsState tvPipBoundsState,
@NonNull PipSnapAlgorithm pipSnapAlgorithm) {
- super(context, tvPipBoundsState, pipSnapAlgorithm);
+ super(context, tvPipBoundsState, pipSnapAlgorithm,
+ new PipKeepClearAlgorithm() {});
this.mTvPipBoundsState = tvPipBoundsState;
this.mKeepClearAlgorithm = new TvPipKeepClearAlgorithm();
reloadResources(context);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
index 51921e7..3714fe7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
@@ -18,6 +18,7 @@
import android.app.PendingIntent;
import android.content.Intent;
+import android.content.pm.ShortcutInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.view.RemoteAnimationAdapter;
@@ -89,7 +90,7 @@
float splitRatio, in RemoteAnimationAdapter adapter) = 11;
/**
- * Start a pair of intent and task using legacy transition system.
+ * Starts a pair of intent and task using legacy transition system.
*/
oneway void startIntentAndTaskWithLegacyTransition(in PendingIntent pendingIntent,
in Intent fillInIntent, int taskId, in Bundle mainOptions,in Bundle sideOptions,
@@ -108,4 +109,11 @@
* does not expect split to currently be running.
*/
RemoteAnimationTarget[] onStartingSplitLegacy(in RemoteAnimationTarget[] appTargets) = 14;
+
+ /**
+ * Starts a pair of shortcut and task using legacy transition system.
+ */
+ oneway void startShortcutAndTaskWithLegacyTransition(in ShortcutInfo shortcutInfo, int taskId,
+ in Bundle mainOptions, in Bundle sideOptions, int sidePosition, float splitRatio,
+ in RemoteAnimationAdapter adapter) = 15;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 2117b69..169e17b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -40,6 +40,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
+import android.content.pm.ShortcutInfo;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.RemoteException;
@@ -788,6 +789,17 @@
}
@Override
+ public void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo,
+ int taskId, @Nullable Bundle mainOptions, @Nullable Bundle sideOptions,
+ @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) {
+ executeRemoteCallWithTaskPermission(mController,
+ "startShortcutAndTaskWithLegacyTransition", (controller) ->
+ controller.mStageCoordinator.startShortcutAndTaskWithLegacyTransition(
+ shortcutInfo, taskId, mainOptions, sideOptions, sidePosition,
+ splitRatio, adapter));
+ }
+
+ @Override
public void startTasks(int mainTaskId, @Nullable Bundle mainOptions,
int sideTaskId, @Nullable Bundle sideOptions,
@SplitPosition int sidePosition, float splitRatio,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 21fc01e..8d405f4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -69,11 +69,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.app.WindowConfiguration;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ShortcutInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.devicestate.DeviceStateManager;
@@ -85,7 +85,6 @@
import android.util.Slog;
import android.view.Choreographer;
import android.view.IRemoteAnimationFinishedCallback;
-import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
@@ -513,6 +512,7 @@
mSplitLayout.setDivideRatio(splitRatio);
updateWindowBounds(mSplitLayout, wct);
wct.reorder(mRootTaskInfo.token, true);
+ wct.setForceTranslucent(mRootTaskInfo.token, false);
// Make sure the launch options will put tasks in the corresponding split roots
addActivityOptions(mainOptions, mMainStage);
@@ -530,132 +530,135 @@
void startTasksWithLegacyTransition(int mainTaskId, @Nullable Bundle mainOptions,
int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition,
float splitRatio, RemoteAnimationAdapter adapter) {
- startWithLegacyTransition(mainTaskId, sideTaskId, null /* pendingIntent */,
- null /* fillInIntent */, mainOptions, sideOptions, sidePosition, splitRatio,
- adapter);
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ if (sideOptions == null) sideOptions = new Bundle();
+ addActivityOptions(sideOptions, mSideStage);
+ wct.startTask(sideTaskId, sideOptions);
+
+ startWithLegacyTransition(wct, mainTaskId, mainOptions, sidePosition, splitRatio, adapter);
}
/** Start an intent and a task ordered by {@code intentFirst}. */
void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, Intent fillInIntent,
int taskId, @Nullable Bundle mainOptions, @Nullable Bundle sideOptions,
@SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) {
- startWithLegacyTransition(taskId, INVALID_TASK_ID, pendingIntent, fillInIntent,
- mainOptions, sideOptions, sidePosition, splitRatio, adapter);
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ if (sideOptions == null) sideOptions = new Bundle();
+ addActivityOptions(sideOptions, mSideStage);
+ wct.sendPendingIntent(pendingIntent, fillInIntent, sideOptions);
+
+ startWithLegacyTransition(wct, taskId, mainOptions, sidePosition, splitRatio, adapter);
}
- private void startWithLegacyTransition(int mainTaskId, int sideTaskId,
- @Nullable PendingIntent pendingIntent, @Nullable Intent fillInIntent,
- @Nullable Bundle mainOptions, @Nullable Bundle sideOptions,
+ void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo,
+ int taskId, @Nullable Bundle mainOptions, @Nullable Bundle sideOptions,
@SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) {
- final boolean withIntent = pendingIntent != null && fillInIntent != null;
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ if (sideOptions == null) sideOptions = new Bundle();
+ addActivityOptions(sideOptions, mSideStage);
+ wct.startShortcut(mContext.getPackageName(), shortcutInfo, sideOptions);
+
+ startWithLegacyTransition(wct, taskId, mainOptions, sidePosition, splitRatio, adapter);
+ }
+
+ private void startWithLegacyTransition(WindowContainerTransaction sideWct, int mainTaskId,
+ @Nullable Bundle mainOptions, @SplitPosition int sidePosition, float splitRatio,
+ RemoteAnimationAdapter adapter) {
// Init divider first to make divider leash for remote animation target.
mSplitLayout.init();
+ mSplitLayout.setDivideRatio(splitRatio);
+
// Set false to avoid record new bounds with old task still on top;
mShouldUpdateRecents = false;
mIsDividerRemoteAnimating = true;
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- final WindowContainerTransaction evictWct = new WindowContainerTransaction();
- prepareEvictChildTasks(SPLIT_POSITION_TOP_OR_LEFT, evictWct);
- prepareEvictChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, evictWct);
- // Need to add another wrapper here in shell so that we can inject the divider bar
- // and also manage the process elevation via setRunningRemote
- IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() {
+
+ LegacyTransitions.ILegacyTransition transition = new LegacyTransitions.ILegacyTransition() {
@Override
- public void onAnimationStart(@WindowManager.TransitionOldType int transit,
- RemoteAnimationTarget[] apps,
- RemoteAnimationTarget[] wallpapers,
- RemoteAnimationTarget[] nonApps,
- final IRemoteAnimationFinishedCallback finishedCallback) {
- RemoteAnimationTarget[] augmentedNonApps =
- new RemoteAnimationTarget[nonApps.length + 1];
- for (int i = 0; i < nonApps.length; ++i) {
- augmentedNonApps[i] = nonApps[i];
+ public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
+ RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
+ IRemoteAnimationFinishedCallback finishedCallback,
+ SurfaceControl.Transaction t) {
+ if (apps == null || apps.length == 0) {
+ onRemoteAnimationFinished(apps);
+ t.apply();
+ try {
+ adapter.getRunner().onAnimationCancelled(mKeyguardShowing);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error starting remote animation", e);
+ }
+ return;
}
- augmentedNonApps[augmentedNonApps.length - 1] = getDividerBarLegacyTarget();
+
+ // The surfaces of splitting tasks were placed with window bounds when preparing the
+ // transition, so update divider surface separately.
+ final RemoteAnimationTarget dividerTarget = getDividerBarLegacyTarget();
+ mSplitLayout.getRefDividerBounds(mTempRect1);
+ t.setLayer(dividerTarget.leash, Integer.MAX_VALUE)
+ .setPosition(dividerTarget.leash, mTempRect1.left, mTempRect1.top);
+ setDividerVisibility(true, t);
+
+ for (int i = 0; i < apps.length; ++i) {
+ if (apps[i].mode == MODE_OPENING) {
+ t.show(apps[i].leash);
+ }
+ }
+ t.apply();
IRemoteAnimationFinishedCallback wrapCallback =
new IRemoteAnimationFinishedCallback.Stub() {
@Override
public void onAnimationFinished() throws RemoteException {
- onRemoteAnimationFinishedOrCancelled(false /* cancel */, evictWct);
+ onRemoteAnimationFinished(apps);
finishedCallback.onAnimationFinished();
}
};
Transitions.setRunningRemoteTransitionDelegate(adapter.getCallingApplication());
try {
adapter.getRunner().onAnimationStart(transit, apps, wallpapers,
- augmentedNonApps, wrapCallback);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error starting remote animation", e);
- }
- }
-
- @Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
- onRemoteAnimationFinishedOrCancelled(true /* cancel */, evictWct);
- try {
- adapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
+ ArrayUtils.appendElement(RemoteAnimationTarget.class, nonApps,
+ dividerTarget), wrapCallback);
} catch (RemoteException e) {
Slog.e(TAG, "Error starting remote animation", e);
}
}
};
- RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter(
- wrapper, adapter.getDuration(), adapter.getStatusBarTransitionDelay());
- if (mainOptions == null) {
- mainOptions = ActivityOptions.makeRemoteAnimation(wrappedAdapter).toBundle();
- } else {
- ActivityOptions mainActivityOptions = ActivityOptions.fromBundle(mainOptions);
- mainActivityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter));
- mainOptions = mainActivityOptions.toBundle();
- }
-
- sideOptions = sideOptions != null ? sideOptions : new Bundle();
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
setSideStagePosition(sidePosition, wct);
-
- mSplitLayout.setDivideRatio(splitRatio);
if (!mMainStage.isActive()) {
- // Build a request WCT that will launch both apps such that task 0 is on the main stage
- // while task 1 is on the side stage.
mMainStage.activate(wct, false /* reparent */);
}
+
+ if (mainOptions == null) mainOptions = new Bundle();
+ addActivityOptions(mainOptions, mMainStage);
+ wct.startTask(mainTaskId, mainOptions);
+ wct.merge(sideWct, true);
+
updateWindowBounds(mSplitLayout, wct);
wct.reorder(mRootTaskInfo.token, true);
+ wct.setForceTranslucent(mRootTaskInfo.token, false);
- // Make sure the launch options will put tasks in the corresponding split roots
- addActivityOptions(mainOptions, mMainStage);
- addActivityOptions(sideOptions, mSideStage);
-
- // Add task launch requests
- wct.startTask(mainTaskId, mainOptions);
- if (withIntent) {
- wct.sendPendingIntent(pendingIntent, fillInIntent, sideOptions);
- } else {
- wct.startTask(sideTaskId, sideOptions);
- }
- // Using legacy transitions, so we can't use blast sync since it conflicts.
- mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> {
- setDividerVisibility(true, t);
- updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
- });
+ mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
}
- private void onRemoteAnimationFinishedOrCancelled(boolean cancel,
- WindowContainerTransaction evictWct) {
+ private void onRemoteAnimationFinished(RemoteAnimationTarget[] apps) {
mIsDividerRemoteAnimating = false;
mShouldUpdateRecents = true;
- // If any stage has no child after animation finished, it means that split will display
- // nothing, such status will happen if task and intent is same app but not support
- // multi-instance, we should exit split and expand that app as full screen.
- if (!cancel && (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0)) {
- mMainExecutor.execute(() ->
- exitSplitScreen(mMainStage.getChildCount() == 0
- ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
- } else {
- mSyncQueue.queue(evictWct);
+ if (apps == null || apps.length == 0) return;
+
+ // If any stage has no child after finished animation, that side of the split will display
+ // nothing. This might happen if starting the same app on the both sides while not
+ // supporting multi-instance. Exit the split screen and expand that app to full screen.
+ if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
+ mMainExecutor.execute(() -> exitSplitScreen(mMainStage.getChildCount() == 0
+ ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
+ return;
}
+
+ final WindowContainerTransaction evictWct = new WindowContainerTransaction();
+ prepareEvictNonOpeningChildTasks(SPLIT_POSITION_TOP_OR_LEFT, apps, evictWct);
+ prepareEvictNonOpeningChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, apps, evictWct);
+ mSyncQueue.queue(evictWct);
}
/**
@@ -1393,8 +1396,6 @@
wct.setForceTranslucent(mRootTaskInfo.token, false);
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> {
- updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
-
mSplitLayout.flingDividerToCenter();
});
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 6c65966..cff60f5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -44,6 +44,8 @@
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString;
+import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_OWNER_THUMBNAIL;
+import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_WORK_THUMBNAIL;
import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION;
@@ -903,11 +905,10 @@
private void attachThumbnail(@NonNull ArrayList<Animator> animations,
@NonNull Runnable finishCallback, TransitionInfo.Change change,
TransitionInfo.AnimationOptions options, float cornerRadius) {
- final boolean isTask = change.getTaskInfo() != null;
final boolean isOpen = Transitions.isOpeningType(change.getMode());
final boolean isClose = Transitions.isClosingType(change.getMode());
if (isOpen) {
- if (options.getType() == ANIM_OPEN_CROSS_PROFILE_APPS && isTask) {
+ if (options.getType() == ANIM_OPEN_CROSS_PROFILE_APPS) {
attachCrossProfileThumbnailAnimation(animations, finishCallback, change,
cornerRadius);
} else if (options.getType() == ANIM_THUMBNAIL_SCALE_UP) {
@@ -922,8 +923,13 @@
@NonNull Runnable finishCallback, TransitionInfo.Change change, float cornerRadius) {
final Rect bounds = change.getEndAbsBounds();
// Show the right drawable depending on the user we're transitioning to.
- final Drawable thumbnailDrawable = change.getTaskInfo().userId == mCurrentUserId
- ? mContext.getDrawable(R.drawable.ic_account_circle) : mEnterpriseThumbnailDrawable;
+ final Drawable thumbnailDrawable = change.hasFlags(FLAG_CROSS_PROFILE_OWNER_THUMBNAIL)
+ ? mContext.getDrawable(R.drawable.ic_account_circle)
+ : change.hasFlags(FLAG_CROSS_PROFILE_WORK_THUMBNAIL)
+ ? mEnterpriseThumbnailDrawable : null;
+ if (thumbnailDrawable == null) {
+ return;
+ }
final HardwareBuffer thumbnail = mTransitionAnimation.createCrossProfileAppsThumbnail(
thumbnailDrawable, bounds);
if (thumbnail == null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index e7695926..83aa539 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -148,7 +148,13 @@
public void onClick(View v) {
final int id = v.getId();
if (id == R.id.close_window) {
- mActivityTaskManager.removeTask(mTaskId);
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.removeTask(mTaskToken);
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ mTransitionStarter.startRemoveTransition(wct);
+ } else {
+ mSyncQueue.queue(wct);
+ }
} else if (id == R.id.maximize_window) {
WindowContainerTransaction wct = new WindowContainerTransaction();
RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
@@ -199,6 +205,10 @@
}
private void handleEventForMove(MotionEvent e) {
+ if (mTaskOrganizer.getRunningTaskInfo(mTaskId).getWindowingMode()
+ == WINDOWING_MODE_FULLSCREEN) {
+ return;
+ }
switch (e.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mDragPointerId = e.getPointerId(0);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index dc3deb1..5040bc3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -34,7 +34,7 @@
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.desktopmode.DesktopModeConstants;
+import com.android.wm.shell.desktopmode.DesktopMode;
/**
* Defines visuals and behaviors of a window decoration of a caption bar and shadows. It works with
@@ -142,7 +142,7 @@
return;
}
- if (oldDecorationSurface != mDecorationContainerSurface) {
+ if (oldDecorationSurface != mDecorationContainerSurface || mDragResizeListener == null) {
closeDragResizeListener();
mDragResizeListener = new DragResizeInputListener(
mContext,
@@ -164,7 +164,7 @@
View caption = mResult.mRootView.findViewById(R.id.caption);
caption.setOnTouchListener(mOnCaptionTouchListener);
View maximize = caption.findViewById(R.id.maximize_window);
- if (DesktopModeConstants.IS_FEATURE_ENABLED) {
+ if (DesktopMode.IS_SUPPORTED) {
// Hide maximize button when desktop mode is available
maximize.setVisibility(View.GONE);
} else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
index f512b0d..3d01495 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
@@ -87,7 +87,7 @@
try {
mWindowSession.grantInputChannel(
mDisplayId,
- new SurfaceControl(mDecorationSurface, TAG),
+ mDecorationSurface,
mFakeWindow,
null /* hostInputToken */,
FLAG_NOT_FOCUSABLE,
@@ -150,8 +150,7 @@
mWindowSession.updateInputChannel(
mInputChannel.getToken(),
mDisplayId,
- new SurfaceControl(
- mDecorationSurface, "DragResizeInputListener#setTouchRegion"),
+ mDecorationSurface,
FLAG_NOT_FOCUSABLE,
PRIVATE_FLAG_TRUSTED_OVERLAY,
touchRegion);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 5e64a06..3e3a864 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -66,6 +66,7 @@
final DisplayController mDisplayController;
final ShellTaskOrganizer mTaskOrganizer;
final Supplier<SurfaceControl.Builder> mSurfaceControlBuilderSupplier;
+ final Supplier<SurfaceControl.Transaction> mSurfaceControlTransactionSupplier;
final Supplier<WindowContainerTransaction> mWindowContainerTransactionSupplier;
final SurfaceControlViewHostFactory mSurfaceControlViewHostFactory;
private final DisplayController.OnDisplaysChangedListener mOnDisplaysChangedListener =
@@ -89,7 +90,8 @@
SurfaceControl mDecorationContainerSurface;
SurfaceControl mTaskBackgroundSurface;
- private final CaptionWindowManager mCaptionWindowManager;
+ SurfaceControl mCaptionContainerSurface;
+ private CaptionWindowManager mCaptionWindowManager;
private SurfaceControlViewHost mViewHost;
private final Rect mCaptionInsetsRect = new Rect();
@@ -103,8 +105,8 @@
RunningTaskInfo taskInfo,
SurfaceControl taskSurface) {
this(context, displayController, taskOrganizer, taskInfo, taskSurface,
- SurfaceControl.Builder::new, WindowContainerTransaction::new,
- new SurfaceControlViewHostFactory() {});
+ SurfaceControl.Builder::new, SurfaceControl.Transaction::new,
+ WindowContainerTransaction::new, new SurfaceControlViewHostFactory() {});
}
WindowDecoration(
@@ -114,6 +116,7 @@
RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
+ Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
mContext = context;
@@ -122,16 +125,12 @@
mTaskInfo = taskInfo;
mTaskSurface = taskSurface;
mSurfaceControlBuilderSupplier = surfaceControlBuilderSupplier;
+ mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier;
mWindowContainerTransactionSupplier = windowContainerTransactionSupplier;
mSurfaceControlViewHostFactory = surfaceControlViewHostFactory;
mDisplay = mDisplayController.getDisplay(mTaskInfo.displayId);
mDecorWindowContext = mContext.createConfigurationContext(mTaskInfo.getConfiguration());
-
- // Put caption under task surface because ViewRootImpl sets the destination frame of
- // windowless window layers and BLASTBufferQueue#update() doesn't support offset.
- mCaptionWindowManager =
- new CaptionWindowManager(mTaskInfo.getConfiguration(), mTaskSurface);
}
/**
@@ -213,6 +212,7 @@
startT.setPosition(
mDecorationContainerSurface, decorContainerOffsetX, decorContainerOffsetY)
.setWindowCrop(mDecorationContainerSurface, outResult.mWidth, outResult.mHeight)
+ // TODO(b/244455401): Change the z-order when it's better organized
.setLayer(mDecorationContainerSurface, mTaskInfo.numActivities + 1)
.show(mDecorationContainerSurface);
@@ -234,12 +234,35 @@
startT.setWindowCrop(mTaskBackgroundSurface, taskBounds.width(), taskBounds.height())
.setShadowRadius(mTaskBackgroundSurface, shadowRadius)
.setColor(mTaskBackgroundSurface, mTmpColor)
+ // TODO(b/244455401): Change the z-order when it's better organized
.setLayer(mTaskBackgroundSurface, -1)
.show(mTaskBackgroundSurface);
+ // CaptionContainerSurface, CaptionWindowManager
+ if (mCaptionContainerSurface == null) {
+ final SurfaceControl.Builder builder = mSurfaceControlBuilderSupplier.get();
+ mCaptionContainerSurface = builder
+ .setName("Caption container of Task=" + mTaskInfo.taskId)
+ .setContainerLayer()
+ .setParent(mDecorationContainerSurface)
+ .build();
+ }
+
+ final int captionHeight = (int) Math.ceil(captionHeightDp * outResult.mDensity);
+ startT.setPosition(
+ mCaptionContainerSurface, -decorContainerOffsetX, -decorContainerOffsetY)
+ .setWindowCrop(mCaptionContainerSurface, taskBounds.width(), captionHeight)
+ .show(mCaptionContainerSurface);
+
+ if (mCaptionWindowManager == null) {
+ // Put caption under a container surface because ViewRootImpl sets the destination frame
+ // of windowless window layers and BLASTBufferQueue#update() doesn't support offset.
+ mCaptionWindowManager = new CaptionWindowManager(
+ mTaskInfo.getConfiguration(), mCaptionContainerSurface);
+ }
+
// Caption view
mCaptionWindowManager.setConfiguration(taskConfig);
- final int captionHeight = (int) Math.ceil(captionHeightDp * outResult.mDensity);
final WindowManager.LayoutParams lp =
new WindowManager.LayoutParams(taskBounds.width(), captionHeight,
WindowManager.LayoutParams.TYPE_APPLICATION,
@@ -262,7 +285,7 @@
mCaptionInsetsRect.bottom = mCaptionInsetsRect.top + captionHeight;
wct.addRectInsetsProvider(mTaskInfo.token, mCaptionInsetsRect, CAPTION_INSETS_TYPES);
} else {
- outResult.mRootView.setVisibility(View.GONE);
+ startT.hide(mCaptionContainerSurface);
}
// Task surface itself
@@ -298,14 +321,30 @@
mViewHost = null;
}
+ mCaptionWindowManager = null;
+
+ final SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
+ boolean released = false;
+ if (mCaptionContainerSurface != null) {
+ t.remove(mCaptionContainerSurface);
+ mCaptionContainerSurface = null;
+ released = true;
+ }
+
if (mDecorationContainerSurface != null) {
- mDecorationContainerSurface.release();
+ t.remove(mDecorationContainerSurface);
mDecorationContainerSurface = null;
+ released = true;
}
if (mTaskBackgroundSurface != null) {
- mTaskBackgroundSurface.release();
+ t.remove(mTaskBackgroundSurface);
mTaskBackgroundSurface = null;
+ released = true;
+ }
+
+ if (released) {
+ t.apply();
}
final WindowContainerTransaction wct = mWindowContainerTransactionSupplier.get();
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index 9ba5166..61ac498 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -132,7 +132,7 @@
testSpec.assertLayers {
val pipLayerList = this.layers { it.name.contains(layerName) && it.isVisible }
pipLayerList.zipWithNext { previous, current ->
- current.visibleRegion.coversAtMost(previous.visibleRegion.region)
+ current.visibleRegion.notBiggerThan(previous.visibleRegion.region)
}
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestShellExecutor.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestShellExecutor.java
index da95c77..fe8b305 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestShellExecutor.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestShellExecutor.java
@@ -48,9 +48,10 @@
}
public void flushAll() {
- for (Runnable r : mRunnables) {
+ final ArrayList<Runnable> tmpRunnable = new ArrayList<>(mRunnables);
+ mRunnables.clear();
+ for (Runnable r : tmpRunnable) {
r.run();
}
- mRunnables.clear();
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 5b3b8fd..90a3773 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -54,6 +54,7 @@
import android.view.SurfaceControl;
import android.window.BackEvent;
import android.window.BackNavigationInfo;
+import android.window.IBackNaviAnimationController;
import android.window.IOnBackInvokedCallback;
import androidx.test.filters.SmallTest;
@@ -98,6 +99,9 @@
@Mock
private IOnBackInvokedCallback mIOnBackInvokedCallback;
+ @Mock
+ private IBackNaviAnimationController mIBackNaviAnimationController;
+
private BackAnimationController mController;
private int mEventTime = 0;
@@ -127,7 +131,7 @@
SurfaceControl screenshotSurface,
HardwareBuffer hardwareBuffer,
int backType,
- IOnBackInvokedCallback onBackInvokedCallback) {
+ IOnBackInvokedCallback onBackInvokedCallback, boolean prepareAnimation) {
BackNavigationInfo.Builder builder = new BackNavigationInfo.Builder()
.setType(backType)
.setDepartingAnimationTarget(topAnimationTarget)
@@ -135,7 +139,8 @@
.setScreenshotBuffer(hardwareBuffer)
.setTaskWindowConfiguration(new WindowConfiguration())
.setOnBackNavigationDone(new RemoteCallback((bundle) -> {}))
- .setOnBackInvokedCallback(onBackInvokedCallback);
+ .setOnBackInvokedCallback(onBackInvokedCallback)
+ .setPrepareAnimation(prepareAnimation);
createNavigationInfo(builder);
}
@@ -143,7 +148,7 @@
private void createNavigationInfo(BackNavigationInfo.Builder builder) {
try {
doReturn(builder.build()).when(mActivityTaskManager)
- .startBackNavigation(anyBoolean(), any());
+ .startBackNavigation(anyBoolean(), any(), any());
} catch (RemoteException ex) {
ex.rethrowFromSystemServer();
}
@@ -175,7 +180,7 @@
SurfaceControl screenshotSurface = new SurfaceControl();
HardwareBuffer hardwareBuffer = mock(HardwareBuffer.class);
createNavigationInfo(createAnimationTarget(), screenshotSurface, hardwareBuffer,
- BackNavigationInfo.TYPE_CROSS_ACTIVITY, null);
+ BackNavigationInfo.TYPE_CROSS_ACTIVITY, null, true);
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
verify(mTransaction).setBuffer(screenshotSurface, hardwareBuffer);
verify(mTransaction).setVisibility(screenshotSurface, true);
@@ -188,7 +193,7 @@
HardwareBuffer hardwareBuffer = mock(HardwareBuffer.class);
RemoteAnimationTarget animationTarget = createAnimationTarget();
createNavigationInfo(animationTarget, screenshotSurface, hardwareBuffer,
- BackNavigationInfo.TYPE_CROSS_ACTIVITY, null);
+ BackNavigationInfo.TYPE_CROSS_ACTIVITY, null, true);
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
doMotionEvent(MotionEvent.ACTION_MOVE, 100);
// b/207481538, we check that the surface is not moved for now, we can re-enable this once
@@ -222,15 +227,16 @@
mController.setBackToLauncherCallback(mIOnBackInvokedCallback);
RemoteAnimationTarget animationTarget = createAnimationTarget();
createNavigationInfo(animationTarget, null, null,
- BackNavigationInfo.TYPE_RETURN_TO_HOME, null);
+ BackNavigationInfo.TYPE_RETURN_TO_HOME, null, true);
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
// Check that back start and progress is dispatched when first move.
doMotionEvent(MotionEvent.ACTION_MOVE, 100);
+ simulateRemoteAnimationStart(BackNavigationInfo.TYPE_RETURN_TO_HOME, animationTarget);
verify(mIOnBackInvokedCallback).onBackStarted();
ArgumentCaptor<BackEvent> backEventCaptor = ArgumentCaptor.forClass(BackEvent.class);
- verify(mIOnBackInvokedCallback).onBackProgressed(backEventCaptor.capture());
+ verify(mIOnBackInvokedCallback, atLeastOnce()).onBackProgressed(backEventCaptor.capture());
assertEquals(animationTarget, backEventCaptor.getValue().getDepartingAnimationTarget());
// Check that back invocation is dispatched.
@@ -255,7 +261,7 @@
IOnBackInvokedCallback appCallback = mock(IOnBackInvokedCallback.class);
ArgumentCaptor<BackEvent> backEventCaptor = ArgumentCaptor.forClass(BackEvent.class);
createNavigationInfo(animationTarget, null, null,
- BackNavigationInfo.TYPE_RETURN_TO_HOME, appCallback);
+ BackNavigationInfo.TYPE_RETURN_TO_HOME, appCallback, false);
triggerBackGesture();
@@ -273,9 +279,10 @@
mController.setBackToLauncherCallback(mIOnBackInvokedCallback);
RemoteAnimationTarget animationTarget = createAnimationTarget();
createNavigationInfo(animationTarget, null, null,
- BackNavigationInfo.TYPE_RETURN_TO_HOME, null);
+ BackNavigationInfo.TYPE_RETURN_TO_HOME, null, true);
triggerBackGesture();
+ simulateRemoteAnimationStart(BackNavigationInfo.TYPE_RETURN_TO_HOME, animationTarget);
// Check that back invocation is dispatched.
verify(mIOnBackInvokedCallback).onBackInvoked();
@@ -294,6 +301,7 @@
// Verify that we start accepting gestures again once transition finishes.
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
doMotionEvent(MotionEvent.ACTION_MOVE, 100);
+ simulateRemoteAnimationStart(BackNavigationInfo.TYPE_RETURN_TO_HOME, animationTarget);
verify(mIOnBackInvokedCallback).onBackStarted();
}
@@ -302,15 +310,17 @@
mController.setBackToLauncherCallback(mIOnBackInvokedCallback);
RemoteAnimationTarget animationTarget = createAnimationTarget();
createNavigationInfo(animationTarget, null, null,
- BackNavigationInfo.TYPE_RETURN_TO_HOME, null);
+ BackNavigationInfo.TYPE_RETURN_TO_HOME, null, true);
triggerBackGesture();
+ simulateRemoteAnimationStart(BackNavigationInfo.TYPE_RETURN_TO_HOME, animationTarget);
reset(mIOnBackInvokedCallback);
// Simulate transition timeout.
mShellExecutor.flushAll();
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
doMotionEvent(MotionEvent.ACTION_MOVE, 100);
+ simulateRemoteAnimationStart(BackNavigationInfo.TYPE_RETURN_TO_HOME, animationTarget);
verify(mIOnBackInvokedCallback).onBackStarted();
}
@@ -321,11 +331,12 @@
RemoteAnimationTarget animationTarget = createAnimationTarget();
createNavigationInfo(animationTarget, null, null,
- BackNavigationInfo.TYPE_RETURN_TO_HOME, null);
+ BackNavigationInfo.TYPE_RETURN_TO_HOME, null, true);
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
// Check that back start and progress is dispatched when first move.
doMotionEvent(MotionEvent.ACTION_MOVE, 100);
+ simulateRemoteAnimationStart(BackNavigationInfo.TYPE_RETURN_TO_HOME, animationTarget);
verify(mIOnBackInvokedCallback).onBackStarted();
// Check that back invocation is dispatched.
@@ -349,4 +360,14 @@
BackEvent.EDGE_LEFT);
mEventTime += 10;
}
+
+ private void simulateRemoteAnimationStart(int type, RemoteAnimationTarget animationTarget)
+ throws RemoteException {
+ if (mController.mIBackAnimationRunner != null) {
+ final RemoteAnimationTarget[] targets = new RemoteAnimationTarget[]{animationTarget};
+ mController.mIBackAnimationRunner.onAnimationStart(mIBackNaviAnimationController, type,
+ targets, null, null);
+ mShellExecutor.flushAll();
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
index 58f20da..7afef8b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
@@ -99,7 +99,7 @@
WINDOWING_MODE_FREEFORM)).thenReturn(displayWct);
// The test
- mController.updateDesktopModeEnabled(true);
+ mController.updateDesktopModeActive(true);
ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
WindowContainerTransaction.class);
@@ -144,7 +144,7 @@
WINDOWING_MODE_FULLSCREEN)).thenReturn(displayWct);
// The test
- mController.updateDesktopModeEnabled(false);
+ mController.updateDesktopModeActive(false);
ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
WindowContainerTransaction.class);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java
new file mode 100644
index 0000000..0fd5cb0
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.freeform;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_OPEN;
+
+import static com.android.wm.shell.transition.Transitions.TRANSIT_MAXIMIZE;
+import static com.android.wm.shell.transition.Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.same;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.IBinder;
+import android.view.SurfaceControl;
+import android.window.IWindowContainerToken;
+import android.window.TransitionInfo;
+import android.window.WindowContainerToken;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.fullscreen.FullscreenTaskListener;
+import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.transition.Transitions;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests of {@link FreeformTaskTransitionObserver}
+ */
+@SmallTest
+public class FreeformTaskTransitionObserverTest {
+
+ @Mock
+ private ShellInit mShellInit;
+ @Mock
+ private Transitions mTransitions;
+ @Mock
+ private FullscreenTaskListener<?> mFullscreenTaskListener;
+ @Mock
+ private FreeformTaskListener<?> mFreeformTaskListener;
+
+ private FreeformTaskTransitionObserver mTransitionObserver;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ PackageManager pm = mock(PackageManager.class);
+ doReturn(true).when(pm).hasSystemFeature(
+ PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT);
+ final Context context = mock(Context.class);
+ doReturn(pm).when(context).getPackageManager();
+
+ mTransitionObserver = new FreeformTaskTransitionObserver(
+ context, mShellInit, mTransitions, mFullscreenTaskListener, mFreeformTaskListener);
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ final ArgumentCaptor<Runnable> initRunnableCaptor = ArgumentCaptor.forClass(
+ Runnable.class);
+ verify(mShellInit).addInitCallback(initRunnableCaptor.capture(),
+ same(mTransitionObserver));
+ initRunnableCaptor.getValue().run();
+ } else {
+ mTransitionObserver.onInit();
+ }
+ }
+
+ @Test
+ public void testRegistersObserverAtInit() {
+ verify(mTransitions).registerObserver(same(mTransitionObserver));
+ }
+
+ @Test
+ public void testCreatesWindowDecorOnOpenTransition_freeform() {
+ final TransitionInfo.Change change =
+ createChange(TRANSIT_OPEN, 1, WINDOWING_MODE_FREEFORM);
+ final TransitionInfo info = new TransitionInfo(TRANSIT_OPEN, 0);
+ info.addChange(change);
+
+ final IBinder transition = mock(IBinder.class);
+ final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
+ mTransitionObserver.onTransitionStarting(transition);
+
+ verify(mFreeformTaskListener).createWindowDecoration(change, startT, finishT);
+ }
+
+ @Test
+ public void testObtainsWindowDecorOnCloseTransition_freeform() {
+ final TransitionInfo.Change change =
+ createChange(TRANSIT_CLOSE, 1, WINDOWING_MODE_FREEFORM);
+ final TransitionInfo info = new TransitionInfo(TRANSIT_CLOSE, 0);
+ info.addChange(change);
+
+ final IBinder transition = mock(IBinder.class);
+ final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
+ mTransitionObserver.onTransitionStarting(transition);
+
+ verify(mFreeformTaskListener).giveWindowDecoration(change.getTaskInfo(), startT, finishT);
+ }
+
+ @Test
+ public void testDoesntCloseWindowDecorDuringCloseTransition() throws Exception {
+ final TransitionInfo.Change change =
+ createChange(TRANSIT_CLOSE, 1, WINDOWING_MODE_FREEFORM);
+ final TransitionInfo info = new TransitionInfo(TRANSIT_CLOSE, 0);
+ info.addChange(change);
+
+ final AutoCloseable windowDecor = mock(AutoCloseable.class);
+ doReturn(windowDecor).when(mFreeformTaskListener).giveWindowDecoration(
+ eq(change.getTaskInfo()), any(), any());
+
+ final IBinder transition = mock(IBinder.class);
+ final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
+ mTransitionObserver.onTransitionStarting(transition);
+
+ verify(windowDecor, never()).close();
+ }
+
+ @Test
+ public void testClosesWindowDecorAfterCloseTransition() throws Exception {
+ final TransitionInfo.Change change =
+ createChange(TRANSIT_CLOSE, 1, WINDOWING_MODE_FREEFORM);
+ final TransitionInfo info = new TransitionInfo(TRANSIT_CLOSE, 0);
+ info.addChange(change);
+
+ final AutoCloseable windowDecor = mock(AutoCloseable.class);
+ doReturn(windowDecor).when(mFreeformTaskListener).giveWindowDecoration(
+ eq(change.getTaskInfo()), any(), any());
+
+ final IBinder transition = mock(IBinder.class);
+ final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
+ mTransitionObserver.onTransitionStarting(transition);
+ mTransitionObserver.onTransitionFinished(transition, false);
+
+ verify(windowDecor).close();
+ }
+
+ @Test
+ public void testClosesMergedWindowDecorationAfterTransitionFinishes() throws Exception {
+ // The playing transition
+ final TransitionInfo.Change change1 =
+ createChange(TRANSIT_OPEN, 1, WINDOWING_MODE_FREEFORM);
+ final TransitionInfo info1 = new TransitionInfo(TRANSIT_OPEN, 0);
+ info1.addChange(change1);
+
+ final IBinder transition1 = mock(IBinder.class);
+ final SurfaceControl.Transaction startT1 = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction finishT1 = mock(SurfaceControl.Transaction.class);
+ mTransitionObserver.onTransitionReady(transition1, info1, startT1, finishT1);
+ mTransitionObserver.onTransitionStarting(transition1);
+
+ // The merged transition
+ final TransitionInfo.Change change2 =
+ createChange(TRANSIT_CLOSE, 2, WINDOWING_MODE_FREEFORM);
+ final TransitionInfo info2 = new TransitionInfo(TRANSIT_CLOSE, 0);
+ info2.addChange(change2);
+
+ final AutoCloseable windowDecor2 = mock(AutoCloseable.class);
+ doReturn(windowDecor2).when(mFreeformTaskListener).giveWindowDecoration(
+ eq(change2.getTaskInfo()), any(), any());
+
+ final IBinder transition2 = mock(IBinder.class);
+ final SurfaceControl.Transaction startT2 = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction finishT2 = mock(SurfaceControl.Transaction.class);
+ mTransitionObserver.onTransitionReady(transition2, info2, startT2, finishT2);
+ mTransitionObserver.onTransitionMerged(transition2, transition1);
+
+ mTransitionObserver.onTransitionFinished(transition1, false);
+
+ verify(windowDecor2).close();
+ }
+
+ @Test
+ public void testClosesAllWindowDecorsOnTransitionMergeAfterCloseTransitions() throws Exception {
+ // The playing transition
+ final TransitionInfo.Change change1 =
+ createChange(TRANSIT_CLOSE, 1, WINDOWING_MODE_FREEFORM);
+ final TransitionInfo info1 = new TransitionInfo(TRANSIT_CLOSE, 0);
+ info1.addChange(change1);
+
+ final AutoCloseable windowDecor1 = mock(AutoCloseable.class);
+ doReturn(windowDecor1).when(mFreeformTaskListener).giveWindowDecoration(
+ eq(change1.getTaskInfo()), any(), any());
+
+ final IBinder transition1 = mock(IBinder.class);
+ final SurfaceControl.Transaction startT1 = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction finishT1 = mock(SurfaceControl.Transaction.class);
+ mTransitionObserver.onTransitionReady(transition1, info1, startT1, finishT1);
+ mTransitionObserver.onTransitionStarting(transition1);
+
+ // The merged transition
+ final TransitionInfo.Change change2 =
+ createChange(TRANSIT_CLOSE, 2, WINDOWING_MODE_FREEFORM);
+ final TransitionInfo info2 = new TransitionInfo(TRANSIT_CLOSE, 0);
+ info2.addChange(change2);
+
+ final AutoCloseable windowDecor2 = mock(AutoCloseable.class);
+ doReturn(windowDecor2).when(mFreeformTaskListener).giveWindowDecoration(
+ eq(change2.getTaskInfo()), any(), any());
+
+ final IBinder transition2 = mock(IBinder.class);
+ final SurfaceControl.Transaction startT2 = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction finishT2 = mock(SurfaceControl.Transaction.class);
+ mTransitionObserver.onTransitionReady(transition2, info2, startT2, finishT2);
+ mTransitionObserver.onTransitionMerged(transition2, transition1);
+
+ mTransitionObserver.onTransitionFinished(transition1, false);
+
+ verify(windowDecor1).close();
+ verify(windowDecor2).close();
+ }
+
+ @Test
+ public void testTransfersWindowDecorOnMaximize() {
+ final TransitionInfo.Change change =
+ createChange(TRANSIT_CHANGE, 1, WINDOWING_MODE_FULLSCREEN);
+ final TransitionInfo info = new TransitionInfo(TRANSIT_MAXIMIZE, 0);
+ info.addChange(change);
+
+ final AutoCloseable windowDecor = mock(AutoCloseable.class);
+ doReturn(windowDecor).when(mFreeformTaskListener).giveWindowDecoration(
+ eq(change.getTaskInfo()), any(), any());
+
+ final IBinder transition = mock(IBinder.class);
+ final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
+ mTransitionObserver.onTransitionStarting(transition);
+
+ verify(mFreeformTaskListener).giveWindowDecoration(change.getTaskInfo(), startT, finishT);
+ verify(mFullscreenTaskListener).adoptWindowDecoration(
+ eq(change), same(startT), same(finishT), any());
+ }
+
+ @Test
+ public void testTransfersWindowDecorOnRestoreFromMaximize() {
+ final TransitionInfo.Change change =
+ createChange(TRANSIT_CHANGE, 1, WINDOWING_MODE_FREEFORM);
+ final TransitionInfo info = new TransitionInfo(TRANSIT_RESTORE_FROM_MAXIMIZE, 0);
+ info.addChange(change);
+
+ final IBinder transition = mock(IBinder.class);
+ final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
+ mTransitionObserver.onTransitionStarting(transition);
+
+ verify(mFullscreenTaskListener).giveWindowDecoration(change.getTaskInfo(), startT, finishT);
+ verify(mFreeformTaskListener).adoptWindowDecoration(
+ eq(change), same(startT), same(finishT), any());
+ }
+
+ private static TransitionInfo.Change createChange(int mode, int taskId, int windowingMode) {
+ final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
+ taskInfo.taskId = taskId;
+ taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
+
+ final TransitionInfo.Change change = new TransitionInfo.Change(
+ new WindowContainerToken(mock(IWindowContainerToken.class)),
+ mock(SurfaceControl.class));
+ change.setMode(mode);
+ change.setTaskInfo(taskInfo);
+ return change;
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
index 0059846..262e429 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
@@ -64,7 +64,7 @@
initializeMockResources();
mPipBoundsState = new PipBoundsState(mContext);
mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState,
- new PipSnapAlgorithm());
+ new PipSnapAlgorithm(), new PipKeepClearAlgorithm() {});
mPipBoundsState.setDisplayLayout(
new DisplayLayout(mDefaultDisplayInfo, mContext.getResources(), true, true));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index 579638d..9088077 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -98,7 +98,7 @@
mPipBoundsState = new PipBoundsState(mContext);
mPipTransitionState = new PipTransitionState();
mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState,
- new PipSnapAlgorithm());
+ new PipSnapAlgorithm(), new PipKeepClearAlgorithm() {});
mMainExecutor = new TestShellExecutor();
mPipTaskOrganizer = new PipTaskOrganizer(mContext,
mMockSyncTransactionQueue, mPipTransitionState, mPipBoundsState,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java
similarity index 64%
rename from libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithmTest.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java
index e0f7e35..4d7e9e4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithmTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java
@@ -34,61 +34,61 @@
import java.util.Set;
/**
- * Unit tests against {@link PipKeepClearAlgorithm}.
+ * Unit tests against {@link PhonePipKeepClearAlgorithm}.
*/
@RunWith(AndroidTestingRunner.class)
@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class PipKeepClearAlgorithmTest extends ShellTestCase {
+public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
- private PipKeepClearAlgorithm mPipKeepClearAlgorithm;
+ private PhonePipKeepClearAlgorithm mPipKeepClearAlgorithm;
private static final Rect DISPLAY_BOUNDS = new Rect(0, 0, 1000, 1000);
@Before
public void setUp() throws Exception {
- mPipKeepClearAlgorithm = new PipKeepClearAlgorithm();
+ mPipKeepClearAlgorithm = new PhonePipKeepClearAlgorithm(mContext);
}
@Test
- public void adjust_withCollidingRestrictedKeepClearAreas_movesBounds() {
+ public void findUnoccludedPosition_withCollidingRestrictedKeepClearArea_movesBounds() {
final Rect inBounds = new Rect(0, 0, 100, 100);
final Rect keepClearRect = new Rect(50, 50, 150, 150);
- final Rect outBounds = mPipKeepClearAlgorithm.adjust(inBounds, Set.of(keepClearRect),
- Set.of(), DISPLAY_BOUNDS);
+ final Rect outBounds = mPipKeepClearAlgorithm.findUnoccludedPosition(inBounds,
+ Set.of(keepClearRect), Set.of(), DISPLAY_BOUNDS);
assertFalse(outBounds.contains(keepClearRect));
}
@Test
- public void adjust_withNonCollidingRestrictedKeepClearAreas_boundsDoNotChange() {
+ public void findUnoccludedPosition_withNonCollidingRestrictedKeepClearArea_boundsUnchanged() {
final Rect inBounds = new Rect(0, 0, 100, 100);
final Rect keepClearRect = new Rect(100, 100, 150, 150);
- final Rect outBounds = mPipKeepClearAlgorithm.adjust(inBounds, Set.of(keepClearRect),
- Set.of(), DISPLAY_BOUNDS);
+ final Rect outBounds = mPipKeepClearAlgorithm.findUnoccludedPosition(inBounds,
+ Set.of(keepClearRect), Set.of(), DISPLAY_BOUNDS);
assertEquals(inBounds, outBounds);
}
@Test
- public void adjust_withCollidingUnrestrictedKeepClearAreas_boundsDoNotChange() {
+ public void findUnoccludedPosition_withCollidingUnrestrictedKeepClearArea_moveBounds() {
// TODO(b/183746978): update this test to accommodate for the updated algorithm
final Rect inBounds = new Rect(0, 0, 100, 100);
final Rect keepClearRect = new Rect(50, 50, 150, 150);
- final Rect outBounds = mPipKeepClearAlgorithm.adjust(inBounds, Set.of(),
+ final Rect outBounds = mPipKeepClearAlgorithm.findUnoccludedPosition(inBounds, Set.of(),
Set.of(keepClearRect), DISPLAY_BOUNDS);
- assertEquals(inBounds, outBounds);
+ assertFalse(outBounds.contains(keepClearRect));
}
@Test
- public void adjust_withNonCollidingUnrestrictedKeepClearAreas_boundsDoNotChange() {
+ public void findUnoccludedPosition_withNonCollidingUnrestrictedKeepClearArea_boundsUnchanged() {
final Rect inBounds = new Rect(0, 0, 100, 100);
final Rect keepClearRect = new Rect(100, 100, 150, 150);
- final Rect outBounds = mPipKeepClearAlgorithm.adjust(inBounds, Set.of(),
+ final Rect outBounds = mPipKeepClearAlgorithm.findUnoccludedPosition(inBounds, Set.of(),
Set.of(keepClearRect), DISPLAY_BOUNDS);
assertEquals(inBounds, outBounds);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
index eb5726b..1b5091f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
@@ -64,6 +64,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.Optional;
@@ -85,7 +86,7 @@
@Mock private PhonePipMenuController mMockPhonePipMenuController;
@Mock private PipAppOpsListener mMockPipAppOpsListener;
@Mock private PipBoundsAlgorithm mMockPipBoundsAlgorithm;
- @Mock private PipKeepClearAlgorithm mMockPipKeepClearAlgorithm;
+ @Mock private PhonePipKeepClearAlgorithm mMockPipKeepClearAlgorithm;
@Mock private PipSnapAlgorithm mMockPipSnapAlgorithm;
@Mock private PipMediaController mMockPipMediaController;
@Mock private PipTaskOrganizer mMockPipTaskOrganizer;
@@ -267,7 +268,20 @@
}
@Test
- public void onKeepClearAreasChanged_updatesPipBoundsState() {
+ public void onKeepClearAreasChanged_featureDisabled_pipBoundsStateDoesntChange() {
+ final int displayId = 1;
+ final Rect keepClearArea = new Rect(0, 0, 10, 10);
+ when(mMockPipBoundsState.getDisplayId()).thenReturn(displayId);
+
+ mPipController.mDisplaysChangedListener.onKeepClearAreasChanged(
+ displayId, Set.of(keepClearArea), Set.of());
+
+ verify(mMockPipBoundsState, never()).setKeepClearAreas(Mockito.anySet(), Mockito.anySet());
+ }
+
+ @Test
+ public void onKeepClearAreasChanged_featureEnabled_updatesPipBoundsState() {
+ mPipController.setEnablePipKeepClearAlgorithm(true);
final int displayId = 1;
final Rect keepClearArea = new Rect(0, 0, 10, 10);
when(mMockPipBoundsState.getDisplayId()).thenReturn(displayId);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java
index dd10aa7..dba037d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java
@@ -36,6 +36,7 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
+import com.android.wm.shell.pip.PipKeepClearAlgorithm;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
@@ -87,8 +88,10 @@
MockitoAnnotations.initMocks(this);
mPipBoundsState = new PipBoundsState(mContext);
final PipSnapAlgorithm pipSnapAlgorithm = new PipSnapAlgorithm();
+ final PipKeepClearAlgorithm pipKeepClearAlgorithm =
+ new PipKeepClearAlgorithm() {};
final PipBoundsAlgorithm pipBoundsAlgorithm = new PipBoundsAlgorithm(mContext,
- mPipBoundsState, pipSnapAlgorithm);
+ mPipBoundsState, pipSnapAlgorithm, pipKeepClearAlgorithm);
final PipMotionHelper motionHelper = new PipMotionHelper(mContext, mPipBoundsState,
mPipTaskOrganizer, mPhonePipMenuController, pipSnapAlgorithm,
mMockPipTransitionController, mFloatingContentCoordinator);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
index ecefd89..474d6aa 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
@@ -34,6 +34,7 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
+import com.android.wm.shell.pip.PipKeepClearAlgorithm;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
@@ -104,7 +105,8 @@
MockitoAnnotations.initMocks(this);
mPipBoundsState = new PipBoundsState(mContext);
mPipSnapAlgorithm = new PipSnapAlgorithm();
- mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState, mPipSnapAlgorithm);
+ mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState, mPipSnapAlgorithm,
+ new PipKeepClearAlgorithm() {});
PipMotionHelper pipMotionHelper = new PipMotionHelper(mContext, mPipBoundsState,
mPipTaskOrganizer, mPhonePipMenuController, mPipSnapAlgorithm,
mMockPipTransitionController, mFloatingContentCoordinator);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index e11be31..ab6ac94 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.same;
@@ -59,6 +60,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import java.util.ArrayList;
@@ -96,6 +98,8 @@
@Mock
private WindowContainerTransaction mMockWindowContainerTransaction;
+ private final List<SurfaceControl.Transaction> mMockSurfaceControlTransactions =
+ new ArrayList<>();
private final List<SurfaceControl.Builder> mMockSurfaceControlBuilders = new ArrayList<>();
private SurfaceControl.Transaction mMockSurfaceControlStartT;
private SurfaceControl.Transaction mMockSurfaceControlFinishT;
@@ -123,6 +127,10 @@
final SurfaceControl.Builder taskBackgroundSurfaceBuilder =
createMockSurfaceControlBuilder(taskBackgroundSurface);
mMockSurfaceControlBuilders.add(taskBackgroundSurfaceBuilder);
+ final SurfaceControl captionContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder captionContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(captionContainerSurface);
+ mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder);
final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
new ActivityManager.TaskDescription.Builder()
@@ -147,6 +155,7 @@
verify(decorContainerSurfaceBuilder, never()).build();
verify(taskBackgroundSurfaceBuilder, never()).build();
+ verify(captionContainerSurfaceBuilder, never()).build();
verify(mMockSurfaceControlViewHostFactory, never()).create(any(), any(), any());
verify(mMockSurfaceControlFinishT).hide(taskSurface);
@@ -168,6 +177,10 @@
final SurfaceControl.Builder taskBackgroundSurfaceBuilder =
createMockSurfaceControlBuilder(taskBackgroundSurface);
mMockSurfaceControlBuilders.add(taskBackgroundSurfaceBuilder);
+ final SurfaceControl captionContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder captionContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(captionContainerSurface);
+ mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder);
final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
new ActivityManager.TaskDescription.Builder()
@@ -205,6 +218,12 @@
verify(mMockSurfaceControlStartT).setLayer(taskBackgroundSurface, -1);
verify(mMockSurfaceControlStartT).show(taskBackgroundSurface);
+ verify(captionContainerSurfaceBuilder).setParent(decorContainerSurface);
+ verify(captionContainerSurfaceBuilder).setContainerLayer();
+ verify(mMockSurfaceControlStartT).setPosition(captionContainerSurface, 20, 40);
+ verify(mMockSurfaceControlStartT).setWindowCrop(captionContainerSurface, 300, 64);
+ verify(mMockSurfaceControlStartT).show(captionContainerSurface);
+
verify(mMockSurfaceControlViewHostFactory).create(any(), eq(defaultDisplay), any());
verify(mMockSurfaceControlViewHost)
.setView(same(mMockView),
@@ -245,6 +264,13 @@
final SurfaceControl.Builder taskBackgroundSurfaceBuilder =
createMockSurfaceControlBuilder(taskBackgroundSurface);
mMockSurfaceControlBuilders.add(taskBackgroundSurfaceBuilder);
+ final SurfaceControl captionContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder captionContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(captionContainerSurface);
+ mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder);
+
+ final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+ mMockSurfaceControlTransactions.add(t);
final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
new ActivityManager.TaskDescription.Builder()
@@ -268,17 +294,19 @@
windowDecor.relayout(taskInfo);
verify(mMockSurfaceControlViewHost, never()).release();
- verify(decorContainerSurface, never()).release();
- verify(taskBackgroundSurface, never()).release();
+ verify(t, never()).apply();
verify(mMockWindowContainerTransaction, never())
.removeInsetsProvider(eq(taskInfo.token), any());
taskInfo.isVisible = false;
windowDecor.relayout(taskInfo);
- verify(mMockSurfaceControlViewHost).release();
- verify(decorContainerSurface).release();
- verify(taskBackgroundSurface).release();
+ final InOrder releaseOrder = inOrder(t, mMockSurfaceControlViewHost);
+ releaseOrder.verify(mMockSurfaceControlViewHost).release();
+ releaseOrder.verify(t).remove(captionContainerSurface);
+ releaseOrder.verify(t).remove(decorContainerSurface);
+ releaseOrder.verify(t).remove(taskBackgroundSurface);
+ releaseOrder.verify(t).apply();
verify(mMockWindowContainerTransaction).removeInsetsProvider(eq(taskInfo.token), any());
}
@@ -330,21 +358,30 @@
private TestWindowDecoration createWindowDecoration(
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer,
- taskInfo, testSurface, new MockSurfaceControlBuilderSupplier(),
+ taskInfo, testSurface,
+ new MockObjectSupplier<>(mMockSurfaceControlBuilders,
+ () -> createMockSurfaceControlBuilder(mock(SurfaceControl.class))),
+ new MockObjectSupplier<>(mMockSurfaceControlTransactions,
+ () -> mock(SurfaceControl.Transaction.class)),
() -> mMockWindowContainerTransaction, mMockSurfaceControlViewHostFactory);
}
- private class MockSurfaceControlBuilderSupplier implements Supplier<SurfaceControl.Builder> {
+ private class MockObjectSupplier<T> implements Supplier<T> {
+ private final List<T> mObjects;
+ private final Supplier<T> mDefaultSupplier;
private int mNumOfCalls = 0;
+ private MockObjectSupplier(List<T> objects, Supplier<T> defaultSupplier) {
+ mObjects = objects;
+ mDefaultSupplier = defaultSupplier;
+ }
+
@Override
- public SurfaceControl.Builder get() {
- final SurfaceControl.Builder builder =
- mNumOfCalls < mMockSurfaceControlBuilders.size()
- ? mMockSurfaceControlBuilders.get(mNumOfCalls)
- : createMockSurfaceControlBuilder(mock(SurfaceControl.class));
+ public T get() {
+ final T mock = mNumOfCalls < mObjects.size()
+ ? mObjects.get(mNumOfCalls) : mDefaultSupplier.get();
++mNumOfCalls;
- return builder;
+ return mock;
}
}
@@ -362,11 +399,12 @@
ShellTaskOrganizer taskOrganizer, ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
+ Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
super(context, displayController, taskOrganizer, taskInfo, taskSurface,
- surfaceControlBuilderSupplier, windowContainerTransactionSupplier,
- surfaceControlViewHostFactory);
+ surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
+ windowContainerTransactionSupplier, surfaceControlViewHostFactory);
}
@Override
diff --git a/libs/dream/lowlight/Android.bp b/libs/dream/lowlight/Android.bp
new file mode 100644
index 0000000..5b5b0f0
--- /dev/null
+++ b/libs/dream/lowlight/Android.bp
@@ -0,0 +1,47 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+ name: "low_light_dream_lib-sources",
+ srcs: [
+ "src/**/*.java",
+ ],
+ path: "src",
+}
+
+android_library {
+ name: "LowLightDreamLib",
+ srcs: [
+ ":low_light_dream_lib-sources",
+ ],
+ resource_dirs: [
+ "res",
+ ],
+ static_libs: [
+ "androidx.arch.core_core-runtime",
+ "dagger2",
+ "jsr330",
+ ],
+ manifest: "AndroidManifest.xml",
+ plugins: ["dagger2-compiler"],
+}
diff --git a/libs/dream/lowlight/AndroidManifest.xml b/libs/dream/lowlight/AndroidManifest.xml
new file mode 100644
index 0000000..a8d9526
--- /dev/null
+++ b/libs/dream/lowlight/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest package="com.android.dream.lowlight" />
diff --git a/libs/dream/lowlight/res/values/config.xml b/libs/dream/lowlight/res/values/config.xml
new file mode 100644
index 0000000..70fe073
--- /dev/null
+++ b/libs/dream/lowlight/res/values/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<resources>
+ <!-- The dream component used when the device is low light environment. -->
+ <string translatable="false" name="config_lowLightDreamComponent"/>
+</resources>
diff --git a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.java b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.java
new file mode 100644
index 0000000..5ecec4d
--- /dev/null
+++ b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dream.lowlight;
+
+import static com.android.dream.lowlight.dagger.LowLightDreamModule.LOW_LIGHT_DREAM_COMPONENT;
+
+import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
+import android.app.DreamManager;
+import android.content.ComponentName;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * Maintains the ambient light mode of the environment the device is in, and sets a low light dream
+ * component, if present, as the system dream when the ambient light mode is low light.
+ *
+ * @hide
+ */
+public final class LowLightDreamManager {
+ private static final String TAG = "LowLightDreamManager";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "AMBIENT_LIGHT_MODE_" }, value = {
+ AMBIENT_LIGHT_MODE_UNKNOWN,
+ AMBIENT_LIGHT_MODE_REGULAR,
+ AMBIENT_LIGHT_MODE_LOW_LIGHT
+ })
+ public @interface AmbientLightMode {}
+
+ /**
+ * Constant for ambient light mode being unknown.
+ * @hide
+ */
+ public static final int AMBIENT_LIGHT_MODE_UNKNOWN = 0;
+
+ /**
+ * Constant for ambient light mode being regular / bright.
+ * @hide
+ */
+ public static final int AMBIENT_LIGHT_MODE_REGULAR = 1;
+
+ /**
+ * Constant for ambient light mode being low light / dim.
+ * @hide
+ */
+ public static final int AMBIENT_LIGHT_MODE_LOW_LIGHT = 2;
+
+ private final DreamManager mDreamManager;
+
+ @Nullable
+ private final ComponentName mLowLightDreamComponent;
+
+ private int mAmbientLightMode = AMBIENT_LIGHT_MODE_UNKNOWN;
+
+ @Inject
+ public LowLightDreamManager(
+ DreamManager dreamManager,
+ @Named(LOW_LIGHT_DREAM_COMPONENT) @Nullable ComponentName lowLightDreamComponent) {
+ mDreamManager = dreamManager;
+ mLowLightDreamComponent = lowLightDreamComponent;
+ }
+
+ /**
+ * Sets the current ambient light mode.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)
+ public void setAmbientLightMode(@AmbientLightMode int ambientLightMode) {
+ if (mLowLightDreamComponent == null) {
+ if (DEBUG) {
+ Log.d(TAG, "ignore ambient light mode change because low light dream component "
+ + "is empty");
+ }
+ return;
+ }
+
+ if (mAmbientLightMode == ambientLightMode) {
+ return;
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "ambient light mode changed from " + mAmbientLightMode + " to "
+ + ambientLightMode);
+ }
+
+ mAmbientLightMode = ambientLightMode;
+
+ mDreamManager.setSystemDreamComponent(mAmbientLightMode == AMBIENT_LIGHT_MODE_LOW_LIGHT
+ ? mLowLightDreamComponent : null);
+ }
+}
diff --git a/libs/dream/lowlight/src/com/android/dream/lowlight/dagger/LowLightDreamModule.java b/libs/dream/lowlight/src/com/android/dream/lowlight/dagger/LowLightDreamModule.java
new file mode 100644
index 0000000..c183a04
--- /dev/null
+++ b/libs/dream/lowlight/src/com/android/dream/lowlight/dagger/LowLightDreamModule.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dream.lowlight.dagger;
+
+import android.app.DreamManager;
+import android.content.ComponentName;
+import android.content.Context;
+
+import androidx.annotation.Nullable;
+
+import com.android.dream.lowlight.R;
+
+import javax.inject.Named;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger module for low light dream.
+ *
+ * @hide
+ */
+@Module
+public interface LowLightDreamModule {
+ String LOW_LIGHT_DREAM_COMPONENT = "low_light_dream_component";
+
+ /**
+ * Provides dream manager.
+ */
+ @Provides
+ static DreamManager providesDreamManager(Context context) {
+ return context.getSystemService(DreamManager.class);
+ }
+
+ /**
+ * Provides the component name of the low light dream, or null if not configured.
+ */
+ @Provides
+ @Named(LOW_LIGHT_DREAM_COMPONENT)
+ @Nullable
+ static ComponentName providesLowLightDreamComponent(Context context) {
+ final String lowLightDreamComponent = context.getResources().getString(
+ R.string.config_lowLightDreamComponent);
+ return lowLightDreamComponent.isEmpty() ? null
+ : ComponentName.unflattenFromString(lowLightDreamComponent);
+ }
+}
diff --git a/libs/dream/lowlight/tests/Android.bp b/libs/dream/lowlight/tests/Android.bp
new file mode 100644
index 0000000..bd6f05e
--- /dev/null
+++ b/libs/dream/lowlight/tests/Android.bp
@@ -0,0 +1,45 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "LowLightDreamTests",
+ srcs: [
+ "**/*.java",
+ ],
+ static_libs: [
+ "LowLightDreamLib",
+ "androidx.test.runner",
+ "androidx.test.rules",
+ "androidx.test.ext.junit",
+ "frameworks-base-testutils",
+ "junit",
+ "mockito-target-extended-minus-junit4",
+ "platform-test-annotations",
+ "testables",
+ "truth-prebuilt",
+ ],
+ libs: [
+ "android.test.mock",
+ "android.test.base",
+ "android.test.runner",
+ ],
+ jni_libs: [
+ "libdexmakerjvmtiagent",
+ "libstaticjvmtiagent",
+ ],
+}
diff --git a/libs/dream/lowlight/tests/AndroidManifest.xml b/libs/dream/lowlight/tests/AndroidManifest.xml
new file mode 100644
index 0000000..abb71fb
--- /dev/null
+++ b/libs/dream/lowlight/tests/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.android.dream.lowlight.tests">
+
+ <application android:debuggable="true" android:largeHeap="true">
+ <uses-library android:name="android.test.mock" />
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:label="Tests for LowLightDreamLib"
+ android:targetPackage="com.android.dream.lowlight.tests">
+ </instrumentation>
+
+</manifest>
diff --git a/libs/dream/lowlight/tests/AndroidTest.xml b/libs/dream/lowlight/tests/AndroidTest.xml
new file mode 100644
index 0000000..1080033
--- /dev/null
+++ b/libs/dream/lowlight/tests/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs Tests for LowLightDreamLib">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
+ <option name="test-file-name" value="LowLightDreamTests.apk" />
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="framework-base-presubmit" />
+ <option name="test-tag" value="LowLightDreamLibTests" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.dream.lowlight.tests" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.java b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.java
new file mode 100644
index 0000000..91a170f
--- /dev/null
+++ b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dream.lowlight;
+
+import static com.android.dream.lowlight.LowLightDreamManager.AMBIENT_LIGHT_MODE_LOW_LIGHT;
+import static com.android.dream.lowlight.LowLightDreamManager.AMBIENT_LIGHT_MODE_REGULAR;
+import static com.android.dream.lowlight.LowLightDreamManager.AMBIENT_LIGHT_MODE_UNKNOWN;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.app.DreamManager;
+import android.content.ComponentName;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class LowLightDreamManagerTest {
+ @Mock
+ private DreamManager mDreamManager;
+
+ @Mock
+ private ComponentName mDreamComponent;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void setAmbientLightMode_lowLight_setSystemDream() {
+ final LowLightDreamManager lowLightDreamManager = new LowLightDreamManager(mDreamManager,
+ mDreamComponent);
+
+ lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
+
+ verify(mDreamManager).setSystemDreamComponent(mDreamComponent);
+ }
+
+ @Test
+ public void setAmbientLightMode_regularLight_clearSystemDream() {
+ final LowLightDreamManager lowLightDreamManager = new LowLightDreamManager(mDreamManager,
+ mDreamComponent);
+
+ lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_REGULAR);
+
+ verify(mDreamManager).setSystemDreamComponent(null);
+ }
+
+ @Test
+ public void setAmbientLightMode_defaultUnknownMode_clearSystemDream() {
+ final LowLightDreamManager lowLightDreamManager = new LowLightDreamManager(mDreamManager,
+ mDreamComponent);
+
+ // Set to low light first.
+ lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
+ clearInvocations(mDreamManager);
+
+ // Return to default unknown mode.
+ lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_UNKNOWN);
+
+ verify(mDreamManager).setSystemDreamComponent(null);
+ }
+
+ @Test
+ public void setAmbientLightMode_dreamComponentNotSet_doNothing() {
+ final LowLightDreamManager lowLightDreamManager = new LowLightDreamManager(mDreamManager,
+ null /*dream component*/);
+
+ lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
+
+ verify(mDreamManager, never()).setSystemDreamComponent(any());
+ }
+}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index c666140..650f360 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1299,8 +1299,8 @@
/** @hide */ public static final String DEVICE_OUT_REMOTE_SUBMIX_NAME = "remote_submix";
/** @hide */ public static final String DEVICE_OUT_TELEPHONY_TX_NAME = "telephony_tx";
/** @hide */ public static final String DEVICE_OUT_LINE_NAME = "line";
- /** @hide */ public static final String DEVICE_OUT_HDMI_ARC_NAME = "hmdi_arc";
- /** @hide */ public static final String DEVICE_OUT_HDMI_EARC_NAME = "hmdi_earc";
+ /** @hide */ public static final String DEVICE_OUT_HDMI_ARC_NAME = "hdmi_arc";
+ /** @hide */ public static final String DEVICE_OUT_HDMI_EARC_NAME = "hdmi_earc";
/** @hide */ public static final String DEVICE_OUT_SPDIF_NAME = "spdif";
/** @hide */ public static final String DEVICE_OUT_FM_NAME = "fm_transmitter";
/** @hide */ public static final String DEVICE_OUT_AUX_LINE_NAME = "aux_line";
diff --git a/media/jni/soundpool/Sound.cpp b/media/jni/soundpool/Sound.cpp
index ac5f35f..ecc44f4 100644
--- a/media/jni/soundpool/Sound.cpp
+++ b/media/jni/soundpool/Sound.cpp
@@ -181,8 +181,11 @@
format.get(), AMEDIAFORMAT_KEY_CHANNEL_COUNT, channelCount)) {
return UNKNOWN_ERROR;
}
- if (!AMediaFormat_getInt32(format.get(), AMEDIAFORMAT_KEY_CHANNEL_MASK,
- (int32_t*) channelMask)) {
+ int32_t mediaFormatChannelMask;
+ if (AMediaFormat_getInt32(format.get(), AMEDIAFORMAT_KEY_CHANNEL_MASK,
+ &mediaFormatChannelMask)) {
+ *channelMask = audio_channel_mask_from_media_format_mask(mediaFormatChannelMask);
+ } else {
*channelMask = AUDIO_CHANNEL_NONE;
}
*sizeInBytes = written;
diff --git a/packages/BackupRestoreConfirmation/res/values-or/strings.xml b/packages/BackupRestoreConfirmation/res/values-or/strings.xml
index 1c54569..cb61092 100644
--- a/packages/BackupRestoreConfirmation/res/values-or/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-or/strings.xml
@@ -20,7 +20,7 @@
<string name="restore_confirm_title" msgid="5469365809567486602">"ସମ୍ପୂର୍ଣ୍ଣ ରିଷ୍ଟୋର୍"</string>
<string name="backup_confirm_text" msgid="1878021282758896593">"ଏକ ସଂଯୁକ୍ତ ଡେସ୍କଟପ୍ କମ୍ପ୍ୟୁଟର୍କୁ ସମସ୍ତ ଡାଟାର ସମ୍ପୂର୍ଣ୍ଣ ବ୍ୟାକଅପ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଇଛି। ଆପଣ ଏହିପରି କରିବାକୁ ଚାହିଁବେ?\n\nଯଦି ଆପଣ ନିଜେ ବ୍ୟାକଅପ୍ର ଅନୁରୋଧ କରିନାହାନ୍ତି, ତେବେ ଏହି କାମକୁ ଆଗକୁ ବଢ଼ିବାକୁ ଦିଅନ୍ତୁ ନାହିଁ।"</string>
<string name="allow_backup_button_label" msgid="4217228747769644068">"ମୋ ଡାଟାର ବ୍ୟାକଅପ୍ ନିଆଯାଉ"</string>
- <string name="deny_backup_button_label" msgid="6009119115581097708">"ବ୍ୟାକଅପ୍ ନିଆନଯାଉ"</string>
+ <string name="deny_backup_button_label" msgid="6009119115581097708">"ବେକଅପ ନିଅନ୍ତୁ ନାହିଁ"</string>
<string name="restore_confirm_text" msgid="7499866728030461776">"ଏକ ସଂଯୁକ୍ତ ଡେସ୍କଟପ୍ କମ୍ପ୍ୟୁଟର୍ରୁ ସମସ୍ତ ଡାଟାର ସମ୍ପୂର୍ଣ୍ଣ ରିଷ୍ଟୋର୍ ଅନୁରୋଧ କରାଯାଇଛି। ଆପଣ ଏହାକୁ ଅନୁମତି ଦେବାକୁ ଚାହିଁବେ କି?\n\nଯଦି ଆପଣ ନିଜେ ରିଷ୍ଟୋର୍ ଅନୁରୋଧ କରିନାହାନ୍ତି, ତେବେ ଏହା କାର୍ଯ୍ୟକୁ ଆଗକୁ ବଢ଼ିବାକୁ ଦିଅନ୍ତୁ ନାହିଁ। ଏହା ବର୍ତ୍ତମାନ ଡିଭାଇସ୍ରେ ଥିବା ଯେକୌଣସି ଡାଟାକୁ ବଦଳାଇଦେବ!"</string>
<string name="allow_restore_button_label" msgid="3081286752277127827">"ମୋ ଡାଟାକୁ ରିଷ୍ଟୋର୍ କରାଯାଉ"</string>
<string name="deny_restore_button_label" msgid="1724367334453104378">"ରିଷ୍ଟୋର୍ କରନ୍ତୁ ନାହିଁ।"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml b/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml
index a1e6167..1f6be83 100644
--- a/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml
@@ -20,7 +20,7 @@
<string name="restore_confirm_title" msgid="5469365809567486602">"Restauro completo"</string>
<string name="backup_confirm_text" msgid="1878021282758896593">"Foi solicitada uma cópia de segurança completa de todos os dados para um computador. Permitir esta operação?\n\nCaso não tenha solicitado a cópia de segurança, não permita que a operação prossiga."</string>
<string name="allow_backup_button_label" msgid="4217228747769644068">"Fazer cópia de seg. dos dados"</string>
- <string name="deny_backup_button_label" msgid="6009119115581097708">"Não efetuar cópia de seg."</string>
+ <string name="deny_backup_button_label" msgid="6009119115581097708">"Não fazer cópia de seg."</string>
<string name="restore_confirm_text" msgid="7499866728030461776">"Foi solicitado um restauro completo de todos os dados a partir de um computador. Permitir esta operação?\n\nCaso não tenha solicitado o restauro, não permita que a operação prossiga. Isto substituirá os dados existentes no equipamento!"</string>
<string name="allow_restore_button_label" msgid="3081286752277127827">"Restaurar os meus dados"</string>
<string name="deny_restore_button_label" msgid="1724367334453104378">"Não restaurar"</string>
diff --git a/packages/CompanionDeviceManager/res/drawable-night/ic_info.xml b/packages/CompanionDeviceManager/res/drawable-night/ic_info.xml
index 5689e34..a984938 100644
--- a/packages/CompanionDeviceManager/res/drawable-night/ic_info.xml
+++ b/packages/CompanionDeviceManager/res/drawable-night/ic_info.xml
@@ -19,7 +19,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:tint="@android:color/system_accent1_200">
+ android:tint="@android:color/system_neutral1_200">
<path android:fillColor="@android:color/white"
android:pathData="M11,17H13V11H11ZM12,9Q12.425,9 12.713,8.712Q13,8.425 13,8Q13,7.575 12.713,7.287Q12.425,7 12,7Q11.575,7 11.288,7.287Q11,7.575 11,8Q11,8.425 11.288,8.712Q11.575,9 12,9ZM12,22Q9.925,22 8.1,21.212Q6.275,20.425 4.925,19.075Q3.575,17.725 2.788,15.9Q2,14.075 2,12Q2,9.925 2.788,8.1Q3.575,6.275 4.925,4.925Q6.275,3.575 8.1,2.787Q9.925,2 12,2Q14.075,2 15.9,2.787Q17.725,3.575 19.075,4.925Q20.425,6.275 21.212,8.1Q22,9.925 22,12Q22,14.075 21.212,15.9Q20.425,17.725 19.075,19.075Q17.725,20.425 15.9,21.212Q14.075,22 12,22ZM12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12ZM12,20Q15.325,20 17.663,17.663Q20,15.325 20,12Q20,8.675 17.663,6.337Q15.325,4 12,4Q8.675,4 6.338,6.337Q4,8.675 4,12Q4,15.325 6.338,17.663Q8.675,20 12,20Z"/>
</vector>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/drawable/ic_info.xml b/packages/CompanionDeviceManager/res/drawable/ic_info.xml
index d9f6a27..229960c 100644
--- a/packages/CompanionDeviceManager/res/drawable/ic_info.xml
+++ b/packages/CompanionDeviceManager/res/drawable/ic_info.xml
@@ -20,7 +20,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:tint="@android:color/system_accent1_600">
+ android:tint="@android:color/system_neutral1_700">
<path android:fillColor="@android:color/white"
android:pathData="M11,17H13V11H11ZM12,9Q12.425,9 12.713,8.712Q13,8.425 13,8Q13,7.575 12.713,7.287Q12.425,7 12,7Q11.575,7 11.288,7.287Q11,7.575 11,8Q11,8.425 11.288,8.712Q11.575,9 12,9ZM12,22Q9.925,22 8.1,21.212Q6.275,20.425 4.925,19.075Q3.575,17.725 2.788,15.9Q2,14.075 2,12Q2,9.925 2.788,8.1Q3.575,6.275 4.925,4.925Q6.275,3.575 8.1,2.787Q9.925,2 12,2Q14.075,2 15.9,2.787Q17.725,3.575 19.075,4.925Q20.425,6.275 21.212,8.1Q22,9.925 22,12Q22,14.075 21.212,15.9Q20.425,17.725 19.075,19.075Q17.725,20.425 15.9,21.212Q14.075,22 12,22ZM12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12ZM12,20Q15.325,20 17.663,17.663Q20,15.325 20,12Q20,8.675 17.663,6.337Q15.325,4 12,4Q8.675,4 6.338,6.337Q4,8.675 4,12Q4,15.325 6.338,17.663Q8.675,20 12,20Z"/>
</vector>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/layout/helper_confirmation.xml b/packages/CompanionDeviceManager/res/layout/helper_confirmation.xml
index d0d46f7..1f922b9 100644
--- a/packages/CompanionDeviceManager/res/layout/helper_confirmation.xml
+++ b/packages/CompanionDeviceManager/res/layout/helper_confirmation.xml
@@ -35,7 +35,7 @@
<ImageView
android:id="@+id/app_icon"
android:layout_width="match_parent"
- android:layout_height="48dp"
+ android:layout_height="32dp"
android:gravity="center"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"/>
diff --git a/packages/CompanionDeviceManager/res/layout/vendor_header.xml b/packages/CompanionDeviceManager/res/layout/vendor_header.xml
index 14e7431..16a87e5 100644
--- a/packages/CompanionDeviceManager/res/layout/vendor_header.xml
+++ b/packages/CompanionDeviceManager/res/layout/vendor_header.xml
@@ -22,7 +22,7 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center"
- android:paddingTop="24dp"
+ android:paddingTop="12dp"
android:paddingBottom="4dp"
android:paddingStart="24dp"
android:paddingEnd="24dp"
@@ -32,24 +32,26 @@
android:id="@+id/vendor_header_image"
android:layout_width="48dp"
android:layout_height="48dp"
+ android:padding="12dp"
android:contentDescription="@string/vendor_icon_description" />
<TextView
android:id="@+id/vendor_header_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
- android:textSize="16sp"
+ android:textSize="14sp"
android:layout_toEndOf="@+id/vendor_header_image"
android:textColor="?android:attr/textColorSecondary"/>
<ImageButton
android:id="@+id/vendor_header_button"
- android:background="@drawable/ic_info"
+ android:src="@drawable/ic_info"
android:layout_width="48dp"
android:layout_height="48dp"
+ android:padding="12dp"
android:contentDescription="@string/vendor_header_button_description"
- android:layout_alignParentEnd="true" />
+ android:layout_alignParentEnd="true"
+ android:background="@android:color/transparent" />
</RelativeLayout>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index ef21b6d..c5ef913 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -34,7 +34,7 @@
<string name="permission_notification_summary" msgid="884075314530071011">"इससे सभी सूचनाएं देखी जा सकती हैं. इसमें संपर्क, मैसेज, और फ़ोटो जैसी जानकारी शामिल होती है"</string>
<string name="permission_storage" msgid="6831099350839392343">"फ़ोटो और मीडिया"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
- <string name="helper_title_computer" msgid="4671071173916176037">"Google Play सेवाएं"</string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
<string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> की ओर से, फ़ोन में मौजूद फ़ोटो, मीडिया, और सूचनाओं को ऐक्सेस करने की अनुमति मांग रहा है"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"डिवाइस"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
diff --git a/packages/CompanionDeviceManager/res/values-night/themes.xml b/packages/CompanionDeviceManager/res/values-night/themes.xml
index 6eb16e7..55e91b6 100644
--- a/packages/CompanionDeviceManager/res/values-night/themes.xml
+++ b/packages/CompanionDeviceManager/res/values-night/themes.xml
@@ -18,8 +18,8 @@
<style name="ChooserActivity"
parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar">
- <item name="*android:windowFixedHeightMajor">100%</item>
- <item name="*android:windowFixedHeightMinor">100%</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
diff --git a/packages/InputDevices/res/values-am/strings.xml b/packages/InputDevices/res/values-am/strings.xml
index ff9f652..1698150 100644
--- a/packages/InputDevices/res/values-am/strings.xml
+++ b/packages/InputDevices/res/values-am/strings.xml
@@ -5,7 +5,7 @@
<string name="keyboard_layouts_label" msgid="6688773268302087545">"የAndroid የቁልፍ ሰሌዳ"</string>
<string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"እንግሊዝኛ (ዩኬ)"</string>
<string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"እንግሊዘኛ (ዩ.ኤስ.)"</string>
- <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"እንግሊዘኛ (ዩ. ኤስ.)፣ አለም አቀፍ ቅጥ"</string>
+ <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"እንግሊዘኛ (ዩ. ኤስ.)፣ ዓለም አቀፍ ቅጥ"</string>
<string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"እንግሊዘኛ (ዩ. ኤስ.)፣ የኮልማርክ ቅጥ"</string>
<string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"እንግሊዘኛ (ዩ. ኤስ.)፣ የድቮራክ ቅጥ"</string>
<string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"እንግሊዝኛ (አሜሪካ)፣ የሥራሰው ቅጥ"</string>
diff --git a/packages/PackageInstaller/res/values-it/strings.xml b/packages/PackageInstaller/res/values-it/strings.xml
index 74f7d908..3fe7ba4 100644
--- a/packages/PackageInstaller/res/values-it/strings.xml
+++ b/packages/PackageInstaller/res/values-it/strings.xml
@@ -37,7 +37,7 @@
<string name="install_failed_msg" product="tv" msgid="1920009940048975221">"Impossibile installare <xliff:g id="APP_NAME">%1$s</xliff:g> sulla TV."</string>
<string name="install_failed_msg" product="default" msgid="6484461562647915707">"Impossibile installare <xliff:g id="APP_NAME">%1$s</xliff:g> sul telefono."</string>
<string name="launch" msgid="3952550563999890101">"Apri"</string>
- <string name="unknown_apps_admin_dlg_text" msgid="4456572224020176095">"L\'amministratore non consente l\'installazione di app ottenute da fonti sconosciute"</string>
+ <string name="unknown_apps_admin_dlg_text" msgid="4456572224020176095">"L\'amministratore non consente l\'installazione di app ottenute da origini sconosciute"</string>
<string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Questo utente non può installare app sconosciute"</string>
<string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"L\'utente non è autorizzato a installare app"</string>
<string name="ok" msgid="7871959885003339302">"OK"</string>
diff --git a/packages/PrintSpooler/res/values-kk/strings.xml b/packages/PrintSpooler/res/values-kk/strings.xml
index 29126bc..939e1b4 100644
--- a/packages/PrintSpooler/res/values-kk/strings.xml
+++ b/packages/PrintSpooler/res/values-kk/strings.xml
@@ -106,6 +106,6 @@
<string name="print_error_default_message" msgid="8602678405502922346">"Кешіріңіз, бұл нәтиже бермеді. Әрекетті қайталаңыз."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Қайталау"</string>
<string name="print_error_printer_unavailable" msgid="8985614415253203381">"Бұл принтер дәл қазір қол жетімді емес."</string>
- <string name="print_cannot_load_page" msgid="6179560924492912009">"Бетті алдын ала қарау мүмкін емес"</string>
- <string name="print_preparing_preview" msgid="3939930735671364712">"Алдын ала қарау дайындалуда…"</string>
+ <string name="print_cannot_load_page" msgid="6179560924492912009">"Бетті алдын ала көру мүмкін емес"</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Алдын ала көру дайындалуда…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-te/strings.xml b/packages/PrintSpooler/res/values-te/strings.xml
index 500a472..e00e28c 100644
--- a/packages/PrintSpooler/res/values-te/strings.xml
+++ b/packages/PrintSpooler/res/values-te/strings.xml
@@ -64,9 +64,9 @@
<string name="notification_channel_progress" msgid="872788690775721436">"జరుగుతున్న ముద్రణలు"</string>
<string name="notification_channel_failure" msgid="9042250774797916414">"విఫలమైన ముద్రణలు"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ఫైల్ను సృష్టించలేకపోయాము"</string>
- <string name="print_services_disabled_toast" msgid="9089060734685174685">"కొన్ని ముద్రణ సేవలు నిలిపివేయబడ్డాయి"</string>
+ <string name="print_services_disabled_toast" msgid="9089060734685174685">"కొన్ని ప్రింట్ సర్వీసులు నిలిపివేయబడ్డాయి"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ప్రింటర్ల కోసం వెతుకుతోంది"</string>
- <string name="print_no_print_services" msgid="8561247706423327966">"ముద్రణ సేవలు ఏవీ ప్రారంభించలేదు"</string>
+ <string name="print_no_print_services" msgid="8561247706423327966">"ప్రింట్ సర్వీసులు ఏవీ ప్రారంభించలేదు"</string>
<string name="print_no_printers" msgid="4869403323900054866">"ప్రింటర్లు కనుగొనబడలేదు"</string>
<string name="cannot_add_printer" msgid="7840348733668023106">"ప్రింటర్లను జోడించడం సాధ్యపడలేదు"</string>
<string name="select_to_add_printers" msgid="3800709038689830974">"ప్రింటర్ను జోడించడానికి ఎంచుకోండి"</string>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml
index 35d1323..2aa26e3 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml
@@ -20,6 +20,11 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="?android:attr/colorBackground"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingTop="@dimen/settingslib_switchbar_margin"
+ android:paddingBottom="@dimen/settingslib_switchbar_margin"
android:orientation="vertical">
<LinearLayout
@@ -27,7 +32,6 @@
android:minHeight="@dimen/settingslib_min_switch_bar_height"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:layout_margin="@dimen/settingslib_switchbar_margin"
android:paddingStart="@dimen/settingslib_switchbar_padding_left"
android:paddingEnd="@dimen/settingslib_switchbar_padding_right">
diff --git a/packages/SettingsLib/SearchWidget/res/values-ro/strings.xml b/packages/SettingsLib/SearchWidget/res/values-ro/strings.xml
index b2f503f..22790c0 100644
--- a/packages/SettingsLib/SearchWidget/res/values-ro/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-ro/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="search_menu" msgid="1914043873178389845">"Căutați în setări"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Caută în setări"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 481d26d..2b5f4ac 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> oor tot vol"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> oor tot vol"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laaiproses is onderbreek"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Laai"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laai tans vinnig"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Laai tans stadig"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Laai tans draadloos"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Laai tans"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Laai nie"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Gekoppel, laai nie"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Gelaai"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet is ontkoppel."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Geen oproepe nie."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Tyd"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Datum"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Weer"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luggehalte"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Uitsaai-inligting"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Huiskontroles"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Kies \'n profielprent"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Verstekgebruikerikoon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fisieke sleutelbord"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 9a51181..734eb33 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"እስኪሞላ ድረስ <xliff:g id="TIME">%1$s</xliff:g> ይቀራል"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - እስኪሞላ ድረስ <xliff:g id="TIME">%2$s</xliff:g> ይቀራል"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ኃይል መሙላት ባለበት ቆሟል"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"ያልታወቀ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ኃይል በመሙላት ላይ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ኃይል በፍጥነት በመሙላት ላይ"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ኃይል በዝግታ በመሙላት ላይ"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"በገመድ-አልባ ኃይል በመሙላት ላይ"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ኃይል በመሙላት ላይ"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ባትሪ እየሞላ አይደለም"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"ተገናኝቷል፣ ኃይል በመሙላት ላይ አይደለም"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ባትሪ ሞልቷል"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ኤተርኔት ተነቅሏል።"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ኢተርኔት።"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"መደወል የለም።"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"ጊዜ"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"ቀን"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"የአየር ሁኔታ"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"የአየር ጥራት"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"የCast መረጃ"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"የቤት ውስጥ ቁጥጥሮች"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"የመገለጫ ሥዕል ይምረጡ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ነባሪ የተጠቃሚ አዶ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"አካላዊ ቁልፍ ሰሌዳ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 086956b..0a64da3 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -184,7 +184,7 @@
<string name="launch_defaults_some" msgid="3631650616557252926">"تم ضبط بعض الإعدادات التلقائية"</string>
<string name="launch_defaults_none" msgid="8049374306261262709">"لم يتم ضبط إعدادات تلقائية"</string>
<string name="tts_settings" msgid="8130616705989351312">"إعدادات تحويل النص إلى كلام"</string>
- <string name="tts_settings_title" msgid="7602210956640483039">"تحويل النص إلى كلام"</string>
+ <string name="tts_settings_title" msgid="7602210956640483039">"إخراج النص إلى كلام"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"معدل سرعة الكلام"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"سرعة قول الكلام"</string>
<string name="tts_default_pitch_title" msgid="6988592215554485479">"درجة الصوت"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"يتبقّى <xliff:g id="TIME">%1$s</xliff:g> حتى اكتمال شحن البطارية."</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - يتبقّى <xliff:g id="TIME">%2$s</xliff:g> حتى اكتمال شحن البطارية."</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - تم إيقاف الشحن مؤقتًا"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"غير معروف"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"جارٍ الشحن"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"جارٍ الشحن سريعًا"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"جارٍ الشحن ببطء"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"جارٍ الشحن لاسلكيًا"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"جارٍ الشحن"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"لا يتم الشحن"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"الجهاز متصل بالشاحن، ولا يتم الشحن."</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"مشحونة"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"تم قطع اتصال Ethernet."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"إيثرنت"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"لا يتم الاتصال."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"الوقت"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"التاريخ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"الطقس"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"جودة الهواء"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"معلومات البث"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"إدارة آلية للمنزل"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"اختيار صورة الملف الشخصي"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"رمز المستخدم التلقائي"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"لوحة مفاتيح خارجية"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 9e0f910..d11ed3c 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"সম্পূৰ্ণ হ’বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"সম্পূৰ্ণ হ’বলৈ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - চাৰ্জিং পজ কৰা হৈছে"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"অজ্ঞাত"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"চাৰ্জ কৰি থকা হৈছে"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্ৰুততাৰে চাৰ্জ হৈছে"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"লাহে লাহে চাৰ্জ হৈছে"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"বেতাঁৰৰ মাধ্যমেৰে চাৰ্জ হৈ আছে"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"চাৰ্জ কৰি থকা হৈছে"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"চ্চাৰ্জ কৰা নাই"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"সংযোগ হৈ আছে, চাৰ্জ হৈ থকা নাই"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"চাৰ্জ হ’ল"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ইথাৰনেট সংযোগ বিচ্ছিন্ন হৈছে।"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ইথাৰনেট।"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"কল কৰা নহয়"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"সময়"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"তাৰিখ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"বতৰ"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"বায়ুৰ গুণগত মান"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"কাষ্টৰ তথ্য"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"গৃহ নিয়ন্ত্ৰণ"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"স্মাৰ্টস্পেচ"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"এখন প্ৰ’ফাইল চিত্ৰ বাছনি কৰক"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ডিফ’ল্ট ব্যৱহাৰকাৰীৰ চিহ্ন"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"কায়িক কীব’ৰ্ড"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index f6da021..9491b07 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Tam şarj edilənədək <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - tam şarj edilənədək <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj durdurulub"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Naməlum"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Enerji doldurma"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Sürətlə doldurulur"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Asta doldurulur"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Simsiz şarj edilir"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Şarj edilir"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Doldurulmur"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Qoşulub, şarj edilmir"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Şarj edilib"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet bağlantısı kəsilib."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Zəng yoxdur."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Vaxt"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Tarix"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Hava"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Havanın keyfiyyəti"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Yayım məlumatı"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Əsas səhifə kontrolları"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Profil şəkli seçin"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Defolt istifadəçi ikonası"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fiziki klaviatura"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index a21a89a..274ce75 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do kraja punjenja"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do kraja punjenja"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Punjenje je zaustavljeno"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Puni se"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo se puni"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Sporo se puni"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bežično punjenje"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Punjenje"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Ne puni se"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Povezano, ne puni se"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Napunjeno"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Veza sa eternetom je prekinuta."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Eternet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Bez pozivanja."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Vreme"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Datum"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Vreme"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvalitet vazduha"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Podaci o prebacivanju"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Upravljanje domom"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"SmartSpace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Odaberite sliku profila"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Podrazumevana ikona korisnika"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fizička tastatura"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 316cefa9..8c336c0 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Да поўнай зарадкі засталося <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – да поўнай зарадкі засталося: <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Зарадка прыпынена"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Невядома"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Зарадка"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хуткая зарадка"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Павольная зарадка"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Бесправадная зарадка"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Ідзе зарадка"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Не зараджаецца"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Падключана, не зараджаецца"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Зараджаны"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet адлучаны."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Ніякіх выклікаў."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Час"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Дата"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Надвор\'е"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Якасць паветра"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Даныя пра трансляцыю"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Кіраванне домам"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Выберыце відарыс профілю"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Стандартны карыстальніцкі значок"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Фізічная клавіятура"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index f7452df..702b5ee 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Оставащо време до пълно зареждане: <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: Зареждането е на пауза"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Зарежда се"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Зарежда се бързо"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Зарежда се бавно"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Зарежда се безжично"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Зареждане"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Не се зарежда"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Свързано, не се зарежда"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Заредена"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Връзката с Ethernet е прекратена."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Без обаждания."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Час"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Дата"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Времето"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Качество на въздуха"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Предаване: Инф."</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Контроли за дома"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Изберете снимка на потребителския профил"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Икона за основния потребител"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Физическа клавиатура"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 0c0c737..bbc5249 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -274,7 +274,7 @@
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM আনলক করার অনুমতি দিতে চান?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"সতর্কতা: এই ডিভাইসে সেটিংটি চালু থাকা অবস্থায় ডিভাইস সুরক্ষা বৈশিষ্ট্যগুলি কাজ করবে না৷"</string>
<string name="mock_location_app" msgid="6269380172542248304">"অনুরূপ লোকেশন অ্যাপ বেছে নিন"</string>
- <string name="mock_location_app_not_set" msgid="6972032787262831155">"কোনো অনুরূপ লোকেশন অ্যাপ্লিকেশান সেট করা নেই"</string>
+ <string name="mock_location_app_not_set" msgid="6972032787262831155">"কোনও অনুরূপ লোকেশন অ্যাপ সেট করা নেই"</string>
<string name="mock_location_app_set" msgid="4706722469342913843">"অনুরূপ লোকেশন অ্যাপ্লিকেশান: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"নেটওয়ার্কিং"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"ওয়্যারলেস ডিসপ্লে সার্টিফিকেশন"</string>
@@ -284,7 +284,7 @@
<string name="mobile_data_always_on" msgid="8275958101875563572">"মোবাইল ডেটা সব সময় সক্রিয় থাক"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"টিথারিং হার্ডওয়্যার অ্যাক্সিলারেশন"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"নামহীন ব্লুটুথ ডিভাইসগুলি দেখুন"</string>
- <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"চূড়ান্ত ভলিউম অক্ষম করুন"</string>
+ <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"চূড়ান্ত ভলিউম বন্ধ করুন"</string>
<string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche ফিচার চালু করুন"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ব্লুটুথ AVRCP ভার্সন"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ব্লুটুথ AVRCP ভার্সন বেছে নিন"</string>
@@ -338,7 +338,7 @@
<string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB এর অ্যাপ্লিকেশনগুলি যাচাই করুন"</string>
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ক্ষতিকারক ক্রিয়াকলাপ করছে কিনা তার জন্য ADB/ADT মারফত ইনস্টল করা অ্যাপ্লিকেশানগুলি চেক করুন।"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"নামহীন ব্লুটুথ ডিভাইসগুলি দেখানো হবে (শুধুমাত্র MAC অ্যাড্রেস)"</string>
- <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"অপ্রত্যাশিত উচ্চ ভলিউম বা নিয়ন্ত্রণের অভাবের মত দূরবর্তী ডিভাইসের ভলিউম সমস্যাগুলির ক্ষেত্রে, ব্লুটুথ চুড়ান্ত ভলিউম বৈশিষ্ট্য অক্ষম করে৷"</string>
+ <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"অপ্রত্যাশিত উচ্চ ভলিউম বা নিয়ন্ত্রণের অভাবের মত দূরবর্তী ডিভাইসের ভলিউম সমস্যাগুলির ক্ষেত্রে, ব্লুটুথ চুড়ান্ত ভলিউম বৈশিষ্ট্য বন্ধ করে৷"</string>
<string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ব্লুটুথ Gabeldorche ফিচার স্ট্যাক চালু করে।"</string>
<string name="enhanced_connectivity_summary" msgid="1576414159820676330">"কানেক্টিভিটি ফিচার উন্নত করার বিষয়টি চালু করা হয়েছে।"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"স্থানীয় টার্মিনাল"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>-এ ব্যাটারি পুরো চার্জ হয়ে যাবে"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ ব্যাটারি পুরো চার্জ হয়ে যাবে"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - চার্জিং পজ করা হয়েছে"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"অজানা"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"চার্জ হচ্ছে"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্রুত চার্জ হচ্ছে"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ধীরে চার্জ হচ্ছে"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"কেবল ছাড়া চার্জ হচ্ছে"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"চার্জ হচ্ছে"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"চার্জ হচ্ছে না"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"কানেক্ট করা থাকলেও চার্জ করা হচ্ছে না"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"চার্জ হয়েছে"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ইথারনেটের সংযোগ বিচ্ছিন্ন হয়েছে৷"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ইথারনেট।"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"কল করবেন না।"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"সময়"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"তারিখ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"আবহাওয়া"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"এয়ার কোয়ালিটি"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"কাস্ট সম্পর্কিত তথ্য"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"হোম কন্ট্রোল"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"একটি প্রোফাইল ছবি বেছে নিন"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ডিফল্ট ব্যবহারকারীর আইকন"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ফিজিক্যাল কীবোর্ড"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 28c80e9..c60342e 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -233,10 +233,10 @@
<string name="tethering_settings_not_available" msgid="266821736434699780">"Postavke dijeljenja internetske veze nisu dostupne za ovog korisnika"</string>
<string name="apn_settings_not_available" msgid="1147111671403342300">"Postavke za ime pristupne tačke nisu dostupne za ovog korisnika"</string>
<string name="enable_adb" msgid="8072776357237289039">"Otklanjanje grešaka putem USB-a"</string>
- <string name="enable_adb_summary" msgid="3711526030096574316">"Način rada za uklanjanje grešaka kada je povezan USB"</string>
+ <string name="enable_adb_summary" msgid="3711526030096574316">"Način rada za otklanjanje grešaka kada je povezan USB"</string>
<string name="clear_adb_keys" msgid="3010148733140369917">"Ukinite odobrenja otklanjanja grešaka putem USB-a"</string>
<string name="enable_adb_wireless" msgid="6973226350963971018">"Bežično otklanjanje grešaka"</string>
- <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Način rada otklanjanja grešaka kada je WiFi mreža povezana"</string>
+ <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Način rada za otklanjanje grešaka kada je povezan WiFi"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"Greška"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"Bežično otklanjanje grešaka"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Da vidite i koristite dostupne uređaje, uključite bežično otklanjanje grešaka"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Punjenje je pauzirano"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Sporo punjenje"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bežično punjenje"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Punjenje"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Ne puni se"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Povezano, ne puni se"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Napunjeno"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Veza sa Ethernetom je prekinuta."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Nema pozivanja."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Vrijeme"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Datum"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Vremenska prognoza"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvalitet zraka"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Podaci o emitiranju"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Kontrole doma"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Odaberite sliku profila"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Zadana ikona korisnika"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fizička tastatura"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index e17adb1..a6ae453 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -408,8 +408,7 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permet ajustar la mida de totes les activitats per al mode multifinestra, independentment dels valors definits"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Activa les finestres de forma lliure"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Activa la compatibilitat amb finestres de forma lliure experimentals"</string>
- <!-- no translation found for desktop_mode (2389067840550544462) -->
- <skip />
+ <string name="desktop_mode" msgid="2389067840550544462">"Mode d\'escriptori"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Contrasenya per a còpies d\'ordinador"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Les còpies de seguretat completes d\'ordinador no estan protegides"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toca per canviar o suprimir la contrasenya per a les còpies de seguretat completes de l\'ordinador"</string>
@@ -478,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: la càrrega s\'ha posat en pausa"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconegut"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"S\'està carregant"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregant ràpidament"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carregant lentament"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Carregant sense fil"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"S\'està carregant"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"No s\'està carregant"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connectat; no s\'està carregant"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Carregada"</string>
@@ -659,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"S\'ha desconnectat l\'Ethernet."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Sense trucades."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Hora"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Data"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Temps"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualitat de l\'aire"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Informació d\'emissió"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Domòtica"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"D\'una ullada"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Tria una foto de perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icona d\'usuari predeterminat"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclat físic"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index eb3a05c..86739d9 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do úplného nabití"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Nabíjení je pozastaveno"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Neznámé"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíjí se"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rychlé nabíjení"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Pomalé nabíjení"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bezdrátové nabíjení"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Nabíjení"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nenabíjí se"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Připojeno, nenabíjí se"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Nabito"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Síť ethernet je odpojena."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Bez volání."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Čas"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Datum"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Počasí"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvalita vzduchu"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info o odesílání"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Ovládání domácnosti"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Vyberte profilový obrázek"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Výchozí uživatelská ikona"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fyzická klávesnice"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 84fca3d..ef56e22 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Fuldt opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – fuldt opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Opladningen er sat på pause"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Ukendt"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Oplader"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Oplader hurtigt"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Oplader langsomt"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Trådløs opladning"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Oplader"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Oplader ikke"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Tilsluttet, oplader ikke"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Opladet"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet er ikke tilsluttet."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Opkald er deaktiveret."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Klokkeslæt"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Dato"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Vejr"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luftkvalitet"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast-oplysninger"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Styring af hjem"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Overblik"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Vælg et profilbillede"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikon for standardbruger"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fysisk tastatur"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index b75e4df..f4cbfcd 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -408,8 +408,7 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Die Größe aller Aktivitäten darf, ungeachtet der Manifestwerte, für die Mehrfensterdarstellung angepasst werden"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Freiform-Fenster zulassen"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Unterstützung für experimentelle Freiform-Fenster aktivieren"</string>
- <!-- no translation found for desktop_mode (2389067840550544462) -->
- <skip />
+ <string name="desktop_mode" msgid="2389067840550544462">"Desktopmodus"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Passwort für Desktop-Sicherung"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Vollständige Desktop-Sicherungen sind momentan nicht passwortgeschützt"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Zum Ändern oder Entfernen des Passworts für vollständige Desktop-Sicherungen tippen"</string>
@@ -478,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Voll in <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladevorgang angehalten"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unbekannt"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Wird aufgeladen"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Schnelles Aufladen"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Langsames Aufladen"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Kabelloses Laden"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Wird geladen"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Wird nicht geladen"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Verbunden, wird nicht geladen"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Aufgeladen"</string>
@@ -659,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet nicht verbunden"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Keine Anrufe."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Uhrzeit"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Datum"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Wetter"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luftqualität"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Streaming-Info"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Smart-Home-Steuerung"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Profilbild auswählen"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Standardmäßiges Nutzersymbol"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Physische Tastatur"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index cbc2724..9f71bde 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> για πλήρη φόρτιση"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Απομένουν <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Η φόρτιση τέθηκε σε παύση"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Άγνωστο"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Φόρτιση"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ταχεία φόρτιση"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Αργή φόρτιση"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Ασύρματη φόρτιση"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Φόρτιση"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Δεν φορτίζει"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Συνδεδεμένη, δεν φορτίζει"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Φορτισμένη"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Το Ethernet αποσυνδέθηκε."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Χωρίς κλήσεις."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Ώρα"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Ημερομηνία"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Καιρός"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ποιότητα αέρα"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Πληροφορίες ηθοποιών"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Οικιακοί έλεγχοι"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Επιλογή φωτογραφίας προφίλ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Προεπιλεγμένο εικονίδιο χρήστη"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Φυσικό πληκτρολόγιο"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index c787941..5d16f39 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging is paused"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charging slowly"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Charging wirelessly"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Charging"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connected, not charging"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"No calling."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Time"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Date"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air quality"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index dc79408..d991312 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging is paused"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charging slowly"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Charging wirelessly"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Charging"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connected, not charging"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"No calling."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Time"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Date"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air quality"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index c787941..5d16f39 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging is paused"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charging slowly"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Charging wirelessly"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Charging"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connected, not charging"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"No calling."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Time"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Date"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air quality"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index c787941..5d16f39 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging is paused"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charging slowly"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Charging wirelessly"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Charging"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connected, not charging"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"No calling."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Time"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Date"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air quality"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 175ac5d..ec5d668 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging is paused"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charging slowly"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Charging wirelessly"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Charging"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connected, not charging"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"No calling."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Time"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Date"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air Quality"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast Info"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index cf15466..0731b6b 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> para completar"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Se pausó la carga"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápidamente"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carga lenta"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Carga inalámbrica"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Cargando"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"No se está cargando."</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado; no se está cargando"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Cargada"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desconectada"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Sin llamadas."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Hora"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Fecha"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Clima"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calidad del aire"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info de reparto"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Control de la casa"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Elige una foto de perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ícono de usuario predeterminado"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index bb2f59b..8db2231 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -234,7 +234,7 @@
<string name="apn_settings_not_available" msgid="1147111671403342300">"Los ajustes del nombre del punto de acceso no están disponibles para este usuario"</string>
<string name="enable_adb" msgid="8072776357237289039">"Depuración por USB"</string>
<string name="enable_adb_summary" msgid="3711526030096574316">"Activa el modo de depuración cuando el dispositivo esté conectado por USB"</string>
- <string name="clear_adb_keys" msgid="3010148733140369917">"Revocar autorizaciones de depuración USB"</string>
+ <string name="clear_adb_keys" msgid="3010148733140369917">"Revocar autorizaciones de depuración por USB"</string>
<string name="enable_adb_wireless" msgid="6973226350963971018">"Depuración inalámbrica"</string>
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Activa el modo de depuración cuando haya conexión Wi‑Fi"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"Error"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> hasta la carga completa"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> hasta la carga completa"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga en pausa"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carga rápida"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carga lenta"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Carga inalámbrica"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Cargando"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"No se está cargando"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado pero sin cargar"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Cargada"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Conexión Ethernet desconectada."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Sin llamadas."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Hora"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Fecha"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Tiempo"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calidad del aire"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de emisión"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Domótica"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"De un vistazo"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Elige una imagen de perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icono de usuario predeterminado"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index bcd6ad1..8b8f5b9 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Täislaadimiseks kulub <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – täislaadimiseks kulub <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – laadimine on peatatud"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tundmatu"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Laadimine"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Kiirlaadimine"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Aeglaselt laadimine"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Juhtmevaba laadimine"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Laadimine"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Ei lae"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ühendatud, ei laeta"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Laetud"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Etherneti-ühendus on katkestatud."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Helistamine pole võimalik."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Kellaaeg"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Kuupäev"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Ilm"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Õhukvaliteet"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Osatäitjate teave"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Kodu juhtimine"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Ülevaade"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Valige profiilipilt"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Vaikekasutajaikoon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Füüsiline klaviatuur"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index b1ac236..022fc05 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Kargatze-prozesua etenda dago"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Ezezaguna"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Kargatzen"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Bizkor kargatzen"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Mantso kargatzen"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Hari gabe kargatzen"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Kargatzen"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Ez da kargatzen ari"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Konektatuta dago, baina ez da kargatzen ari"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Kargatuta"</string>
@@ -556,7 +554,7 @@
<string name="help_label" msgid="3528360748637781274">"Laguntza eta iritziak"</string>
<string name="storage_category" msgid="2287342585424631813">"Biltegiratzea"</string>
<string name="shared_data_title" msgid="1017034836800864953">"Datu partekatuak"</string>
- <string name="shared_data_summary" msgid="5516326713822885652">"Ikusi eta aldatu partekatutako datuak"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Ikusi eta aldatu datu partekatuak"</string>
<string name="shared_data_no_blobs_text" msgid="3108114670341737434">"Ez dago erabiltzaile honen datu partekaturik."</string>
<string name="shared_data_query_failure_text" msgid="3489828881998773687">"Errore bat gertatu da datu partekatuak eskuratzean. Saiatu berriro."</string>
<string name="blob_id_text" msgid="8680078988996308061">"Partekatutako datuen IDa: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
@@ -587,7 +585,7 @@
<string name="profile_info_settings_title" msgid="105699672534365099">"Profileko informazioa"</string>
<string name="user_need_lock_message" msgid="4311424336209509301">"Profil murriztua sortu aurretik, aplikazioak eta datu pertsonalak babesteko, pantaila blokeatzeko metodo bat konfiguratu beharko duzu."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Ezarri blokeoa"</string>
- <string name="user_switch_to_user" msgid="6975428297154968543">"Aldatu <xliff:g id="USER_NAME">%s</xliff:g> erabiltzailera"</string>
+ <string name="user_switch_to_user" msgid="6975428297154968543">"Aldatu \"<xliff:g id="USER_NAME">%s</xliff:g>\" erabiltzailera"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Beste erabiltzaile bat sortzen…"</string>
<string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Beste gonbidatu bat sortzen…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Ezin izan da sortu erabiltzailea"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet bidezko konexioa eten da."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Deirik ez."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Ordua"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Data"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Eguraldia"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Airearen kalitatea"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Igorpenari buruzko informazioa"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Etxeko gailuak kontrolatzeko aukerak"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Aukeratu profileko argazki bat"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Erabiltzaile lehenetsiaren ikonoa"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teklatu fisikoa"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index ffd80ec..2231452 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -312,7 +312,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"نمایش گزینهها برای گواهینامه نمایش بیسیم"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"افزایش سطح گزارشگیری Wi‑Fi، نمایش به ازای SSID RSSI در انتخابکننده Wi‑Fi"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"تخلیه باتری راکاهش میدهد و عملکرد شبکه را بهبود میبخشد"</string>
- <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"اگر این حالت فعال باشد، هر بار این دستگاه به شبکهای متصل شود که تصادفیسازی «واپایش دسترسی رسانه» در آن فعال است، ممکن است «نشانی واد» آن تغییر کند."</string>
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"اگر این حالت فعال باشد، هر بار این دستگاه به شبکهای متصل شود که تصادفیسازی «واپایش دسترسی رسانه» در آن فعال است، ممکن است «مک آدرس» آن تغییر کند."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"محدودشده"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"محدودنشده"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"اندازههای حافظه موقت ثبتکننده"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> تا شارژ کامل باقی مانده است"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل باقی مانده است"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - شارژ موقتاً متوقف شده است"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"ناشناس"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"در حال شارژ شدن"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"درحال شارژ شدن سریع"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"درحال شارژ شدن آهسته"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"درحال شارژ بیسیم"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"درحال شارژ شدن"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"شارژ نمیشود"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"متصل، شارژ نمیشود"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"شارژ کامل شد"</string>
@@ -533,7 +531,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"زنگهای هشدار و یادآوریها"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"مجاز کردن تنظیم زنگ ساعت و یادآوری"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"زنگهای ساعت و یادآوریها"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"به این برنامه اجازه میدهد زنگ ساعت تنظیم کند و کنشهای حساس به زمان را زمانبندی کند. این تنظیم به برنامه اجازه میدهد در پسزمینه اجرا شود که ممکن است باتری بیشتری مصرف کند.\n\nاگر این اجازه خاموش باشد، زنگهای ساعت موجود و رویدادهای مبتنی بر زمان که این برنامه زمانبندی کرده است کار نخواهند کرد."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"به این برنامه اجازه میدهد زنگ ساعت تنظیم کند و کنشهای حساس به زمان را زمانبندی کند. این تنظیم به برنامه اجازه میدهد در پسزمینه اجرا شود که ممکن است باتری بیشتری مصرف کند.\n\nاگر این اجازه خاموش باشد، زنگهای ساعت موجود و رویدادهای زمانمحور که این برنامه زمانبندی کرده است کار نخواهند کرد."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"زمانبندی، زنگ ساعت، یادآوری، ساعت"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"روشن کردن"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"روشن کردن «مزاحم نشوید»"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"اترنت قطع شد."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"اترنت."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"تماس گرفته نشود."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"ساعت"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"تاریخ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"آبوهوا"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"کیفیت هوا"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"اطلاعات پخش محتوا"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"کنترل لوازم خانگی"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"انتخاب عکس نمایه"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"نماد کاربر پیشفرض"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"صفحهکلید فیزیکی"</string>
@@ -677,7 +668,7 @@
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"اگر <xliff:g id="SWITCHAPP">%1$s</xliff:g> را همهفرستی کنید یا خروجی را تغییر دهید، همهفرستی کنونی متوقف خواهد شد"</string>
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"همهفرستی <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
<string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"تغییر خروجی"</string>
- <string name="back_navigation_animation" msgid="8105467568421689484">"پویانماییهای اشاره برگشت پیشبینانه"</string>
- <string name="back_navigation_animation_summary" msgid="741292224121599456">"پویانماییهای سیستم را برای اشاره برگشت پیشبینانه فعال کنید."</string>
+ <string name="back_navigation_animation" msgid="8105467568421689484">"پویانماییهای اشاره برگشت پیشگویانه"</string>
+ <string name="back_navigation_animation_summary" msgid="741292224121599456">"پویانماییهای سیستم را برای اشاره برگشت پیشگویانه فعال کنید."</string>
<string name="back_navigation_animation_dialog" msgid="8696966520944625596">"این تنظیم پویانماییهای سیستم را برای پویانمایی اشاره برگشت پیشبینانه فعال میکند. این تنظیم مستلزم تنظیم شدن enableOnBackInvokedCallback مربوط به هر برنامه روی صحیح در فایل مانیفست است."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 3d12c02..743d53b3 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> kunnes täynnä"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Lataus on keskeytetty"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tuntematon"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Ladataan"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Nopea lataus"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Hidas lataus"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Langaton lataus"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Ladataan"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Ei laturissa"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Yhdistetty, ei ladata"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Ladattu"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet on irrotettu."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Ei puheluita."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Aika"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Päivämäärä"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Sää"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ilmanlaatu"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Striimaustiedot"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Kodin ohjaus"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Pikanäkymä"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Valitse profiilikuva"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Oletuskäyttäjäkuvake"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fyysinen näppäimistö"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 808c3f2..dfa6db3 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -76,7 +76,7 @@
<item msgid="1963366694959681026">"avrcp16"</item>
</string-array>
<string-array name="bluetooth_map_versions">
- <item msgid="8786402640610987099">"MAP 1.2 (valeur par défaut)"</item>
+ <item msgid="8786402640610987099">"MAP 1.2 (par défaut)"</item>
<item msgid="6817922176194686449">"MAP 1.3"</item>
<item msgid="3423518690032737851">"MAP 1.4"</item>
</string-array>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 7dfc86e..d3f96f2 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -273,9 +273,9 @@
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Autoriser le déverrouillage du fichier d\'amorce"</string>
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Permettre le déverrouillage par le fabricant?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"AVERTISSEMENT : Les fonctionnalités de protection de l\'appareil ne fonctionneront pas sur cet appareil lorsque ce paramètre est activé."</string>
- <string name="mock_location_app" msgid="6269380172542248304">"Sélectionner l\'application de localisation factice"</string>
- <string name="mock_location_app_not_set" msgid="6972032787262831155">"Aucune application de localisation factice définie"</string>
- <string name="mock_location_app_set" msgid="4706722469342913843">"Application de localisation factice : <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app" msgid="6269380172542248304">"Sélectionner l\'application de position fictive"</string>
+ <string name="mock_location_app_not_set" msgid="6972032787262831155">"Aucune application de position fictive définie"</string>
+ <string name="mock_location_app_set" msgid="4706722469342913843">"Application de position fictive : <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"Réseautage"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"Certification de l\'affichage sans fil"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Autoriser enreg. données Wi-Fi détaillées"</string>
@@ -408,8 +408,7 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permet de redimensionner toutes les activités pour le mode multi-fenêtre, indépendamment des valeurs du fichier manifeste."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Activer les fenêtres de forme libre"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Activer la compatibilité avec les fenêtres de forme libre expérimentales."</string>
- <!-- no translation found for desktop_mode (2389067840550544462) -->
- <skip />
+ <string name="desktop_mode" msgid="2389067840550544462">"Mode Bureau"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Mot de passe sauvegarde PC"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Les sauvegardes complètes sur PC ne sont pas protégées actuellement"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Touchez pour modifier ou supprimer le mot de passe utilisé pour les sauvegardes complètes sur ordinateur."</string>
@@ -478,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la recharge complète"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la recharge complète)"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - La recharge est interrompue"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charge en cours…"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Recharge rapide"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Recharge lente"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"En recharge sans fil"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Recharge en cours…"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"N\'est pas en charge"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connecté, pas en charge"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Chargée"</string>
@@ -659,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet déconnecté."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Aucun appel."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Heure"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Date"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Météo"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualité de l\'air"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info diffusion"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Domotique"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Aperçu"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choisir une photo de profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icône d\'utilisateur par défaut"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Clavier physique"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 52d15f1..b6eb82e 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Chargée à 100 %% dans <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – La recharge est en pause"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Batterie en charge"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charge rapide"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charge lente"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"En charge sans fil"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Recharge"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Pas en charge"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connectée, pas en charge"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Chargée"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet déconnecté"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Pas d\'appels."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Heure"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Date"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Météo"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualité de l\'air"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Infos distribution"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Domotique"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choisissez une photo de profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icône de l\'utilisateur par défaut"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Clavier physique"</string>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index f663120..fb8e5f2 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -76,7 +76,7 @@
<item msgid="1963366694959681026">"avrcp16"</item>
</string-array>
<string-array name="bluetooth_map_versions">
- <item msgid="8786402640610987099">"MAP 1.2 (predeterminada)"</item>
+ <item msgid="8786402640610987099">"MAP 1.2 (predeterminado)"</item>
<item msgid="6817922176194686449">"MAP 1.3"</item>
<item msgid="3423518690032737851">"MAP 1.4"</item>
</string-array>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index ef73b59..7a8942a 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -288,8 +288,8 @@
<string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activar Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versión de Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecciona a versión de Bluetooth AVRCP"</string>
- <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versión de MAP de Bluetooth"</string>
- <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Selecciona a versión de MAP de Bluetooth"</string>
+ <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versión de Bluetooth MAP"</string>
+ <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Selecciona a versión de Bluetooth MAP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Códec de audio por Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activar códec de audio por Bluetooth\nSelección"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de mostra de audio por Bluetooth"</string>
@@ -339,8 +339,8 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Comproba as aplicacións instaladas a través de ADB/ADT para detectar comportamento perigoso"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Mostraranse dispositivos Bluetooth sen nomes (só enderezos MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Desactiva a función do volume absoluto do Bluetooth en caso de que se produzan problemas de volume cos dispositivos remotos, como volume demasiado alto ou falta de control"</string>
- <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Activa o conxunto de funcións de Bluetooth Gabeldorsche."</string>
- <string name="enhanced_connectivity_summary" msgid="1576414159820676330">"Activa a función de conectividade mellorada."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Activa o conxunto de funcións de Bluetooth Gabeldorsche"</string>
+ <string name="enhanced_connectivity_summary" msgid="1576414159820676330">"Activa a función de conectividade mellorada"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Activa a aplicación terminal que ofrece acceso ao shell local"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Comprobación HDCP"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> para completar a carga"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> para completar a carga)"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: a carga está en pausa"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Descoñecido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rapidamente"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Cargando lentamente"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Cargando sen fíos"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Cargando"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Non se está cargando"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado, sen cargar"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Cargada"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Desconectouse a Ethernet."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Sen chamadas."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Hora"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Data"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"O tempo"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calidade do aire"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Datos da emisión"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Controis domóticos"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Espazo intelixente"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Escolle unha imaxe do perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icona do usuario predeterminado"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
@@ -677,7 +668,7 @@
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Se emites contido a través de <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou cambias de saída, a emisión en curso deterase"</string>
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Emitir contido a través de <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
<string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Cambiar de saída"</string>
- <string name="back_navigation_animation" msgid="8105467568421689484">"Animacións para o xesto preditivo de volver atrás"</string>
- <string name="back_navigation_animation_summary" msgid="741292224121599456">"Activa as animacións do sistema para o xesto preditivo de volver atrás."</string>
- <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Esta opción de configuración activa as animacións do sistema para o xesto preditivo de volver atrás. É preciso definir enableOnBackInvokedCallback como True (verdadeiro) para cada aplicación no ficheiro de manifesto."</string>
+ <string name="back_navigation_animation" msgid="8105467568421689484">"Animacións de retroceso preditivo"</string>
+ <string name="back_navigation_animation_summary" msgid="741292224121599456">"Activa as animacións do sistema para o retroceso preditivo."</string>
+ <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Esta opción de configuración activa as animacións xestuais preditivas. É preciso definir enableOnBackInvokedCallback como True (verdadeiro) para cada aplicación no ficheiro de manifesto."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 02c9927..f0ee94f 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"પૂર્ણ ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - પૂર્ણ ચાર્જ થવામાં <xliff:g id="TIME">%2$s</xliff:g> બાકી છે"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જિંગ થોભાવવામાં આવ્યું છે"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"અજાણ્યું"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ચાર્જ થઈ રહ્યું છે"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ઝડપથી ચાર્જ થાય છે"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ધીમેથી ચાર્જ થાય છે"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"વાયરલેસથી ચાર્જિંગ"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ચાર્જ થઈ રહ્યું છે"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ચાર્જ થઈ રહ્યું નથી"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"કનેક્ટ કરેલું છે, પણ ચાર્જ થઈ રહ્યું નથી"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ચાર્જ થયું"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ઇથરનેટ ડિસ્કનેક્ટ થયું."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ઇથરનેટ."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"કોઈ કૉલિંગ નહીં."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"સમય"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"તારીખ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"હવામાન"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"હવાની ક્વૉલિટી"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"કાસ્ટ વિશેની માહિતી"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ઘરેલુ સાધન નિયંત્રણો"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"પ્રોફાઇલ ફોટો પસંદ કરો"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ડિફૉલ્ટ વપરાશકર્તાનું આઇકન"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ભૌતિક કીબોર્ડ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 6dbb2b4..4ef4ee6 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -273,8 +273,8 @@
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"बूटलोडर को अनलाॅक किए जाने की अनुमति दें"</string>
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM अनलॉक करने की अनुमति दें?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"चेतावनी: इस सेटिंग के चालू रहने पर डिवाइस सुरक्षा सुविधाएं इस डिवाइस पर काम नहीं करेंगी."</string>
- <string name="mock_location_app" msgid="6269380172542248304">"जगह की दिखावटी जानकारी देने के लिए ऐप्लिकेशन चुनें"</string>
- <string name="mock_location_app_not_set" msgid="6972032787262831155">"जगह की दिखावटी जानकारी देने के लिए ऐप सेट नहीं है"</string>
+ <string name="mock_location_app" msgid="6269380172542248304">"मॉक लोकेशन के लिए ऐप्लिकेशन चुनें"</string>
+ <string name="mock_location_app_not_set" msgid="6972032787262831155">"मॉक लोकेशन के लिए ऐप्लिकेशन सेट नहीं है"</string>
<string name="mock_location_app_set" msgid="4706722469342913843">"जगह की दिखावटी जानकारी देने वाला ऐप: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"नेटवर्किंग"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"वायरलेस डिसप्ले सर्टिफ़िकेशन"</string>
@@ -338,7 +338,7 @@
<string name="verify_apps_over_usb_title" msgid="6031809675604442636">"यूएसबी पर ऐप्लिकेशन की पुष्टि करें"</string>
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"नुकसान पहुंचाने वाली गतिविधियों के लिए ADB/ADT से इंस्टॉल किए गए ऐप्लिकेशन जांचें."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"बिना नाम वाले ब्लूटूथ डिवाइस (सिर्फ़ MAC पते वाले) दिखाए जाएंगे"</string>
- <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"दूर के डिवाइस पर आवाज़ बहुत बढ़ जाने या उससे कंट्रोल हटने जैसी समस्याएं होने पर, यह ब्लूटूथ के ज़रिए आवाज़ के कंट्रोल की सुविधा रोक देता है."</string>
+ <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"रिमोट डिवाइस पर आवाज़ बहुत बढ़ जाने या उससे कंट्रोल हटने जैसी समस्याएं होने पर, यह ब्लूटूथ के ज़रिए आवाज़ के कंट्रोल की सुविधा रोक देता है."</string>
<string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ब्लूटूथ सेटिंग में Gabeldorsche सुविधा को चालू करता है."</string>
<string name="enhanced_connectivity_summary" msgid="1576414159820676330">"कनेक्टिविटी बेहतर बनाने की सुविधा को चालू करें"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"स्थानीय टर्मिनल"</string>
@@ -408,8 +408,7 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"सभी गतिविधियों को मल्टी-विंडो (एक से ज़्यादा ऐप्लिकेशन, एक साथ) के लिए साइज़ बदलने लायक बनाएं, चाहे उनकी मेनिफ़ेस्ट वैल्यू कुछ भी हो."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"फ़्रीफ़ॉर्म विंडो (एक साथ कई विंडो दिखाना) चालू करें"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"जांच के लिए बनी फ़्रीफ़ॉर्म विंडो के लिए सहायता चालू करें."</string>
- <!-- no translation found for desktop_mode (2389067840550544462) -->
- <skip />
+ <string name="desktop_mode" msgid="2389067840550544462">"डेस्कटॉप मोड"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"डेस्कटॉप बैक अप पासवर्ड"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"डेस्कटॉप के पूरे बैक अप फ़िलहाल सुरक्षित नहीं हैं"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"डेस्कटॉप के पूरे बैक अप का पासवर्ड बदलने या हटाने के लिए टैप करें"</string>
@@ -478,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> में बैटरी पूरी चार्ज हो जाएगी"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में बैटरी पूरी चार्ज हो जाएगी"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्जिंग को रोका गया है"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हो रही है"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"तेज़ चार्ज हो रही है"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"धीरे चार्ज हो रही है"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"वायरलेस चार्जिंग"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"चार्ज हो रहा है"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज नहीं हो रही है"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"कनेक्ट किया गया, चार्ज नहीं हो रहा है"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"बैटरी चार्ज हो गई"</string>
@@ -496,7 +493,7 @@
<string name="disabled" msgid="8017887509554714950">"बंद किया गया"</string>
<string name="external_source_trusted" msgid="1146522036773132905">"अनुमति है"</string>
<string name="external_source_untrusted" msgid="5037891688911672227">"अनुमति नहीं है"</string>
- <string name="install_other_apps" msgid="3232595082023199454">"अनजान ऐप्लिकेशन इंस्टॉल करने का ऐक्सेस"</string>
+ <string name="install_other_apps" msgid="3232595082023199454">"अनजान ऐप्लिकेशन इंस्टॉल करने की अनुमति देना"</string>
<string name="home" msgid="973834627243661438">"सेटिंग का होम पेज"</string>
<string-array name="battery_labels">
<item msgid="7878690469765357158">"0%"</item>
@@ -659,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ईथरनेट डिस्कनेक्ट किया गया."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ईथरनेट."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"वॉइस कॉल की सुविधा उपलब्ध नहीं है."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"समय"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"तारीख"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"मौसम"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"हवा की क्वालिटी"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"कास्टिंग की जानकारी"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"होम कंट्रोल"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"स्मार्टस्पेस"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"प्रोफ़ाइल फ़ोटो चुनें"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"उपयोगकर्ता के लिए डिफ़ॉल्ट आइकॉन"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"फ़िज़िकल कीबोर्ड"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index e3f8ba8b..1684dbc 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -338,7 +338,7 @@
<string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Potvrdi aplikacije putem USB-a"</string>
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Provjerite uzrokuju li aplikacije instalirane putem ADB-a/ADT-a poteškoće"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Prikazivat će se Bluetooth uređaji bez naziva (samo MAC adrese)"</string>
- <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Onemogućuje Bluetoothovu značajku apsolutne glasnoće ako udaljeni uređaji imaju poteškoća sa zvukom, kao što su neprihvatljiva glasnoća ili nepostojanje kontrole"</string>
+ <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Onemogućuje Bluetoothovu značajku apsolutne glasnoće ako udaljeni uređaji imaju poteškoća sa zvukom, primjerice, zvuk je pretjerano glasan ili se ne može kontrolirati."</string>
<string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Omogućuje nizove značajke Bluetooth Gabeldorsche."</string>
<string name="enhanced_connectivity_summary" msgid="1576414159820676330">"Omogućuje značajku Poboljšana povezivost."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Lokalni terminal"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do napunjenosti"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je pauzirano"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Sporo punjenje"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bežično punjenje"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Punjenje"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Ne puni se"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Povezano, ne puni se"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Napunjeno"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Prekinuta je veza s ethernetom."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Bez poziva."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Vrijeme"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Datum"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Vremenska prognoza"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvaliteta zraka"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Inform. o emitiranju"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Upravlj. kuć. uređ."</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Odabir profilne slike"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikona zadanog korisnika"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fizička tipkovnica"</string>
@@ -678,6 +669,6 @@
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Emitiranje aplikacije <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
<string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Promjena izlaza"</string>
<string name="back_navigation_animation" msgid="8105467568421689484">"Animacije za pokret povratka s predviđanjem"</string>
- <string name="back_navigation_animation_summary" msgid="741292224121599456">"Omogući animacije sustava za pokret povratka s predviđanjem."</string>
+ <string name="back_navigation_animation_summary" msgid="741292224121599456">"Omogući animaciju kad korisnik napravi povratnu kretnju."</string>
<string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Ova postavka omogućuje animacije sustava za animaciju pokreta s predviđanjem. Zahtijeva postavljanje dopuštenja enableOnBackInvokedCallback po aplikaciji na True u datoteci manifesta."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 8ff6031..a460d9f 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> a teljes töltöttségig"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes töltöttségig"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – A töltés szünetel"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Ismeretlen"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Töltés"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Gyorstöltés"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Lassú töltés"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Vezeték nélküli töltés"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Töltés…"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nem tölt"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Csatlakoztatva, nem töltődik"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Feltöltve"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet leválasztva."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Nem kezdeményezhet hanghívást."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Idő"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Dátum"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Időjárás"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Levegőminőség"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Átküldési információ"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Otthonvezérlés"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Profilkép választása"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Alapértelmezett felhasználó ikonja"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fizikai billentyűzet"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 8a458668..345bca4 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> մինչև լրիվ լիցքավորումը"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Լիցքավորումը դադարեցված է"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Անհայտ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Լիցքավորում"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Արագ լիցքավորում"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Դանդաղ լիցքավորում"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Անլար լիցքավորում"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Լիցքավորում"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Չի լիցքավորվում"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Միացված է, չի լիցքավորվում"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Լիցքավորված է"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet-ը անջատված է:"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet։"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Զանգել հնարավոր չէ։"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Ժամ"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Ամսաթիվ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Եղանակ"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Օդի որակը"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Հեռարձակման տվյալներ"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Տան կարգավորումներ"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Պրոֆիլի նկար ընտրեք"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Օգտատիրոջ կանխադրված պատկերակ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Ֆիզիկական ստեղնաշար"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 6dc5697..8ee255c 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> lagi sampai penuh"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi sampai penuh"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengisian daya dijeda"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Mengisi daya"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengisi daya cepat"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Mengisi daya lambat"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Mengisi daya nirkabel"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Pengisian daya"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Tidak mengisi daya"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Terhubung, tidak mengisi daya"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Terisi"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet terputus."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Tidak ada panggilan."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Waktu"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Tanggal"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Cuaca"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kualitas Udara"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info Transmisi"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Kontrol Rumah"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Pilih foto profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikon pengguna default"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Keyboard fisik"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 4531fb1..5a6ec02 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> fram að fullri hleðslu"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> fram að fullri hleðslu"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Hlé var gert á hleðslu"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Óþekkt"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Í hleðslu"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hröð hleðsla"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Hæg hleðsla"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Hleður þráðlaust"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Í hleðslu"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Ekki í hleðslu"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Tengt, ekki í hleðslu"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Fullhlaðin"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet aftengt."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Engin símtöl."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Tími"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Dagsetning"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Veður"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Loftgæði"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Útsendingaruppl."</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Heimastýringar"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Veldu prófílmynd"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Tákn sjálfgefins notanda"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Vélbúnaðarlyklaborð"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 87f5870..7d04b51 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> alla ricarica completa"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla ricarica completa"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ricarica in pausa"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Sconosciuta"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"In carica"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ricarica veloce"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Ricarica lenta"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"In carica, wireless"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"In carica"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Non in carica"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Dispositivo connesso, non in carica"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Carica"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Connessione Ethernet annullata."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Chiamate non disponibili."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Ora"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Data"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Meteo"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualità dell\'aria"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info sul cast"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Controlli della casa"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Scegli un\'immagine del profilo"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icona dell\'utente predefinito"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Tastiera fisica"</string>
@@ -677,7 +668,7 @@
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Se trasmetti l\'app <xliff:g id="SWITCHAPP">%1$s</xliff:g> o cambi l\'uscita, la trasmissione attuale viene interrotta"</string>
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Trasmetti l\'app <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
<string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Cambia uscita"</string>
- <string name="back_navigation_animation" msgid="8105467568421689484">"Animazioni predittive con Indietro"</string>
+ <string name="back_navigation_animation" msgid="8105467568421689484">"Animazioni predittive per Indietro"</string>
<string name="back_navigation_animation_summary" msgid="741292224121599456">"Attiva le animazioni di sistema per il gesto Indietro predittivo."</string>
<string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Questa impostazione attiva le animazioni di sistema per il gesto Indietro predittivo. Richiede di impostare il metodo enableOnBackInvokedCallback su true nel file manifest di tutte le app."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 5f567c6..e7e4e1c 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"הזמן הנותר לטעינה מלאה: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – הזמן הנותר לטעינה מלאה: <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – הטעינה הושהתה"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"לא ידוע"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"בטעינה"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"הסוללה נטענת מהר"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"הסוללה נטענת לאט"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"בטעינה אלחוטית"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"טעינה"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"לא בטעינה"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"מחובר, לא בטעינה"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"הסוללה טעונה"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"אתרנט מנותק."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"אתרנט."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"אין שיחות."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"שעה"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"תאריך"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"מזג אוויר"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"איכות האוויר"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"פרטי ההעברה"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"בית חכם"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"בחירה של תמונת פרופיל"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"סמל המשתמש שמוגדר כברירת מחדל"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"מקלדת פיזית"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 49dfb92..c9d622086 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -233,10 +233,10 @@
<string name="tethering_settings_not_available" msgid="266821736434699780">"このユーザーはテザリング設定を利用できません"</string>
<string name="apn_settings_not_available" msgid="1147111671403342300">"このユーザーはアクセスポイント名設定を利用できません"</string>
<string name="enable_adb" msgid="8072776357237289039">"USB デバッグ"</string>
- <string name="enable_adb_summary" msgid="3711526030096574316">"USB 接続時はデバッグモードにする"</string>
+ <string name="enable_adb_summary" msgid="3711526030096574316">"USB 接続時にデバッグモードにする"</string>
<string name="clear_adb_keys" msgid="3010148733140369917">"USB デバッグの許可の取り消し"</string>
<string name="enable_adb_wireless" msgid="6973226350963971018">"ワイヤレス デバッグ"</string>
- <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi 接続時はデバッグモードにする"</string>
+ <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi 接続時にデバッグモードにする"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"エラー"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"ワイヤレス デバッグ"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"利用可能なデバイスを確認して使用するには、ワイヤレス デバッグを ON にしてください"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"完了まであと <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - 完了まであと <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電は一時停止中"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"急速充電中"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"低速充電中"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ワイヤレス充電中"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"充電中"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"充電していません"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"接続済み、充電していません"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"充電が完了しました"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"イーサネット接続を解除しました。"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"イーサネット。"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"通話なし。"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"時刻"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"日付"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"天気"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"大気質"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"キャスト情報"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"スマートホーム"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"プロフィール写真の選択"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"デフォルト ユーザー アイコン"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"物理キーボード"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 93dfb44..fb7b96a 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> — სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - დატენვა ᲨეᲩერებულია"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"უცნობი"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"იტენება"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"სწრაფად იტენება"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ნელა იტენება"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"უსადენოდ დატენა"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"იტენება"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"არ იტენება"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"დაკავშირებულია, არ იტენება"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"დატენილია"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet კავშირი შეწყვეტილია."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"ზარების გარეშე."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"დრო"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"თარიღი"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"ამინდი"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"ჰაერის ხარისხი"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ტრანსლირების ინფო"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"სახლის მართვა"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"ჭკვიანი სივრცე"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"აირჩიეთ პროფილის სურათი"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"მომხმარებლის ნაგულისხმევი ხატულა"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ფიზიკური კლავიატურა"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 4733c28..4c35633 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Толық зарядталғанға дейін <xliff:g id="TIME">%1$s</xliff:g> қалды."</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – толық зарядталғанға дейін <xliff:g id="TIME">%2$s</xliff:g> қалды."</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядтау кідіртілді."</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Белгісіз"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Зарядталуда"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Жылдам зарядталуда"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Баяу зарядталуда"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Сымсыз зарядталуда"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Зарядталып жатыр."</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Зарядталу орындалып жатқан жоқ"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Жалғанған, зарядталып жатқан жоқ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Зарядталды"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet ажыратылған."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Қоңырау шалу мүмкін емес."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Уақыт"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Күн"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Ауа райы"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ауа сапасы"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Трансляция ақпараты"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Үйді басқару элементтері"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Профиль суретін таңдау"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Әдепкі пайдаланушы белгішесі"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Пернетақта"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 7715985..0799e38 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបពេញ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - នៅសល់ <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើបពេញ"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ការសាកថ្មត្រូវបានផ្អាក"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"មិនស្គាល់"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"កំពុងសាកថ្ម"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"កំពុងសាកថ្មយឺត"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"កំពុងសាកថ្មឥតខ្សែ"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"កំពុងសាកថ្ម"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"មិនកំពុងសាកថ្ម"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"បានភ្ជាប់ មិនកំពុងសាកថ្ម"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"បានសាកថ្មពេញ"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"បានផ្តាច់អ៊ីសឺរណិត។"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"អ៊ីសឺរណិត។"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"គ្មានការហៅទូរសព្ទទេ។"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"ម៉ោង"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"កាលបរិច្ឆេទ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"អាកាសធាតុ"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"គុណភាពខ្យល់"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ព័ត៌មានអំពីការបញ្ជូន"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ការគ្រប់គ្រងផ្ទះ"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ជ្រើសរើសរូបភាពកម្រងព័ត៌មាន"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"រូបអ្នកប្រើប្រាស់លំនាំដើម"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ក្ដារចុចរូបវន្ត"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 66e2da8..12a3323 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> - ಸಮಯದಲ್ಲಿ ಪೂರ್ತಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ತಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"ಅಪರಿಚಿತ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ವೇಗದ ಚಾರ್ಜಿಂಗ್"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ನಿಧಾನ ಗತಿಯ ಚಾರ್ಜಿಂಗ್"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ವೈರ್ಲೆಸ್ ಚಾರ್ಜಿಂಗ್"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"ಕನೆಕ್ಟ್ ಆಗಿದೆ, ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ಇಥರ್ನೆಟ್ ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ಇಥರ್ನೆಟ್."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"ಕರೆ ಮಾಡಲಾಗುವುದಿಲ್ಲ."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"ಸಮಯ"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"ದಿನಾಂಕ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"ಹವಾಮಾನ"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"ವಾಯು ಗುಣಮಟ್ಟ"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ಬಿತ್ತರಿಸಿದ ಮಾಹಿತಿ"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ಹೋಮ್ ನಿಯಂತ್ರಣಗಳು"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ಪ್ರೊಫೈಲ್ ಚಿತ್ರವನ್ನು ಆಯ್ಕೆ ಮಾಡಿ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ಡೀಫಾಲ್ಟ್ ಬಳಕೆದಾರರ ಐಕಾನ್"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್"</string>
@@ -677,7 +668,7 @@
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"ನೀವು <xliff:g id="SWITCHAPP">%1$s</xliff:g> ಅನ್ನು ಪ್ರಸಾರ ಮಾಡಿದರೆ ಅಥವಾ ಔಟ್ಪುಟ್ ಅನ್ನು ಬದಲಾಯಿಸಿದರೆ, ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಪ್ರಸಾರವು ಸ್ಥಗಿತಗೊಳ್ಳುತ್ತದೆ"</string>
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ಅನ್ನು ಪ್ರಸಾರ ಮಾಡಿ"</string>
<string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"ಔಟ್ಪುಟ್ ಅನ್ನು ಬದಲಾಯಿಸಿ"</string>
- <string name="back_navigation_animation" msgid="8105467568421689484">"ಮುನ್ನೋಟದ ಬ್ಯಾಕ್ ಆ್ಯನಿಮೇಶನ್ಗಳು"</string>
- <string name="back_navigation_animation_summary" msgid="741292224121599456">"ಮುನ್ನೋಟದ ಬ್ಯಾಕ್ ಗೆಸ್ಚರ್ಗಾಗಿ ಸಿಸ್ಟಂ ಆ್ಯನಿಮೇಶನ್ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ."</string>
+ <string name="back_navigation_animation" msgid="8105467568421689484">"ಮುನ್ಸೂಚಕ ಬ್ಯಾಕ್ ಆ್ಯನಿಮೇಶನ್ಗಳು"</string>
+ <string name="back_navigation_animation_summary" msgid="741292224121599456">"ಮುನ್ಸೂಚಕ ಬ್ಯಾಕ್ ಗೆಸ್ಚರ್ಗಾಗಿ ಸಿಸ್ಟಂ ಆ್ಯನಿಮೇಶನ್ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ."</string>
<string name="back_navigation_animation_dialog" msgid="8696966520944625596">"ಮುನ್ನೋಟದ ಗೆಸ್ಚರ್ ಆ್ಯನಿಮೇಶನ್ಗಾಗಿ ಸಿಸ್ಟಂ ಆ್ಯನಿಮೇಶನ್ಗಳನ್ನು ಈ ಸೆಟ್ಟಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸುತ್ತವೆ. ಇದನ್ನು ಮಾಡಲು, ಪ್ರತಿ ಆ್ಯಪ್ನ ಮ್ಯಾನಿಫೆಸ್ಟ್ ಫೈಲ್ನಲ್ಲಿರುವ enableOnBackInvokedCallback ಪ್ಯಾರಾಮೀಟರ್ ಅನ್ನು ಸರಿ ಎಂದು ಹೊಂದಿಸಬೇಕು."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 111dd34..7aef15d 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -184,7 +184,7 @@
<string name="launch_defaults_some" msgid="3631650616557252926">"일부 기본값이 설정됨"</string>
<string name="launch_defaults_none" msgid="8049374306261262709">"기본값이 설정되지 않음"</string>
<string name="tts_settings" msgid="8130616705989351312">"TTS 설정"</string>
- <string name="tts_settings_title" msgid="7602210956640483039">"TTS 출력"</string>
+ <string name="tts_settings_title" msgid="7602210956640483039">"텍스트 음성 변환 출력"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"말하는 속도"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"텍스트를 읽어주는 속도"</string>
<string name="tts_default_pitch_title" msgid="6988592215554485479">"음조"</string>
@@ -273,8 +273,8 @@
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"부트로더 잠금 해제 허용"</string>
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM 잠금 해제를 허용하시겠습니까?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"경고: 이 설정을 사용하는 동안에는 이 기기에서 기기 보호 기능이 작동하지 않습니다."</string>
- <string name="mock_location_app" msgid="6269380172542248304">"모의 위치 앱 선택"</string>
- <string name="mock_location_app_not_set" msgid="6972032787262831155">"모의 위치 앱이 설정되어 있지 않음"</string>
+ <string name="mock_location_app" msgid="6269380172542248304">"가상 위치 앱 선택"</string>
+ <string name="mock_location_app_not_set" msgid="6972032787262831155">"가상 위치 앱이 설정되어 있지 않음"</string>
<string name="mock_location_app_set" msgid="4706722469342913843">"모의 위치 앱: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"네트워크"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"무선 디스플레이 인증서"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> 후 충전 완료"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 일시중지됨"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"알 수 없음"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"충전 중"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"고속 충전 중"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"저속 충전 중"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"무선 충전 중"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"충전"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"충전 안함"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"연결됨, 충전 중 아님"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"충전됨"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"이더넷에서 연결 해제되었습니다."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"이더넷에 연결되었습니다."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"통화 모드가 없습니다."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"시간"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"날짜"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"날씨"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"대기 상태"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"전송 정보"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"홈 컨트롤"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"프로필 사진 선택하기"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"기본 사용자 아이콘"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"물리적 키보드"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index ea9bd86..3e88ed5 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -195,7 +195,7 @@
<string name="tts_default_lang_summary" msgid="9042620014800063470">"Текстти окуй турган тилди тандоо"</string>
<string name="tts_play_example_title" msgid="1599468547216481684">"Үлгүнү угуу"</string>
<string name="tts_play_example_summary" msgid="634044730710636383">"Кепти синтездөөнүн кыскача көргөзмөсүн ойнотуу"</string>
- <string name="tts_install_data_title" msgid="1829942496472751703">"Үн дайындарын орнотуу"</string>
+ <string name="tts_install_data_title" msgid="1829942496472751703">"Үнгө байланыштуу нерселерди орнотуу"</string>
<string name="tts_install_data_summary" msgid="3608874324992243851">"Кеп синтезине керектүү үн дайындарын орнотуңуз"</string>
<string name="tts_engine_security_warning" msgid="3372432853837988146">"Бул кепти синтездөө каражаты бардык айтыла турган текстти, анын ичинде сырсөздөр жана насыя карточкасынын номери сыяктуу жеке маалыматты, топтошу мүмкүн. Ал <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> каражатынан алынат. Бул кепти синтездөө каражаты колдонулсунбу?"</string>
<string name="tts_engine_network_required" msgid="8722087649733906851">"Бул тилде кеп синтезаторун иштетүү үчүн Интернетке туташуу керек."</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> кийин толук кубатталат"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталат"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Кубаттоо тындырылды"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Белгисиз"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Кубатталууда"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ыкчам кубатталууда"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Жай кубатталууда"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Зымсыз кубатталууда"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Кубатталууда"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Кубат алган жок"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Туташты, кубатталган жок"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Кубатталды"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet ажырады."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Чалуу жок."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Убакыт"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Күн"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Аба ырайы"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Абанын сапаты"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Тышкы экранга чыгаруу маалыматы"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Үйдү көзөмөлдөө"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Профилдин сүрөтүн тандоо"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Демейки колдонуучунун сүрөтчөсү"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Аппараттык баскычтоп"</string>
@@ -678,6 +669,6 @@
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> колдонмосунда кабарлоо"</string>
<string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Аудионун чыгуусун өзгөртүү"</string>
<string name="back_navigation_animation" msgid="8105467568421689484">"Божомолдонгон анимациялар"</string>
- <string name="back_navigation_animation_summary" msgid="741292224121599456">"Божомолдоп билүү үчүн тутумдун анимацияларын иштетиңиз."</string>
- <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Бул параметр жаңсоо анимациясын божомолдоп билүү үчүн тутумдун анимацияларын иштетет. Ал үчүн манифест файлындагы enableOnBackInvokedCallback параметри ар бир колдонмо үчүн \"true\" деп коюлушу керек."</string>
+ <string name="back_navigation_animation_summary" msgid="741292224121599456">"Божомолдоп билүү үчүн системанын анимацияларын иштетиңиз."</string>
+ <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Бул параметр жаңсоо анимациясын божомолдоп билүү үчүн системанын анимацияларын иштетет. Ал үчүн манифест файлындагы enableOnBackInvokedCallback параметри ар бир колдонмо үчүн \"true\" деп коюлушу керек."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 10b814d..c2dfb81 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ຍັງເຫຼືອອີກ <xliff:g id="TIME">%1$s</xliff:g> ຈຶ່ງຈະສາກເຕັມ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"ຍັງເຫຼືອອີກ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະສາກເຕັມ"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ການສາກໄຟຖືກຢຸດໄວ້ຊົ່ວຄາວ"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"ບໍ່ຮູ້ຈັກ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ກຳລັງສາກໄຟ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ກຳລັງສາກໄຟດ່ວນ"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ກຳລັງສາກໄຟຊ້າໆ"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ກຳລັງສາກໄຟໄຮ້ສາຍ"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ກຳລັງສາກໄຟ"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ບໍ່ໄດ້ສາກໄຟ"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"ເຊື່ອມຕໍ່ແລ້ວ, ບໍ່ໄດ້ສາກໄຟ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ສາກເຕັມແລ້ວ"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ອີເທີເນັດຕັດເຊື່ອມຕໍ່ແລ້ວ."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ອີເທີເນັດ."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"ບໍ່ສາມາດໂທສຽງໄດ້."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"ເວລາ"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"ວັນທີ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"ສະພາບອາກາດ"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"ຄຸນນະພາບອາກາດ"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ຂໍ້ມູນການສົ່ງສັນຍານ"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ການຄວບຄຸມເຮືອນ"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ເລືອກຮູບໂປຣໄຟລ໌"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ໄອຄອນຜູ້ໃຊ້ເລີ່ມຕົ້ນ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ແປ້ນພິມພາຍນອກ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index ce53dfe..01e4708 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Liko <xliff:g id="TIME">%1$s</xliff:g>, kol bus visiškai įkrauta"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko <xliff:g id="TIME">%2$s</xliff:g>, kol bus visiškai įkrauta"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – įkrovimas pristabdytas"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nežinomas"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Kraunasi..."</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Greitai įkraunama"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Lėtai įkraunama"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Kraunama be laidų"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Įkraunama"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nekraunama"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Prijungta, neįkraunama"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Įkrauta"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Atsijungta nuo eterneto."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Eternetas."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Nekviečiama."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Laikas"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Data"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Orai"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Oro kokybė"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Perdav. informacija"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Namų sist. valdikl."</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Pasirinkite profilio nuotrauką"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Numatytojo naudotojo piktograma"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fizinė klaviatūra"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index df91791..1020fc4 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> līdz pilnai uzlādei"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> — uzlāde ir pārtraukta"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nezināms"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Uzlāde"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Notiek ātrā uzlāde"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Notiek lēnā uzlāde"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bezvadu uzlāde"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Notiek uzlāde"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nenotiek uzlāde"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ierīce pievienota, uzlāde nenotiek"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Uzlādēts"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Pārtraukts savienojums ar tīklu Ethernet."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Tīkls Ethernet"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Zvanīšana nav pieejama."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Laiks"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Datums"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Laikapstākļi"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Gaisa kvalitāte"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Apraides informācija"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Mājas kontrolierīces"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Profila attēla izvēle"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Noklusējuma lietotāja ikona"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fiziskā tastatūra"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 7f82835..7846561 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полна батерија"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> до полна батерија"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Полнењето е паузирано"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Се полни"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо полнење"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Бавно полнење"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Се полни безжично"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Се полни"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Не се полни"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Поврзано, не се полни"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Полна"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Етернетот е исклучен."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Етернет."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Без повици."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Време"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Датум"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Временска прогноза"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Квалитет на воздух"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Инфо за улогите"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Контроли за домот"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Изберете профилна слика"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Икона за стандарден корисник"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Физичка тастатура"</string>
@@ -677,7 +668,7 @@
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ако емитувате на <xliff:g id="SWITCHAPP">%1$s</xliff:g> или го промените излезот, тековното емитување ќе запре"</string>
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Емитување на <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
<string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Променете излез"</string>
- <string name="back_navigation_animation" msgid="8105467568421689484">"Предвидливи анимации отпозади"</string>
- <string name="back_navigation_animation_summary" msgid="741292224121599456">"Овозможете предвидливи системски анимации отпозади."</string>
+ <string name="back_navigation_animation" msgid="8105467568421689484">"Анимации за движењето за враќање"</string>
+ <string name="back_navigation_animation_summary" msgid="741292224121599456">"Овозможете системски анимации за движењето за враќање."</string>
<string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Поставкава ги овозможува системските анимации за предвидливи движења. Поставката треба да се постави на „точно“ преку апликација enableOnBackInvokedCallback во датотеката за манифест."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 43040ef..31664fb 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"പൂർണ്ണമാകാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമാകാൻ <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ചാർജിംഗ് താൽക്കാലികമായി നിർത്തി"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"അജ്ഞാതം"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ചാർജ് ചെയ്യുന്നു"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"അതിവേഗ ചാർജിംഗ്"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"പതുക്കെയുള്ള ചാർജിംഗ്"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"വയർലെസായി ചാർജുചെയ്യുന്നു"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ചാർജ് ചെയ്യുന്നു"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ചാർജ്ജുചെയ്യുന്നില്ല"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"കണക്റ്റ് ചെയ്തിരിക്കുന്നു, ചാർജ് ചെയ്യുന്നില്ല"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ചാർജായി"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ഇതർനെറ്റ് വിച്ഛേദിച്ചു."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ഇതർനെറ്റ്."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"വോയ്സ് കോൾ ലഭ്യമല്ല."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"സമയം"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"തീയതി"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"കാലാവസ്ഥ"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"വായു നിലവാരം"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"കാസ്റ്റ് വിവരങ്ങൾ"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ഹോം കൺട്രോളുകൾ"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"പ്രൊഫൈൽ ചിത്രം തിരഞ്ഞെടുക്കുക"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ഡിഫോൾട്ട് ഉപയോക്തൃ ഐക്കൺ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ഫിസിക്കൽ കീബോർഡ്"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index ad8b6fd..e556136 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Дүүрэх хүртэл <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - дүүрэх хүртэл <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Цэнэглэхийг түр зогсоосон"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Тодорхойгүй"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Цэнэглэж байна"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хурдан цэнэглэж байна"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Удаан цэнэглэж байна"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Утасгүй цэнэглэж байна"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Цэнэглэж байна"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Цэнэглэхгүй байна"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Холбогдсон, цэнэглээгүй байна"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Цэнэглэсэн"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet саллаа."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Этернэт."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Дуудлага байхгүй."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Хугацаа"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Огноо"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Цаг агаар"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Агаарын чанар"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Дамжуулах мэдээлэл"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Гэрийн удирдлага"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Профайл зураг сонгох"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Өгөгдмөл хэрэглэгчийн дүрс тэмдэг"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Биет гар"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index be5222a..55d4e63 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -201,9 +201,9 @@
<string name="tts_engine_network_required" msgid="8722087649733906851">"या भाषेस टेक्स्ट टू स्पीचसाठी एका नेटवर्क कनेक्शनची आवश्यकता आहे."</string>
<string name="tts_default_sample_string" msgid="6388016028292967973">"हे उच्चार संश्लेषणाचे एक उदाहरण आहे"</string>
<string name="tts_status_title" msgid="8190784181389278640">"डीफॉल्ट भाषा स्थिती"</string>
- <string name="tts_status_ok" msgid="8583076006537547379">"<xliff:g id="LOCALE">%1$s</xliff:g> पूर्णपणे समर्थित आहे"</string>
+ <string name="tts_status_ok" msgid="8583076006537547379">"<xliff:g id="LOCALE">%1$s</xliff:g> ला पूर्ण सपोर्ट आहे"</string>
<string name="tts_status_requires_network" msgid="8327617638884678896">"<xliff:g id="LOCALE">%1$s</xliff:g> ला नेटवर्क कनेक्शनची आवश्यकता आहे"</string>
- <string name="tts_status_not_supported" msgid="2702997696245523743">"<xliff:g id="LOCALE">%1$s</xliff:g> समर्थित नाही"</string>
+ <string name="tts_status_not_supported" msgid="2702997696245523743">"<xliff:g id="LOCALE">%1$s</xliff:g> ला सपोर्ट नाही"</string>
<string name="tts_status_checking" msgid="8026559918948285013">"तपासत आहे..."</string>
<string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> साठी सेटिंग्ज"</string>
<string name="tts_engine_settings_button" msgid="477155276199968948">"इंजीन सेटिंग्ज लाँच करा"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"पूर्ण चार्ज होण्यासाठी <xliff:g id="TIME">%1$s</xliff:g> शिल्लक आहेत"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूर्ण चार्ज होण्यासाठी <xliff:g id="TIME">%2$s</xliff:g> शिल्लक आहे"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज करणे थांबवले आहे"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज होत आहे"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"वेगाने चार्ज होत आहे"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"हळू चार्ज होत आहे"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"वायरलेसने चार्ज होत आहे"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"चार्ज होत आहे"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज होत नाही"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"कनेक्ट केले, चार्ज होत नाही"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"चार्ज झाली"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"इथरनेट डिस्कनेक्ट केले."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"इथरनेट."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"कॉलिंग उपलब्ध नाही."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"वेळ"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"तारीख"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"हवामान"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"हवेची गुणवत्ता"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"कास्टसंबंधित माहिती"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"होम कंट्रोल"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"स्मार्टस्पेस"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"प्रोफाइल फोटो निवडा"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"डीफॉल्ट वापरकर्ता आयकन"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"वास्तविक कीबोर्ड"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index cadc5cf..3ecd1c2 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> lagi sebelum penuh"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi sebelum penuh"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengecasan dijeda"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Mengecas"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengecas dgn cepat"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Mengecas perlahan"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Mengecas tanpa wayar"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Pengecasan"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Tidak mengecas"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Bersambung, tidak mengecas"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Sudah dicas"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet diputuskan sambungan."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Tiada panggilan."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Masa"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Tarikh"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Cuaca"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kualiti Udara"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Maklumat Pelakon"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Kawalan Rumah"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Pilih gambar profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikon pengguna lalai"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Papan kekunci fizikal"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 0c49387..3035760 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> လိုသည်"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"အားပြည့်ရန် <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> လိုသည်"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားသွင်းခြင်းကို ခဏရပ်ထားသည်"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"မသိ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"အားသွင်းနေပါသည်"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"အမြန် အားသွင်းနေသည်"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"နှေးကွေးစွာ အားသွင်း"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ကြိုးမဲ့ အားသွင်းနေသည်"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"အားသွင်းနေသည်"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"အားသွင်းမနေပါ"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"ချိတ်ဆက်ထားသည်၊ အားသွင်းမနေပါ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"အားသွင်းပြီးပါပြီ"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet နှင့်ချိတ်ဆက်မှုပြတ်တောက်"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"အီသာနက်။"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"ခေါ်ဆိုမှု မရှိပါ။"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"အချိန်"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"ရက်စွဲ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"မိုးလေဝသ"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"လေထုအရည်အသွေး"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ကာစ် အချက်အလက်"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"အိမ်သတ်မှတ်ချက်များ"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ပရိုဖိုင်ပုံ ရွေးပါ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"မူရင်းအသုံးပြုသူ သင်္ကေတ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ပကတိ ကီးဘုတ်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 6ca0cc3..a7618df 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Fulladet om <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fulladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ladingen er satt på pause"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Ukjent"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Lader"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Lader raskt"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Lader sakte"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Lader trådløst"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Lader"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Lader ikke"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Tilkoblet, lader ikke"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Ladet"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet er frakoblet."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Ingen ringing."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Klokkeslett"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Dato"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Vær"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luftkvalitet"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Castinformasjon"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Hjemkontroller"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Velg et profilbilde"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Standard brukerikon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fysisk tastatur"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 88bdba4..628881c 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"पूरा चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> लाग्ने छ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूरा चार्ज हुन <xliff:g id="TIME">%2$s</xliff:g> लाग्ने छ"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज गर्ने प्रक्रिया रोकिएको छ"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हुँदै छ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"द्रुत गतिमा चार्ज गरिँदै छ"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ढिलो चार्ज हुँदै छ"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"वायरलेस तरिकाले चार्ज गरिँदै छ"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"चार्ज हुँदै छ"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज भइरहेको छैन"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"कनेक्ट गरिएको छ, चार्ज भइरहेको छैन"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"चार्ज भयो"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"इथरनेट विच्छेद भयो।"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"इथरनेट।"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"कल गर्ने सुविधा उपलब्ध छैन।"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"समय"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"मिति"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"मौसम"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"वायुको गुणस्तर"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"कास्टसम्बन्धी जानकारी"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"घरायसी उपकरणका नियन्त्रण"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"प्रोफाइल फोटो छान्नुहोस्"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"प्रयोगकर्ताको डिफल्ट आइकन"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"भौतिक किबोर्ड"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 1183630..30467b8 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Vol over <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - vol over <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Opladen is onderbroken"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Opladen"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Snel opladen"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Langzaam opladen"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Draadloos opladen"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Opladen"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Wordt niet opgeladen"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Verbonden, wordt niet opgeladen"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Opgeladen"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernetverbinding verbroken."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Geen gesprekken."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Tijd"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Datum"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Weer"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luchtkwaliteit"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Castinformatie"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Bediening voor in huis"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Kies een profielfoto"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Standaard gebruikersicoon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fysiek toetsenbord"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index a949dc9..0ef753e 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -233,10 +233,10 @@
<string name="tethering_settings_not_available" msgid="266821736434699780">"ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଟିଥରିଂ ସେଟିଂସ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="apn_settings_not_available" msgid="1147111671403342300">"ଆକ୍ସେସ ପଏଣ୍ଟ ନାମର ସେଟିଂସ ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="enable_adb" msgid="8072776357237289039">"USB ଡିବଗିଂ"</string>
- <string name="enable_adb_summary" msgid="3711526030096574316">"USB ସଂଯୁକ୍ତ ହେବାବେଳେ ଡିବଗ୍ ମୋଡ୍"</string>
+ <string name="enable_adb_summary" msgid="3711526030096574316">"USB କନେକ୍ଟ ହେବାବେଳେ ଡିବଗ ମୋଡ"</string>
<string name="clear_adb_keys" msgid="3010148733140369917">"USB ଡିବଗିଂ ଅଧିକାରକୁ ବାତିଲ୍ କରନ୍ତୁ"</string>
<string name="enable_adb_wireless" msgid="6973226350963971018">"ୱାୟାରଲେସ୍ ଡିବଗିଂ"</string>
- <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"ୱାଇ-ଫାଇ ସଂଯୁକ୍ତ ଥିବା ବେଳେ ଡିବଗ୍ ମୋଡ୍"</string>
+ <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"ୱାଇ-ଫାଇ କନେକ୍ଟ ଥିବା ବେଳେ ଡିବଗ ମୋଡ"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"ତ୍ରୁଟି"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"ୱାୟାରଲେସ୍ ଡିବଗିଂ"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"ଉପଲବ୍ଧ ଡିଭାଇସଗୁଡ଼ିକୁ ଦେଖିବାକୁ ଏବଂ ବ୍ୟବହାର କରିବାକୁ ୱାୟାରଲେସ୍ ଡିବଗିଂ ଚାଲୁ କରନ୍ତୁ"</string>
@@ -273,8 +273,8 @@
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"bootloaderକୁ ଅନ୍ଲକ୍ ହେବାର ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM ଅନଲକ୍ କରିବା ଅନୁମତି ଦେବେ?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"ଚେତାବନୀ: ଏହି ସେଟିଙ୍ଗ ଚାଲୁ ଥିବାବେଳେ ଡିଭାଇସ୍ର ସୁରକ୍ଷା ବୈଶିଷ୍ଟ୍ୟ କାମ କରିବ ନାହିଁ"</string>
- <string name="mock_location_app" msgid="6269380172542248304">"ମକ୍ ଲୋକେସନ୍ ଆପ୍ର ଚୟନ କରନ୍ତୁ"</string>
- <string name="mock_location_app_not_set" msgid="6972032787262831155">"କୌଣସି ମକ୍ ଲୋକେସନ ଆପ୍ ସେଟ୍ କରାଯାଇନାହିଁ"</string>
+ <string name="mock_location_app" msgid="6269380172542248304">"ମକ ଲୋକେସନ ଆପ ଚୟନ କରନ୍ତୁ"</string>
+ <string name="mock_location_app_not_set" msgid="6972032787262831155">"କୌଣସି ମକ ଲୋକେସନ ଆପ ସେଟ କରାଯାଇନାହିଁ"</string>
<string name="mock_location_app_set" msgid="4706722469342913843">"ମକ୍ ଲୋକେସନ୍ ଆପ୍: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"ନେଟ୍ୱର୍କିଙ୍ଗ"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"ୱାୟରଲେସ୍ ଡିସ୍ପ୍ଲେ ସାର୍ଟିଫିକେସନ୍"</string>
@@ -283,10 +283,10 @@
<string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"ୱାଇ-ଫାଇ ଅଣ-ଅବିରତ MAC ରେଣ୍ଡମାଇଜେସନ୍"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"ମୋବାଇଲ୍ ଡାଟା ସର୍ବଦା ସକ୍ରିୟ"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"ଟିଥରିଙ୍ଗ ହାର୍ଡୱେର ଆକ୍ସିଲିରେସନ୍"</string>
- <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"ବ୍ଲୁଟୂଥ୍ ଡିଭାଇସ୍ଗୁଡ଼ିକୁ ନାମ ବିନା ଦେଖନ୍ତୁ"</string>
+ <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"ବ୍ଲୁଟୂଥ ଡିଭାଇସଗୁଡ଼ିକୁ ନାମ ବିନା ଦେଖାନ୍ତୁ"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"ପୂର୍ଣ୍ଣ ଭଲ୍ୟୁମ୍ ଅକ୍ଷମ କରନ୍ତୁ"</string>
<string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"ଗାବେଲ୍ଡୋର୍ସ ସକ୍ରିୟ କରନ୍ତୁ"</string>
- <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ବ୍ଲୁଟୂଥ୍ AVRCP ଭର୍ସନ୍"</string>
+ <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ବ୍ଲୁଟୂଥ୍ AVRCP ସଂସ୍କରଣ"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ବ୍ଲୁଟୂଥ୍ AVRCP ଭର୍ସନ୍"</string>
<string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ବ୍ଲୁଟୁଥ୍ MAP ସଂସ୍କରଣ"</string>
<string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"ବ୍ଲୁଟୁଥ୍ MAP ସଂସ୍କରଣ ଚୟନ କରନ୍ତୁ"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ପୂର୍ଣ୍ଣ ହେବାକୁ ଆଉ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - ପୂର୍ଣ୍ଣ ହେବାକୁ ଆଉ <xliff:g id="TIME">%2$s</xliff:g> ବାକି ଅଛି"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ଚାର୍ଜିଂକୁ ବିରତ କରାଯାଇଛି"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"ଅଜ୍ଞାତ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ଚାର୍ଜ ହେଉଛି"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ଧୀରେ ଚାର୍ଜ ହେଉଛି"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ୱେୟରଲେସ ଭାବେ ଚାର୍ଜିଂ"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ଚାର୍ଜ ହେଉଛି"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ଚାର୍ଜ ହେଉନାହିଁ"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"ସଂଯୋଗ କରାଯାଇଛି, ଚାର୍ଜ ହେଉନାହିଁ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ଚାର୍ଜ ହୋଇଯାଇଛି"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ଇଥରନେଟ୍ ବିଚ୍ଛିନ୍ନ ହୋଇଛି।"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ଇଥରନେଟ୍।"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"କୌଣସି କଲିଂ ନାହିଁ।"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"ସମୟ"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"ତାରିଖ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"ପାଣିପାଗ"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"ବାୟୁର ଗୁଣବତ୍ତା"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"କାଷ୍ଟ ସୂଚନା"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ହୋମ କଣ୍ଟ୍ରୋଲ"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"ସ୍ମାର୍ଟସ୍ପେସ"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ଏକ ପ୍ରୋଫାଇଲ ଛବି ବାଛନ୍ତୁ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ଡିଫଲ୍ଟ ଉପଯୋଗକର୍ତ୍ତା ଆଇକନ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ଫିଜିକାଲ କୀବୋର୍ଡ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 4d16cec..a65073c 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ਬੈਟਰੀ ਪੂਰੀ ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਪੂਰੀ ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਚਾਰਜਿੰਗ ਨੂੰ ਰੋਕਿਆ ਗਿਆ ਹੈ"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"ਅਗਿਆਤ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ਬਿਨਾਂ ਤਾਰ ਤੋਂ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"ਕਨੈਕਟ ਹੈ, ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਹੀ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ਚਾਰਜ ਹੋ ਗਈ"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ਈਥਰਨੈੱਟ ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ।"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ਈਥਰਨੈੱਟ।"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"ਕਾਲਿੰਗ ਸੇਵਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"ਸਮਾਂ"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"ਤਾਰੀਖ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"ਮੌਸਮ"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"ਹਵਾ ਦੀ ਕੁਆਲਿਟੀ"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ਕਾਸਟ ਸੰਬੰਧੀ ਜਾਣਕਾਰੀ"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ਹੋਮ ਕੰਟਰੋਲ"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ਕੋਈ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਚੁਣੋ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਵਰਤੋਂਕਾਰ ਪ੍ਰਤੀਕ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index cd8b6fb..68188b9 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do pełnego naładowania"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – ładowanie zostało wstrzymane"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nieznane"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Ładowanie"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Szybkie ładowanie"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Wolne ładowanie"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Ładowanie bezprzewodowe"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Ładowanie"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nie podłączony"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Podłączono, brak ładowania"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Naładowana"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Rozłączono z siecią Ethernet."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Brak połączenia."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Godzina"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Data"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Pogoda"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Jakość powietrza"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Obsada"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Sterowanie domem"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Wybierz zdjęcie profilowe"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikona domyślnego użytkownika"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Klawiatura fizyczna"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 4e1b1dd..21f68e6 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até a conclusão"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a conclusão"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: o carregamento está pausado"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carregando devagar"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Carregando sem fio"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Carregando"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Não está carregando"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado sem carregar"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Carregada"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desconectada."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Sem chamadas."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Hora"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Data"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Clima"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualidade do ar"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de transmissão"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Automação residencial"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Escolher a foto do perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ícone de usuário padrão"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 9215ce3..aebc553 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -273,7 +273,7 @@
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Permitir o desbloqueio do carregador de arranque"</string>
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Permitir o desbloqueio de OEM?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"AVISO: as funcionalidades de proteção do dispositivo não funcionam neste dispositivo enquanto esta definição estiver ativada."</string>
- <string name="mock_location_app" msgid="6269380172542248304">"Selecionar aplicação de localização fictícia"</string>
+ <string name="mock_location_app" msgid="6269380172542248304">"Selecionar app de localização fictícia"</string>
<string name="mock_location_app_not_set" msgid="6972032787262831155">"Aplicação de localização fictícia não definida"</string>
<string name="mock_location_app_set" msgid="4706722469342913843">"Aplicação de localização fictícia: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"Redes"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até à carga máxima"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até à carga máxima"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – O carregamento está pausado"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"A carregar"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregamento rápido"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carregamento lento"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"A carregar sem fios"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"A carregar"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Não está a carregar"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ligado, não está a carregar"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Carregada"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desligada."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Sem chamadas."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Hora"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Data"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Meteorologia"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualidade do ar"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de transmissão"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Ctr. domésticos"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Espaço inteligente"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Escolha uma imagem do perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ícone do utilizador predefinido"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 4e1b1dd..21f68e6 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até a conclusão"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a conclusão"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: o carregamento está pausado"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carregando devagar"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Carregando sem fio"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Carregando"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Não está carregando"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado sem carregar"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Carregada"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desconectada."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Sem chamadas."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Hora"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Data"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Clima"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualidade do ar"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de transmissão"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Automação residencial"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Escolher a foto do perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ícone de usuário padrão"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 34b0ac9..987b9c3 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -86,7 +86,7 @@
<item msgid="8147982633566548515">"map14"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Folosiți selectarea sistemului (prestabilit)"</item>
+ <item msgid="2494959071796102843">"Folosește selectarea sistemului (prestabilit)"</item>
<item msgid="4055460186095649420">"SBC"</item>
<item msgid="720249083677397051">"AAC"</item>
<item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
@@ -96,7 +96,7 @@
<item msgid="506175145534048710">"Opus"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Folosiți selectarea sistemului (prestabilit)"</item>
+ <item msgid="8868109554557331312">"Folosește selectarea sistemului (prestabilit)"</item>
<item msgid="9024885861221697796">"SBC"</item>
<item msgid="4688890470703790013">"AAC"</item>
<item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
@@ -106,7 +106,7 @@
<item msgid="7940970833006181407">"Opus"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
- <item msgid="926809261293414607">"Folosiți selectarea sistemului (prestabilit)"</item>
+ <item msgid="926809261293414607">"Folosește selectarea sistemului (prestabilit)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
<item msgid="3208896645474529394">"48,0 kHz"</item>
<item msgid="8420261949134022577">"88,2 kHz"</item>
@@ -120,24 +120,24 @@
<item msgid="8946330945963372966">"96,0 kHz"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
- <item msgid="2574107108483219051">"Folosiți selectarea sistemului (prestabilit)"</item>
+ <item msgid="2574107108483219051">"Folosește selectarea sistemului (prestabilit)"</item>
<item msgid="4671992321419011165">"16 biți/eșantion"</item>
<item msgid="1933898806184763940">"24 biți/eșantion"</item>
<item msgid="1212577207279552119">"32 biți/eșantion"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
- <item msgid="9196208128729063711">"Folosiți selectarea sistemului (prestabilit)"</item>
+ <item msgid="9196208128729063711">"Folosește selectarea sistemului (prestabilit)"</item>
<item msgid="1084497364516370912">"16 biți/eșantion"</item>
<item msgid="2077889391457961734">"24 biți/eșantion"</item>
<item msgid="3836844909491316925">"32 biți/eșantion"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_channel_mode_titles">
- <item msgid="3014194562841654656">"Folosiți selectarea sistemului (prestabilit)"</item>
+ <item msgid="3014194562841654656">"Folosește selectarea sistemului (prestabilit)"</item>
<item msgid="5982952342181788248">"Mono"</item>
<item msgid="927546067692441494">"Stereo"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
- <item msgid="1997302811102880485">"Folosiți selectarea sistemului (prestabilit)"</item>
+ <item msgid="1997302811102880485">"Folosește selectarea sistemului (prestabilit)"</item>
<item msgid="8005696114958453588">"Mono"</item>
<item msgid="1333279807604675720">"Stereo"</item>
</string-array>
@@ -238,7 +238,7 @@
<item msgid="4433736508877934305">"Niciuna"</item>
<item msgid="9140053004929079158">"Logcat"</item>
<item msgid="3866871644917859262">"Systrace (imagini)"</item>
- <item msgid="7345673972166571060">"Apelați stiva pentru glGetError"</item>
+ <item msgid="7345673972166571060">"Apelează stiva pentru glGetError"</item>
</string-array>
<string-array name="show_non_rect_clip_entries">
<item msgid="2482978351289846212">"Dezactivat"</item>
@@ -252,7 +252,7 @@
</string-array>
<string-array name="debug_hw_overdraw_entries">
<item msgid="1968128556747588800">"Dezactivată"</item>
- <item msgid="3033215374382962216">"Afișați zonele cu suprapunere"</item>
+ <item msgid="3033215374382962216">"Afișează zonele cu suprapunere"</item>
<item msgid="3474333938380896988">"Afișați zonele de deuteranomalie"</item>
</string-array>
<string-array name="app_process_limit_entries">
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 3c81199..2ce7ccf 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -58,7 +58,7 @@
<string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problemă la autentificare"</string>
<string name="wifi_cant_connect" msgid="5718417542623056783">"Nu se poate conecta"</string>
<string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Nu se poate conecta la „<xliff:g id="AP_NAME">%1$s</xliff:g>”"</string>
- <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Verificați parola și încercați din nou"</string>
+ <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Verifică parola și încearcă din nou"</string>
<string name="wifi_not_in_range" msgid="1541760821805777772">"În afara ariei de acoperire"</string>
<string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Nu se va conecta automat"</string>
<string name="wifi_no_internet" msgid="1774198889176926299">"Nu există acces la internet"</string>
@@ -69,19 +69,19 @@
<string name="connected_via_passpoint" msgid="7735442932429075684">"Conectată prin %1$s"</string>
<string name="connected_via_app" msgid="3532267661404276584">"Conectat prin <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="available_via_passpoint" msgid="1716000261192603682">"Disponibilă prin %1$s"</string>
- <string name="tap_to_sign_up" msgid="5356397741063740395">"Atingeți pentru a vă înscrie"</string>
+ <string name="tap_to_sign_up" msgid="5356397741063740395">"Atinge pentru a te înscrie"</string>
<string name="wifi_connected_no_internet" msgid="5087420713443350646">"Fără conexiune la internet"</string>
<string name="private_dns_broken" msgid="1984159464346556931">"Serverul DNS privat nu poate fi accesat"</string>
<string name="wifi_limited_connection" msgid="1184778285475204682">"Conexiune limitată"</string>
<string name="wifi_status_no_internet" msgid="3799933875988829048">"Fără conexiune la internet"</string>
- <string name="wifi_status_sign_in_required" msgid="2236267500459526855">"Trebuie să vă conectați"</string>
+ <string name="wifi_status_sign_in_required" msgid="2236267500459526855">"Trebuie să te conectezi"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5885145407184194503">"Punctul de acces este temporar plin"</string>
<string name="connected_via_carrier" msgid="1968057009076191514">"Conectată prin %1$s"</string>
<string name="available_via_carrier" msgid="465598683092718294">"Disponibilă prin %1$s"</string>
<string name="osu_opening_provider" msgid="4318105381295178285">"Se deschide <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string>
<string name="osu_connect_failed" msgid="9107873364807159193">"Nu s-a putut conecta"</string>
<string name="osu_completing_sign_up" msgid="8412636665040390901">"Se finalizează înscrierea…"</string>
- <string name="osu_sign_up_failed" msgid="5605453599586001793">"Nu s-a putut finaliza înscrierea. Atingeți pentru a încerca din nou."</string>
+ <string name="osu_sign_up_failed" msgid="5605453599586001793">"Nu s-a putut finaliza înscrierea. Atinge pentru a încerca din nou."</string>
<string name="osu_sign_up_complete" msgid="7640183358878916847">"Înscrierea a fost finalizată. Se conectează…"</string>
<string name="speed_label_very_slow" msgid="8526005255731597666">"Foarte lentă"</string>
<string name="speed_label_slow" msgid="6069917670665664161">"Lentă"</string>
@@ -94,7 +94,7 @@
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Deconectat"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"În curs de deconectare..."</string>
<string name="bluetooth_connecting" msgid="5871702668260192755">"Se conectează..."</string>
- <string name="bluetooth_connected" msgid="8065345572198502293">"V-ați conectat la <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_connected" msgid="8065345572198502293">"Te-ai conectat la <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
<string name="bluetooth_pairing" msgid="4269046942588193600">"Se asociază…"</string>
<string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Conectat (fără telefon) la <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Conectat (fără conținut media) la <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -118,7 +118,7 @@
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispozitiv de intrare"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acces la internet"</string>
<string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Acces la agendă și istoricul apelurilor"</string>
- <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Folosiți pentru accesul la agendă și istoricul apelurilor"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Folosește pentru accesul la agendă și istoricul apelurilor"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Distribuirea conexiunii la internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Mesaje text"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acces la SIM"</string>
@@ -137,19 +137,19 @@
<string name="bluetooth_hid_profile_summary_connected" msgid="3923653977051684833">"Conectat la dispozitivul de intrare"</string>
<string name="bluetooth_pan_user_profile_summary_connected" msgid="380469653827505727">"Conectat la dispoz. pt. acces internet"</string>
<string name="bluetooth_pan_nap_profile_summary_connected" msgid="3744773111299503493">"Acces la internet local"</string>
- <string name="bluetooth_pan_profile_summary_use_for" msgid="7422039765025340313">"Utilizați pentru acces la internet"</string>
- <string name="bluetooth_map_profile_summary_use_for" msgid="4453622103977592583">"Utilizați pentru hartă"</string>
+ <string name="bluetooth_pan_profile_summary_use_for" msgid="7422039765025340313">"Folosește pentru acces la internet"</string>
+ <string name="bluetooth_map_profile_summary_use_for" msgid="4453622103977592583">"Folosește pentru hartă"</string>
<string name="bluetooth_sap_profile_summary_use_for" msgid="6204902866176714046">"Folosiți pentru acces la SIM"</string>
- <string name="bluetooth_a2dp_profile_summary_use_for" msgid="7324694226276491807">"Utilizați pentru profilul pentru conținut media audio"</string>
- <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Utilizați pentru componenta audio a telefonului"</string>
- <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Utilizați pentru transferul de fișiere"</string>
+ <string name="bluetooth_a2dp_profile_summary_use_for" msgid="7324694226276491807">"Folosește pentru profilul pentru conținut media audio"</string>
+ <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Folosește pentru componenta audio a telefonului"</string>
+ <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Folosește pentru transferul de fișiere"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Utilizați pentru introducere date"</string>
<string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Folosiți pentru aparatele auditive"</string>
- <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Folosiți pentru LE_AUDIO"</string>
- <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Asociați"</string>
- <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"CONECTAȚI"</string>
- <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Anulați"</string>
- <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Asocierea dispozitivelor vă permite accesul la persoanele de contact și la istoricul apelurilor când dispozitivul este conectat."</string>
+ <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Folosește pentru LE_AUDIO"</string>
+ <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Asociază"</string>
+ <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"CONECTEAZĂ"</string>
+ <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Anulează"</string>
+ <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Asocierea dispozitivelor îți permite accesul la persoanele de contact și la istoricul apelurilor când dispozitivul este conectat."</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Nu s-a putut împerechea cu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Nu s-a putut asocia cu <xliff:g id="DEVICE_NAME">%1$s</xliff:g> din cauza unui cod PIN sau a unei chei de acces incorecte."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Nu se poate comunica cu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
@@ -168,7 +168,7 @@
<string name="accessibility_wifi_three_bars" msgid="779895671061950234">"Semnal Wi-Fi: trei bare."</string>
<string name="accessibility_wifi_signal_full" msgid="7165262794551355617">"Semnal Wi-Fi: complet."</string>
<string name="accessibility_wifi_security_type_none" msgid="162352241518066966">"Rețea nesecurizată"</string>
- <string name="accessibility_wifi_security_type_secured" msgid="2399774097343238942">"Securizați rețeaua"</string>
+ <string name="accessibility_wifi_security_type_secured" msgid="2399774097343238942">"Securizează rețeaua"</string>
<string name="process_kernel_label" msgid="950292573930336765">"Sistem de operare Android"</string>
<string name="data_usage_uninstalled_apps" msgid="1933665711856171491">"Aplicații eliminate"</string>
<string name="data_usage_uninstalled_apps_users" msgid="5533981546921913295">"Aplicații și utilizatori eliminați"</string>
@@ -190,14 +190,14 @@
<string name="tts_default_pitch_title" msgid="6988592215554485479">"Înălțime"</string>
<string name="tts_default_pitch_summary" msgid="9132719475281551884">"Afectează tonalitatea vorbirii sintetizate"</string>
<string name="tts_default_lang_title" msgid="4698933575028098940">"Limbă"</string>
- <string name="tts_lang_use_system" msgid="6312945299804012406">"Utilizați limba sistemului"</string>
- <string name="tts_lang_not_selected" msgid="7927823081096056147">"Nu ați selectat limba"</string>
+ <string name="tts_lang_use_system" msgid="6312945299804012406">"Folosește limba sistemului"</string>
+ <string name="tts_lang_not_selected" msgid="7927823081096056147">"Nu ai selectat limba"</string>
<string name="tts_default_lang_summary" msgid="9042620014800063470">"Setează vocea caracteristică limbii pentru textul vorbit"</string>
- <string name="tts_play_example_title" msgid="1599468547216481684">"Ascultați un exemplu"</string>
- <string name="tts_play_example_summary" msgid="634044730710636383">"Redați o demonstrație scurtă a sintetizării vorbirii"</string>
- <string name="tts_install_data_title" msgid="1829942496472751703">"Instalați date vocale"</string>
- <string name="tts_install_data_summary" msgid="3608874324992243851">"Instalați datele vocale necesare pentru sintetizarea vorbirii"</string>
- <string name="tts_engine_security_warning" msgid="3372432853837988146">"Acest motor de sintetizare a vorbirii poate culege în întregime textul vorbit, inclusiv datele personale cum ar fi parolele și numerele cărților de credit. Metoda provine de la motorul <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Permiteți utilizarea acestui motor de sintetizare a vorbirii?"</string>
+ <string name="tts_play_example_title" msgid="1599468547216481684">"Ascultă un exemplu"</string>
+ <string name="tts_play_example_summary" msgid="634044730710636383">"Redă o demonstrație scurtă a sintetizării vorbirii"</string>
+ <string name="tts_install_data_title" msgid="1829942496472751703">"Instalează date vocale"</string>
+ <string name="tts_install_data_summary" msgid="3608874324992243851">"Instalează datele vocale necesare pentru sintetizarea vorbirii"</string>
+ <string name="tts_engine_security_warning" msgid="3372432853837988146">"Acest motor de sintetizare a vorbirii poate culege în întregime textul vorbit, inclusiv datele personale cum ar fi parolele și numerele cărților de credit. Metoda provine de la motorul <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Permiți utilizarea acestui motor de sintetizare a vorbirii?"</string>
<string name="tts_engine_network_required" msgid="8722087649733906851">"Pentru rezultatul transformării textului în vorbire pentru această limbă este necesară o conexiune de rețea care să funcționeze."</string>
<string name="tts_default_sample_string" msgid="6388016028292967973">"Acesta este un exemplu de sintetizare a vorbirii"</string>
<string name="tts_status_title" msgid="8190784181389278640">"Starea limbii prestabilite"</string>
@@ -209,8 +209,8 @@
<string name="tts_engine_settings_button" msgid="477155276199968948">"Lansați setările motorului"</string>
<string name="tts_engine_preference_section_title" msgid="3861562305498624904">"Motor preferat"</string>
<string name="tts_general_section_title" msgid="8919671529502364567">"Preferințe generale"</string>
- <string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"Resetați tonalitatea vorbirii"</string>
- <string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"Resetați tonalitatea cu care se rostește textul în mod prestabilit."</string>
+ <string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"Resetează tonalitatea vorbirii"</string>
+ <string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"Resetează tonalitatea cu care se rostește textul în mod prestabilit."</string>
<string-array name="tts_rate_entries">
<item msgid="9004239613505400644">"Foarte încet"</item>
<item msgid="1815382991399815061">"Încet"</item>
@@ -222,12 +222,12 @@
<item msgid="7147051179282410945">"Foarte rapid"</item>
<item msgid="581904787661470707">"Cel mai repede"</item>
</string-array>
- <string name="choose_profile" msgid="343803890897657450">"Alegeți un profil"</string>
+ <string name="choose_profile" msgid="343803890897657450">"Alege un profil"</string>
<string name="category_personal" msgid="6236798763159385225">"Personal"</string>
<string name="category_work" msgid="4014193632325996115">"Serviciu"</string>
<string name="development_settings_title" msgid="140296922921597393">"Opțiuni pentru dezvoltatori"</string>
- <string name="development_settings_enable" msgid="4285094651288242183">"Activați opțiunile pentru dezvoltatori"</string>
- <string name="development_settings_summary" msgid="8718917813868735095">"Setați opțiuni pentru dezvoltarea aplicației"</string>
+ <string name="development_settings_enable" msgid="4285094651288242183">"Activează opțiunile pentru dezvoltatori"</string>
+ <string name="development_settings_summary" msgid="8718917813868735095">"Setează opțiuni pentru dezvoltarea aplicației"</string>
<string name="development_settings_not_available" msgid="355070198089140951">"Opțiunile de dezvoltator nu sunt disponibile pentru acest utilizator"</string>
<string name="vpn_settings_not_available" msgid="2894137119965668920">"Setările VPN nu sunt disponibile pentru acest utilizator"</string>
<string name="tethering_settings_not_available" msgid="266821736434699780">"Setările pentru tethering nu sunt disponibile pentru acest utilizator"</string>
@@ -239,41 +239,41 @@
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modul de remediere a erorilor când rețeaua Wi-Fi este conectată"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"Eroare"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"Remedierea erorilor wireless"</string>
- <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Activați remedierea erorilor wireless pentru a vedea și a folosi dispozitivele disponibile"</string>
- <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Asociați dispozitivul folosind codul QR"</string>
- <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Asociați dispozitive noi folosind scannerul de coduri QR"</string>
- <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Asociați dispozitivul folosind codul de conectare"</string>
- <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Asociați dispozitive noi folosind codul din șase cifre"</string>
+ <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Activează remedierea erorilor wireless pentru a vedea și a folosi dispozitivele disponibile"</string>
+ <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Asociază dispozitivul folosind codul QR"</string>
+ <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Asociază dispozitive noi folosind scannerul de coduri QR"</string>
+ <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Asociază dispozitivul folosind codul de conectare"</string>
+ <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Asociază dispozitive noi folosind codul din șase cifre"</string>
<string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispozitive asociate"</string>
<string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Conectat"</string>
<string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detalii despre dispozitiv"</string>
- <string name="adb_device_forget" msgid="193072400783068417">"Ștergeți"</string>
+ <string name="adb_device_forget" msgid="193072400783068417">"Șterge"</string>
<string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Amprenta pentru dispozitiv: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
<string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Conectare nereușită"</string>
- <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Asigurați-vă că ați conectat <xliff:g id="DEVICE_NAME">%1$s</xliff:g> la rețeaua corectă"</string>
- <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Asociați cu dispozitivul"</string>
+ <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Asigură-te că ai conectat <xliff:g id="DEVICE_NAME">%1$s</xliff:g> la rețeaua corectă"</string>
+ <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Asociază cu dispozitivul"</string>
<string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Cod de conectare pentru Wi-Fi"</string>
<string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Asociere nereușită"</string>
- <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Asigurați-vă că dispozitivul este conectat la aceeași rețea."</string>
- <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Asociați dispozitivul prin Wi-Fi scanând un cod QR"</string>
+ <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Asigură-te că dispozitivul este conectat la aceeași rețea."</string>
+ <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Asociază dispozitivul prin Wi-Fi scanând un cod QR"</string>
<string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Se asociază dispozitivul…"</string>
<string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Nu s-a asociat dispozitivul. Codul QR este incorect sau dispozitivul nu este conectat la aceeași rețea."</string>
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresa IP și portul"</string>
- <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scanați codul QR"</string>
- <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Asociați dispozitivul prin Wi-Fi scanând un cod QR"</string>
- <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Conectați-vă la o rețea Wi-Fi"</string>
+ <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scanează codul QR"</string>
+ <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Asociază dispozitivul prin Wi-Fi scanând un cod QR"</string>
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Conectează-te la o rețea Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, remedierea erorilor, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Comandă rapidă pentru raportul de erori"</string>
- <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afișați un buton în meniul de pornire pentru a realiza un raport de erori"</string>
+ <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afișează un buton în meniul de pornire pentru a realiza un raport de erori"</string>
<string name="keep_screen_on" msgid="1187161672348797558">"Activ permanent"</string>
<string name="keep_screen_on_summary" msgid="1510731514101925829">"Ecranul nu va fi inactiv pe durata încărcării"</string>
- <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Activați jurnalul de examinare HCI Bluetooth"</string>
- <string name="bt_hci_snoop_log_summary" msgid="6808538971394092284">"Înregistrați pachetele Bluetooth. (Comutați Bluetooth după modificarea setării)"</string>
+ <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Activează jurnalul de examinare HCI Bluetooth"</string>
+ <string name="bt_hci_snoop_log_summary" msgid="6808538971394092284">"Înregistrează pachetele Bluetooth. (Comutați Bluetooth după modificarea setării)"</string>
<string name="oem_unlock_enable" msgid="5334869171871566731">"Deblocarea OEM"</string>
- <string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Permiteți deblocarea bootloaderului"</string>
- <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Permiteți deblocarea OEM?"</string>
+ <string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Permite deblocarea bootloaderului"</string>
+ <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Permiți deblocarea OEM?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"AVERTISMENT: funcțiile de protecție a dispozitivului nu vor funcționa pe acest dispozitiv cât timp setarea este activată."</string>
- <string name="mock_location_app" msgid="6269380172542248304">"Selectați aplicația pentru locația de testare"</string>
+ <string name="mock_location_app" msgid="6269380172542248304">"Selectează aplicația pentru locația de testare"</string>
<string name="mock_location_app_not_set" msgid="6972032787262831155">"Nicio aplicație setată pentru locația de testare"</string>
<string name="mock_location_app_set" msgid="4706722469342913843">"Aplicația pentru locația de testare: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"Conectare la rețele"</string>
@@ -283,75 +283,75 @@
<string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Randomizarea adresei MAC nepersistente pentru Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"Date mobile permanent active"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Accelerare hardware pentru tethering"</string>
- <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Afișați dispozitivele Bluetooth fără nume"</string>
- <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Dezactivați volumul absolut"</string>
- <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activați Gabeldorsche"</string>
+ <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Afișează dispozitivele Bluetooth fără nume"</string>
+ <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Dezactivează volumul absolut"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activează Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versiunea AVRCP pentru Bluetooth"</string>
- <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selectați versiunea AVRCP pentru Bluetooth"</string>
+ <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selectează versiunea AVRCP pentru Bluetooth"</string>
<string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versiunea MAP pentru Bluetooth"</string>
<string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Selectați versiunea MAP pentru Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec audio Bluetooth"</string>
- <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Declanșați codecul audio Bluetooth\nSelecție"</string>
+ <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Declanșează codecul audio Bluetooth\nSelecție"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Rată de eșantionare audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Declanșați codecul audio Bluetooth\nSelecție: rată de eșantionare"</string>
<string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"O opțiune inactivă înseamnă incompatibilitate cu telefonul sau setul căști-microfon"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Biți audio Bluetooth per eșantion"</string>
- <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Declanșați codecul audio Bluetooth\nSelecție: biți per eșantion"</string>
+ <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Declanșează codecul audio Bluetooth\nSelecție: biți per eșantion"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Modul canal audio Bluetooth"</string>
- <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="2076949781460359589">"Declanșați codecul audio Bluetooth\nSelecție: modul Canal"</string>
+ <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="2076949781460359589">"Declanșează codecul audio Bluetooth\nSelecție: modul Canal"</string>
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3233402355917446304">"Codecul LDAC audio pentru Bluetooth: calitatea redării"</string>
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="7274396574659784285">"Declanșați codecul LDAC audio pentru Bluetooth\nSelecție: calitatea redării"</string>
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="2040810756832027227">"Transmitere în flux: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
<string name="select_private_dns_configuration_title" msgid="7887550926056143018">"DNS privat"</string>
- <string name="select_private_dns_configuration_dialog_title" msgid="3731422918335951912">"Selectați modul DNS privat"</string>
+ <string name="select_private_dns_configuration_dialog_title" msgid="3731422918335951912">"Selectează modul DNS privat"</string>
<string name="private_dns_mode_off" msgid="7065962499349997041">"Dezactivat"</string>
<string name="private_dns_mode_opportunistic" msgid="1947864819060442354">"Automat"</string>
<string name="private_dns_mode_provider" msgid="3619040641762557028">"Nume de gazdă al furnizorului de DNS privat"</string>
- <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"Introduceți numele de gazdă al furnizorului de DNS"</string>
+ <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"Introdu numele de gazdă al furnizorului de DNS"</string>
<string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"Nu s-a putut conecta"</string>
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"Afișați opțiunile pentru certificarea Ecran wireless"</string>
- <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Măriți niv. de înr. prin Wi‑Fi, afișați în fcț. de SSID RSSI în Selectorul Wi‑Fi"</string>
+ <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Mărește nivelul de înregistrare prin Wi‑Fi, afișează după SSID RSSI în Selectorul Wi‑Fi"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Reduce descărcarea bateriei și îmbunătățește performanța rețelei"</string>
<string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Când acest mod este activat, adresa MAC a dispozitivului se poate schimba de fiecare dată când se conectează la o rețea care are activată randomizarea MAC."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"Contorizată"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"Necontorizată"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"Dimensiunile memoriei temporare a jurnalului"</string>
<string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Dimensiuni jurnal / mem. temp. jurnal"</string>
- <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Ștergeți stocarea permanentă a jurnalului?"</string>
- <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Când nu mai monitorizăm folosind jurnalul permanent, trebuie să ștergem datele de jurnal aflate pe dispozitivul dvs."</string>
- <string name="select_logpersist_title" msgid="447071974007104196">"Stocați date jurnal permanent pe dispozitiv"</string>
- <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"Selectați zonele-tampon ale jurnalului de stocat permanent pe dispozitiv"</string>
- <string name="select_usb_configuration_title" msgid="6339801314922294586">"Selectați configurația USB"</string>
- <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"Selectați configurația USB"</string>
- <string name="allow_mock_location" msgid="2102650981552527884">"Permiteți locațiile fictive"</string>
- <string name="allow_mock_location_summary" msgid="179780881081354579">"Permiteți locațiile fictive"</string>
- <string name="debug_view_attributes" msgid="3539609843984208216">"Activați inspectarea atributelor de vizualizare"</string>
+ <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Ștergi stocarea permanentă a jurnalului?"</string>
+ <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Când nu mai monitorizăm folosind jurnalul permanent, trebuie să ștergem datele de jurnal aflate pe dispozitivul tău."</string>
+ <string name="select_logpersist_title" msgid="447071974007104196">"Stochează date jurnal permanent pe dispozitiv"</string>
+ <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"Selectează zonele-tampon ale jurnalului de stocat permanent pe dispozitiv"</string>
+ <string name="select_usb_configuration_title" msgid="6339801314922294586">"Selectează configurația USB"</string>
+ <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"Selectează configurația USB"</string>
+ <string name="allow_mock_location" msgid="2102650981552527884">"Permite locațiile fictive"</string>
+ <string name="allow_mock_location_summary" msgid="179780881081354579">"Permite locațiile fictive"</string>
+ <string name="debug_view_attributes" msgid="3539609843984208216">"Activează inspectarea atributelor de vizualizare"</string>
<string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Păstrați întotdeauna conexiunea de date mobile activată, chiar și atunci când funcția Wi‑Fi este activată (pentru comutarea rapidă între rețele)."</string>
- <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Folosiți accelerarea hardware pentru tethering, dacă este disponibilă"</string>
+ <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Folosește accelerarea hardware pentru tethering, dacă este disponibilă"</string>
<string name="adb_warning_title" msgid="7708653449506485728">"Permiteți remedierea erorilor prin USB?"</string>
<string name="adb_warning_message" msgid="8145270656419669221">"Remedierea erorilor prin USB are exclusiv scopuri de dezvoltare. Utilizați-o pentru a copia date de pe computer pe dispozitiv, pentru a instala aplicații pe dispozitiv fără notificare și pentru a citi datele din jurnale."</string>
- <string name="adbwifi_warning_title" msgid="727104571653031865">"Permiteți remedierea erorilor wireless?"</string>
- <string name="adbwifi_warning_message" msgid="8005936574322702388">"Remedierea erorilor wireless are exclusiv scopuri de dezvoltare. Folosiți-o pentru a copia date de pe computer pe dispozitiv, pentru a instala aplicații pe dispozitiv fără notificare și pentru a citi datele din jurnale."</string>
- <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revocați accesul la remedierea erorilor prin USB de pe toate computerele pe care le-ați autorizat anterior?"</string>
- <string name="dev_settings_warning_title" msgid="8251234890169074553">"Permiteți setările pentru dezvoltare?"</string>
- <string name="dev_settings_warning_message" msgid="37741686486073668">"Aceste setări sunt destinate exclusiv utilizării pentru dezvoltare. Din cauza lor, este posibil ca dispozitivul dvs. și aplicațiile de pe acesta să nu mai funcționeze sau să funcționeze necorespunzător."</string>
+ <string name="adbwifi_warning_title" msgid="727104571653031865">"Permiți remedierea erorilor wireless?"</string>
+ <string name="adbwifi_warning_message" msgid="8005936574322702388">"Remedierea erorilor wireless are exclusiv scopuri de dezvoltare. Folosește-o pentru a copia date de pe computer pe dispozitiv, pentru a instala aplicații pe dispozitiv fără notificare și pentru a citi datele din jurnale."</string>
+ <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revoci accesul la remedierea erorilor prin USB de pe toate computerele pe care le-ai autorizat anterior?"</string>
+ <string name="dev_settings_warning_title" msgid="8251234890169074553">"Permiți setările pentru dezvoltare?"</string>
+ <string name="dev_settings_warning_message" msgid="37741686486073668">"Aceste setări sunt destinate exclusiv utilizării pentru dezvoltare. Din cauza lor, este posibil ca dispozitivul tău și aplicațiile de pe acesta să nu mai funcționeze sau să funcționeze necorespunzător."</string>
<string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Verificați aplicațiile prin USB"</string>
- <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Verificați aplicațiile instalate utilizând ADB/ADT, pentru a detecta un comportament dăunător."</string>
+ <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Verifică aplicațiile instalate utilizând ADB/ADT, pentru a detecta un comportament dăunător."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Vor fi afișate dispozitivele Bluetooth fără nume (numai adresele MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Dezactivează funcția Bluetooth de volum absolut în cazul problemelor de volum apărute la dispozitivele la distanță, cum ar fi volumul mult prea ridicat sau lipsa de control asupra acestuia."</string>
<string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Activează setul de funcții Bluetooth Gabeldorsche."</string>
<string name="enhanced_connectivity_summary" msgid="1576414159820676330">"Activează funcția Conectivitate îmbunătățită."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Aplicație terminal locală"</string>
- <string name="enable_terminal_summary" msgid="2481074834856064500">"Activați aplicația terminal care oferă acces la shell local"</string>
+ <string name="enable_terminal_summary" msgid="2481074834856064500">"Activează aplicația terminal care oferă acces la shell local"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Verificare HDCP"</string>
- <string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"Configurați verific. HDCP"</string>
+ <string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"Configurează verif. HDCP"</string>
<string name="debug_debugging_category" msgid="535341063709248842">"Depanare"</string>
- <string name="debug_app" msgid="8903350241392391766">"Selectați aplicația de depanare"</string>
- <string name="debug_app_not_set" msgid="1934083001283807188">"Nu ați setat o aplicație de depanare"</string>
+ <string name="debug_app" msgid="8903350241392391766">"Selectează aplicația de depanare"</string>
+ <string name="debug_app_not_set" msgid="1934083001283807188">"Nu ai setat o aplicație de depanare"</string>
<string name="debug_app_set" msgid="6599535090477753651">"Aplicație de depanare: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="select_application" msgid="2543228890535466325">"Selectați o aplicație"</string>
+ <string name="select_application" msgid="2543228890535466325">"Selectează o aplicație"</string>
<string name="no_application" msgid="9038334538870247690">"Niciuna"</string>
- <string name="wait_for_debugger" msgid="7461199843335409809">"Așteptați depanatorul"</string>
+ <string name="wait_for_debugger" msgid="7461199843335409809">"Așteaptă depanatorul"</string>
<string name="wait_for_debugger_summary" msgid="6846330006113363286">"Înaintea executării, aplicația așteaptă atașarea depanatorului"</string>
<string name="debug_input_category" msgid="7349460906970849771">"Intrare"</string>
<string name="debug_drawing_category" msgid="5066171112313666619">"Desen"</string>
@@ -362,56 +362,56 @@
<string name="strict_mode_summary" msgid="1838248687233554654">"Iluminare intermitentă la operații lungi pe firul principal"</string>
<string name="pointer_location" msgid="7516929526199520173">"Locația indicatorului"</string>
<string name="pointer_location_summary" msgid="957120116989798464">"Suprapunere care indică date curente pt. atingeri"</string>
- <string name="show_touches" msgid="8437666942161289025">"Afișați atingerile"</string>
- <string name="show_touches_summary" msgid="3692861665994502193">"Afișați feedbackul vizual pentru atingeri"</string>
+ <string name="show_touches" msgid="8437666942161289025">"Afișează atingerile"</string>
+ <string name="show_touches_summary" msgid="3692861665994502193">"Afișează feedbackul vizual pentru atingeri"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"Actualizări suprafețe"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"Iluminarea întregii fereastre la actualizare"</string>
<string name="show_hw_screen_updates" msgid="2021286231267747506">"Afiș. actualizări ecran"</string>
<string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"Iluminare ecrane din ferestre la desenare"</string>
<string name="show_hw_layers_updates" msgid="5268370750002509767">"Actualiz. strat. hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Straturile hardware clipesc verde la actualizare"</string>
- <string name="debug_hw_overdraw" msgid="8944851091008756796">"Depanați suprapunerea"</string>
- <string name="disable_overlays" msgid="4206590799671557143">"Dezactivați suprapun. HW"</string>
- <string name="disable_overlays_summary" msgid="1954852414363338166">"Utilizați mereu GPU pentru compunerea ecranului"</string>
- <string name="simulate_color_space" msgid="1206503300335835151">"Simulați spațiu culoare"</string>
+ <string name="debug_hw_overdraw" msgid="8944851091008756796">"Remediază suprapunerea"</string>
+ <string name="disable_overlays" msgid="4206590799671557143">"Dezactiv. suprapuneri HW"</string>
+ <string name="disable_overlays_summary" msgid="1954852414363338166">"Folosește mereu GPU pentru compunerea ecranului"</string>
+ <string name="simulate_color_space" msgid="1206503300335835151">"Simulează spațiu culoare"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"Monitorizări OpenGL"</string>
<string name="usb_audio_disable_routing" msgid="3367656923544254975">"Dezactivați rutarea audio USB"</string>
<string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Dezact. rutarea automată către perif. audio USB"</string>
- <string name="debug_layout" msgid="1659216803043339741">"Afișați limite aspect"</string>
- <string name="debug_layout_summary" msgid="8825829038287321978">"Afișați limitele clipului, marginile etc."</string>
+ <string name="debug_layout" msgid="1659216803043339741">"Afișează limite aspect"</string>
+ <string name="debug_layout_summary" msgid="8825829038287321978">"Afișează limitele clipului, marginile etc."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Direcție aspect dreapta - stânga"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Direcție obligatorie aspect ecran dreapta - stânga"</string>
- <string name="window_blurs" msgid="6831008984828425106">"Permiteți estompări la nivel de fereastră"</string>
+ <string name="window_blurs" msgid="6831008984828425106">"Permite estompări la nivel de fereastră"</string>
<string name="force_msaa" msgid="4081288296137775550">"Forțați MSAA 4x"</string>
- <string name="force_msaa_summary" msgid="9070437493586769500">"Activați MSAA 4x în aplicațiile OpenGL ES 2.0"</string>
- <string name="show_non_rect_clip" msgid="7499758654867881817">"Remediați decupări nerectangulare"</string>
+ <string name="force_msaa_summary" msgid="9070437493586769500">"Activează MSAA 4x în aplicațiile OpenGL ES 2.0"</string>
+ <string name="show_non_rect_clip" msgid="7499758654867881817">"Remediezi decupări nerectangulare"</string>
<string name="track_frame_time" msgid="522674651937771106">"Profil redare cu HWUI"</string>
- <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Activați nivelurile de depanare GPU"</string>
- <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permiteți încărcarea nivelurilor de depanare GPU pentru aplicațiile de depanare"</string>
- <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Activați înregistrarea detaliată a furnizorilor"</string>
- <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Includeți alte jurnale ale furnizorilor de dispozitive în rapoartele de eroare, care pot conține informații private, folosiți mai multă baterie și/sau mai mult spațiu de stocare."</string>
+ <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Activează nivelurile de depanare GPU"</string>
+ <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite încărcarea nivelurilor de depanare GPU pentru aplicațiile de depanare"</string>
+ <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Activează înregistrarea detaliată a furnizorilor"</string>
+ <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Include alte jurnale ale furnizorilor de dispozitive în rapoartele de eroare, care pot conține informații private, folosește mai multă baterie și/sau mai mult spațiu de stocare."</string>
<string name="window_animation_scale_title" msgid="5236381298376812508">"Scară animație fereastră"</string>
<string name="transition_animation_scale_title" msgid="1278477690695439337">"Scară tranziție animații"</string>
<string name="animator_duration_scale_title" msgid="7082913931326085176">"Scară durată Animator"</string>
<string name="overlay_display_devices_title" msgid="5411894622334469607">"Simulați afișaje secundare"</string>
<string name="debug_applications_category" msgid="5394089406638954196">"Aplicații"</string>
- <string name="immediately_destroy_activities" msgid="1826287490705167403">"Nu păstrați activitățile"</string>
+ <string name="immediately_destroy_activities" msgid="1826287490705167403">"Nu păstra activitățile"</string>
<string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"Elimină activitățile imediat ce utilizatorul le închide"</string>
<string name="app_process_limit_title" msgid="8361367869453043007">"Limită procese fundal"</string>
- <string name="show_all_anrs" msgid="9160563836616468726">"Afișați ANR de fundal"</string>
- <string name="show_all_anrs_summary" msgid="8562788834431971392">"Afișați dialogul Aplicația nu răspunde pentru aplicațiile din fundal"</string>
- <string name="show_notification_channel_warnings" msgid="3448282400127597331">"Afișați avertismentele de pe canalul de notificări"</string>
- <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"Afișați avertisment pe ecran când o aplicație postează o notificare fără canal valid"</string>
- <string name="force_allow_on_external" msgid="9187902444231637880">"Forțați accesul aplicațiilor la stocarea externă"</string>
- <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Permiteți scrierea oricărei aplicații eligibile în stocarea externă, indiferent de valorile manifestului"</string>
+ <string name="show_all_anrs" msgid="9160563836616468726">"Afișează ANR de fundal"</string>
+ <string name="show_all_anrs_summary" msgid="8562788834431971392">"Afișează dialogul Aplicația nu răspunde pentru aplicațiile din fundal"</string>
+ <string name="show_notification_channel_warnings" msgid="3448282400127597331">"Afișează avertismentele de pe canalul de notificări"</string>
+ <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"Afișează avertisment pe ecran când o aplicație postează o notificare fără canal valid"</string>
+ <string name="force_allow_on_external" msgid="9187902444231637880">"Forțează accesul aplicațiilor la stocarea externă"</string>
+ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Permite scrierea oricărei aplicații eligibile în stocarea externă, indiferent de valorile manifestului"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Forțați redimensionarea activităților"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permiteți redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string>
- <string name="enable_freeform_support" msgid="7599125687603914253">"Activați ferestrele cu formă liberă"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Activează ferestrele cu formă liberă"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Activați compatibilitatea pentru ferestrele experimentale cu formă liberă."</string>
<string name="desktop_mode" msgid="2389067840550544462">"Modul desktop"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Parolă backup computer"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"În prezent, backupurile complete pe computer nu sunt protejate"</string>
- <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Atingeți ca să modificați sau să eliminați parola pentru backupurile complete pe desktop"</string>
+ <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Atinge ca să modifici sau să elimini parola pentru backupurile complete pe desktop"</string>
<string name="local_backup_password_toast_success" msgid="4891666204428091604">"A fost setată o parolă de rezervă nouă"</string>
<string name="local_backup_password_toast_confirmation_mismatch" msgid="2994718182129097733">"Parola nouă și confirmarea acesteia nu se potrivesc."</string>
<string name="local_backup_password_toast_validation_failure" msgid="714669442363647122">"Setarea parolei de rezervă a eșuat"</string>
@@ -427,22 +427,22 @@
<item msgid="1282170165150762976">"Culori optimizate pentru conținutul digital"</item>
</string-array>
<string name="inactive_apps_title" msgid="5372523625297212320">"Aplicații în standby"</string>
- <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inactivă. Atingeți pentru a comuta."</string>
- <string name="inactive_app_active_summary" msgid="8047630990208722344">"Activă. Atingeți pentru a comuta."</string>
+ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inactivă. Atinge pentru a comuta."</string>
+ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Activă. Atinge pentru a comuta."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Stare Standby aplicații: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"Setări pentru transcodarea conținutului media"</string>
- <string name="transcode_user_control" msgid="6176368544817731314">"Modificați setările prestabilite de transcodare"</string>
- <string name="transcode_enable_all" msgid="2411165920039166710">"Activați transcodarea"</string>
- <string name="transcode_default" msgid="3784803084573509491">"Presupuneți că aplicațiile acceptă formatele moderne"</string>
- <string name="transcode_notification" msgid="5560515979793436168">"Vedeți notificările privind transcodarea"</string>
- <string name="transcode_disable_cache" msgid="3160069309377467045">"Dezactivați memoria cache pentru transcodare"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"Modifică setările prestabilite de transcodare"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"Activează transcodarea"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"Presupune că aplicațiile acceptă formatele moderne"</string>
+ <string name="transcode_notification" msgid="5560515979793436168">"Vezi notificările privind transcodarea"</string>
+ <string name="transcode_disable_cache" msgid="3160069309377467045">"Dezactivează memoria cache pentru transcodare"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Servicii în curs de funcționare"</string>
- <string name="runningservices_settings_summary" msgid="1046080643262665743">"Vedeți și controlați serviciile care funcționează în prezent"</string>
+ <string name="runningservices_settings_summary" msgid="1046080643262665743">"Vezi și controlează serviciile care funcționează în prezent"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementare WebView"</string>
- <string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Setați implementarea WebView"</string>
- <string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Această opțiune nu mai este validă. Încercați din nou."</string>
+ <string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Setează implementarea WebView"</string>
+ <string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Această opțiune nu mai este validă. Încearcă din nou."</string>
<string name="picture_color_mode" msgid="1013807330552931903">"Modul de culori pentru imagini"</string>
- <string name="picture_color_mode_desc" msgid="151780973768136200">"Folosiți sRGB"</string>
+ <string name="picture_color_mode_desc" msgid="151780973768136200">"Folosește sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Dezactivat"</string>
<string name="daltonizer_mode_monochromacy" msgid="362060873835885014">"Daltonism"</string>
<string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"Deuteranomalie (roșu-verde)"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> până la finalizare"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la finalizare"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Încărcarea este întreruptă"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Necunoscut"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Se încarcă"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Se încarcă rapid"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Se încarcă lent"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Se încarcă wireless"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Se încarcă"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nu se încarcă"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectat, nu se încarcă"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Încărcată"</string>
@@ -511,14 +509,14 @@
<string name="screen_zoom_summary_extremely_large" msgid="1438045624562358554">"Cel mai mare"</string>
<string name="screen_zoom_summary_custom" msgid="3468154096832912210">"Personalizat (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="content_description_menu_button" msgid="6254844309171779931">"Meniu"</string>
- <string name="retail_demo_reset_message" msgid="5392824901108195463">"Introduceți parola pentru a reveni la setările din fabrică în modul demo"</string>
+ <string name="retail_demo_reset_message" msgid="5392824901108195463">"Introdu parola pentru a reveni la setările din fabrică în modul demo"</string>
<string name="retail_demo_reset_next" msgid="3688129033843885362">"Înainte"</string>
- <string name="retail_demo_reset_title" msgid="1866911701095959800">"Trebuie să introduceți o parolă"</string>
+ <string name="retail_demo_reset_title" msgid="1866911701095959800">"Trebuie să introduci o parolă"</string>
<string name="active_input_method_subtypes" msgid="4232680535471633046">"Metode active de introducere de text"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"Folosește limbile sistemului"</string>
<string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"Deschiderea setărilor pentru <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> a eșuat"</string>
- <string name="ime_security_warning" msgid="6547562217880551450">"Această metodă de introducere de text poate culege în întregime textul introdus, inclusiv datele personale, cum ar fi parolele și numerele cardurilor de credit. Metoda provine de la aplicația <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Utilizați această metodă de introducere de text?"</string>
- <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"Notă: după repornire, această aplicație nu poate porni până nu deblocați telefonul"</string>
+ <string name="ime_security_warning" msgid="6547562217880551450">"Această metodă de introducere de text poate culege în întregime textul introdus, inclusiv datele personale, cum ar fi parolele și numerele cardurilor de credit. Metoda provine de la aplicația <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Folosești această metodă de introducere de text?"</string>
+ <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"Notă: după repornire, această aplicație nu poate porni până nu deblochezi telefonul"</string>
<string name="ims_reg_title" msgid="8197592958123671062">"Situația înregistrării IMS"</string>
<string name="ims_reg_status_registered" msgid="884916398194885457">"Înregistrat"</string>
<string name="ims_reg_status_not_registered" msgid="2989287366045704694">"Neînregistrat"</string>
@@ -531,103 +529,103 @@
<string name="okay" msgid="949938843324579502">"OK"</string>
<string name="done" msgid="381184316122520313">"Gata"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarme și mementouri"</string>
- <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permiteți setarea pentru alarme și mementouri"</string>
+ <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permite setarea pentru alarme și mementouri"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarme și mementouri"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permiteți acestei aplicații să stabilească alarme și să planifice acțiuni dependente de timp. Astfel, aplicația poate să ruleze în fundal, fapt care ar putea consuma mai multă baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să stabilească alarme și să planifice acțiuni dependente de timp. Astfel, aplicația poate să ruleze în fundal, fapt care ar putea consuma mai multă baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programare, alarmă, memento, ceas"</string>
- <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activați"</string>
- <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activați Nu deranja"</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activează"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activează Nu deranja"</string>
<string name="zen_mode_settings_summary_off" msgid="3832876036123504076">"Niciodată"</string>
<string name="zen_interruption_level_priority" msgid="5392140786447823299">"Numai cu prioritate"</string>
<string name="zen_mode_and_condition" msgid="8877086090066332516">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
- <string name="zen_alarm_warning_indef" msgid="4146527909616457163">"Dacă nu dezactivați această opțiune înainte, nu veți auzi următoarea alarmă <xliff:g id="WHEN">%1$s</xliff:g>"</string>
- <string name="zen_alarm_warning" msgid="245729928048586280">"Nu veți auzi următoarea alarmă <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+ <string name="zen_alarm_warning_indef" msgid="4146527909616457163">"Dacă nu dezactivezi această opțiune înainte, nu vei auzi următoarea alarmă <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+ <string name="zen_alarm_warning" msgid="245729928048586280">"Nu vei auzi următoarea alarmă <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="3346777418136233330">"la <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="6382760514842998629">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="zen_mode_duration_settings_title" msgid="1553451650289651489">"Durată"</string>
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Întreabă de fiecare dată"</string>
- <string name="zen_mode_forever" msgid="3339224497605461291">"Până când dezactivați"</string>
+ <string name="zen_mode_forever" msgid="3339224497605461291">"Până când dezactivezi"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Chiar acum"</string>
<string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Acest telefon"</string>
<string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Această tabletă"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Acest telefon"</string>
- <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problemă la conectare. Opriți și reporniți dispozitivul."</string>
+ <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problemă la conectare. Oprește și repornește dispozitivul."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispozitiv audio cu fir"</string>
<string name="help_label" msgid="3528360748637781274">"Ajutor și feedback"</string>
<string name="storage_category" msgid="2287342585424631813">"Stocare"</string>
<string name="shared_data_title" msgid="1017034836800864953">"Date la care se permite accesul"</string>
- <string name="shared_data_summary" msgid="5516326713822885652">"Vedeți și modificați datele la care se permite accesul"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Vezi și modifică datele la care se permite accesul"</string>
<string name="shared_data_no_blobs_text" msgid="3108114670341737434">"Nu există date la care se permite accesul pentru acest utilizator."</string>
- <string name="shared_data_query_failure_text" msgid="3489828881998773687">"A apărut o eroare la preluarea datelor la care se permite accesul. Încercați din nou."</string>
+ <string name="shared_data_query_failure_text" msgid="3489828881998773687">"A apărut o eroare la preluarea datelor la care se permite accesul. Încearcă din nou."</string>
<string name="blob_id_text" msgid="8680078988996308061">"ID-ul datelor la care se permite accesul: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
<string name="blob_expires_text" msgid="7882727111491739331">"Expiră pe <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="shared_data_delete_failure_text" msgid="3842701391009628947">"A apărut o eroare la ștergerea datelor la care se permite accesul."</string>
- <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"Nu există închirieri pentru datele la care se permite accesul. Doriți să le ștergeți?"</string>
+ <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"Nu există închirieri pentru datele la care se permite accesul. Vrei să le ștergi?"</string>
<string name="accessor_info_title" msgid="8289823651512477787">"Aplicații care permit accesul la date"</string>
<string name="accessor_no_description_text" msgid="7510967452505591456">"Aplicația nu oferă nicio descriere."</string>
<string name="accessor_expires_text" msgid="4625619273236786252">"Închirierea expiră pe <xliff:g id="DATE">%s</xliff:g>"</string>
- <string name="delete_blob_text" msgid="2819192607255625697">"Ștergeți datele la care se permite accesul"</string>
- <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Sigur ștergeți aceste date la care se permite accesul?"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Șterge datele la care se permite accesul"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Sigur ștergi aceste date la care se permite accesul?"</string>
<string name="user_add_user_item_summary" msgid="5748424612724703400">"Utilizatorii dețin aplicații și materiale proprii"</string>
- <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Puteți restricționa accesul la aplicații și la conținut din contul dvs."</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Poți restricționa accesul la aplicații și la conținut din contul tău"</string>
<string name="user_add_user_item_title" msgid="2394272381086965029">"Utilizator"</string>
<string name="user_add_profile_item_title" msgid="3111051717414643029">"Profil limitat"</string>
- <string name="user_add_user_title" msgid="5457079143694924885">"Adăugați un utilizator nou?"</string>
- <string name="user_add_user_message_long" msgid="1527434966294733380">"Puteți să permiteți accesul la acest dispozitiv altor persoane creând utilizatori suplimentari. Fiecare utilizator are propriul spațiu, pe care îl poate personaliza cu aplicații, imagini de fundal etc. De asemenea, utilizatorii pot ajusta setările dispozitivului, cum ar fi setările pentru Wi-Fi, care îi afectează pe toți ceilalți utilizatori.\n\nDupă ce adăugați un utilizator nou, acesta trebuie să-și configureze spațiul.\n\nOricare dintre utilizatori poate actualiza aplicațiile pentru toți ceilalți utilizatori. Este posibil ca setările de accesibilitate și serviciile să nu se transfere la noul utilizator."</string>
- <string name="user_add_user_message_short" msgid="3295959985795716166">"Când adăugați un utilizator nou, acesta trebuie să-și configureze spațiul.\n\nOrice utilizator poate actualiza aplicațiile pentru toți ceilalți utilizatori."</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Adaugi un utilizator nou?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Poți să permiți accesul la acest dispozitiv altor persoane creând utilizatori suplimentari. Fiecare utilizator are propriul spațiu, pe care îl poate personaliza cu aplicații, imagini de fundal etc. De asemenea, utilizatorii pot ajusta setările dispozitivului, cum ar fi setările pentru Wi-Fi, care îi afectează pe toți ceilalți utilizatori.\n\nDupă ce adaugi un utilizator nou, acesta trebuie să-și configureze spațiul.\n\nOricare dintre utilizatori poate actualiza aplicațiile pentru toți ceilalți utilizatori. Este posibil ca setările de accesibilitate și serviciile să nu se transfere la noul utilizator."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Când adaugi un utilizator nou, acesta trebuie să-și configureze spațiul.\n\nOrice utilizator poate actualiza aplicațiile pentru toți ceilalți utilizatori."</string>
<string name="user_setup_dialog_title" msgid="8037342066381939995">"Configurați utilizatorul acum?"</string>
- <string name="user_setup_dialog_message" msgid="269931619868102841">"Asigurați-vă că utilizatorul are posibilitatea de a prelua dispozitivul și de a-și configura spațiul"</string>
- <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Configurați profilul acum?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Asigură-te că utilizatorul are posibilitatea de a prelua dispozitivul și de a-și configura spațiul"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Configurezi profilul acum?"</string>
<string name="user_setup_button_setup_now" msgid="1708269547187760639">"Configurați acum"</string>
<string name="user_setup_button_setup_later" msgid="8712980133555493516">"Nu acum"</string>
- <string name="user_add_user_type_title" msgid="551279664052914497">"Adăugați"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Adaugă"</string>
<string name="user_new_user_name" msgid="60979820612818840">"Utilizator nou"</string>
<string name="user_new_profile_name" msgid="2405500423304678841">"Profil nou"</string>
<string name="user_info_settings_title" msgid="6351390762733279907">"Info. utilizator"</string>
<string name="profile_info_settings_title" msgid="105699672534365099">"Informații de profil"</string>
- <string name="user_need_lock_message" msgid="4311424336209509301">"Înainte de a putea crea un profil cu permisiuni limitate, va trebui să configurați blocarea ecranului pentru a vă proteja aplicațiile și datele personale."</string>
- <string name="user_set_lock_button" msgid="1427128184982594856">"Configurați blocarea"</string>
- <string name="user_switch_to_user" msgid="6975428297154968543">"Treceți la <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Înainte de a putea crea un profil cu permisiuni limitate, va trebui să configurezi blocarea ecranului pentru a-ți proteja aplicațiile și datele personale."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Configurează blocarea"</string>
+ <string name="user_switch_to_user" msgid="6975428297154968543">"Treci la <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Se creează un utilizator nou…"</string>
<string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Se creează un invitat nou…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Nu s-a creat noul utilizator"</string>
<string name="add_guest_failed" msgid="8074548434469843443">"Nu s-a putut crea un invitat nou"</string>
<string name="user_nickname" msgid="262624187455825083">"Pseudonim"</string>
- <string name="user_add_user" msgid="7876449291500212468">"Adăugați un utilizator"</string>
+ <string name="user_add_user" msgid="7876449291500212468">"Adaugă un utilizator"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adăugați un invitat"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ștergeți invitatul"</string>
- <string name="guest_reset_guest" msgid="6110013010356013758">"Resetați sesiunea pentru invitați"</string>
- <string name="guest_reset_guest_dialog_title" msgid="8047270010895437534">"Resetați invitatul?"</string>
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Resetezi sesiunea pentru invitați"</string>
+ <string name="guest_reset_guest_dialog_title" msgid="8047270010895437534">"Resetezi invitatul?"</string>
<string name="guest_remove_guest_dialog_title" msgid="4548511006624088072">"Excludeți invitatul?"</string>
- <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Resetați"</string>
- <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Eliminați"</string>
+ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Resetează"</string>
+ <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Elimină"</string>
<string name="guest_resetting" msgid="7822120170191509566">"Se resetează invitatul…"</string>
- <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Resetați sesiunea pentru invitați?"</string>
+ <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Resetezi sesiunea pentru invitați?"</string>
<string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Astfel, va începe o nouă sesiune pentru invitați și se vor șterge toate aplicațiile și datele din sesiunea actuală"</string>
- <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Ieșiți din modul pentru invitați?"</string>
+ <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Ieși din modul pentru invitați?"</string>
<string name="guest_exit_dialog_message" msgid="1743218864242719783">"Se vor șterge toate aplicațiile și datele din sesiunea pentru invitați actuală"</string>
<string name="guest_exit_dialog_button" msgid="1736401897067442044">"Ieșiți"</string>
- <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Salvați activitatea invitatului?"</string>
- <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Salvați activitatea din sesiunea actuală sau ștergeți aplicațiile și datele"</string>
- <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Ștergeți"</string>
- <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Salvați"</string>
- <string name="guest_exit_button" msgid="5774985819191803960">"Ieșiți din modul pentru invitați"</string>
- <string name="guest_reset_button" msgid="2515069346223503479">"Resetați sesiunea pentru invitați"</string>
- <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Ieșiți din modul pentru invitați"</string>
+ <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Salvezi activitatea invitatului?"</string>
+ <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Salvează activitatea din sesiunea actuală sau șterge aplicațiile și datele"</string>
+ <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Șterge"</string>
+ <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Salvează"</string>
+ <string name="guest_exit_button" msgid="5774985819191803960">"Ieși din modul pentru invitați"</string>
+ <string name="guest_reset_button" msgid="2515069346223503479">"Resetează sesiunea pentru invitați"</string>
+ <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Ieși din modul pentru invitați"</string>
<string name="guest_notification_ephemeral" msgid="7263252466950923871">"Toate activitățile vor fi șterse la ieșire"</string>
<string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Puteți să salvați sau să ștergeți activitatea la ieșire"</string>
- <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Resetați pentru a șterge acum activitatea din sesiune sau salvați ori ștergeți activitatea la ieșire"</string>
- <string name="user_image_take_photo" msgid="467512954561638530">"Faceți o fotografie"</string>
- <string name="user_image_choose_photo" msgid="1363820919146782908">"Alegeți o imagine"</string>
+ <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Resetează pentru a șterge acum activitatea din sesiune sau salvează ori șterge activitatea la ieșire"</string>
+ <string name="user_image_take_photo" msgid="467512954561638530">"Fă o fotografie"</string>
+ <string name="user_image_choose_photo" msgid="1363820919146782908">"Alege o imagine"</string>
<string name="user_image_photo_selector" msgid="433658323306627093">"Selectați fotografia"</string>
<string name="failed_attempts_now_wiping_device" msgid="4016329172216428897">"Prea multe încercări incorecte. Datele de pe acest dispozitiv vor fi șterse."</string>
<string name="failed_attempts_now_wiping_user" msgid="469060411789668050">"Prea multe încercări incorecte. Acest utilizator va fi șters."</string>
<string name="failed_attempts_now_wiping_profile" msgid="7626589520888963129">"Prea multe încercări incorecte. Acest profil de serviciu și datele sale vor fi șterse."</string>
- <string name="failed_attempts_now_wiping_dialog_dismiss" msgid="2749889771223578925">"Respingeți"</string>
+ <string name="failed_attempts_now_wiping_dialog_dismiss" msgid="2749889771223578925">"Respinge"</string>
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Prestabilit pentru dispozitiv"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Dezactivat"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activat"</string>
- <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Pentru ca modificarea să se aplice, trebuie să reporniți dispozitivul. Reporniți-l acum sau anulați."</string>
+ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Pentru ca modificarea să se aplice, trebuie să repornești dispozitivul. Repornește-l acum sau anulează."</string>
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Căști cu fir"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activat"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Dezactivat"</string>
@@ -658,26 +656,19 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet deconectat."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Apelarea nu este disponibilă."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Oră"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Dată"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Meteo"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calitatea aerului"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Informații artiști"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Controlul locuinței"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
- <string name="avatar_picker_title" msgid="8492884172713170652">"Alegeți o fotografie de profil"</string>
+ <string name="avatar_picker_title" msgid="8492884172713170652">"Alege o fotografie de profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Pictograma prestabilită a utilizatorului"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Tastatură fizică"</string>
- <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Alegeți aspectul tastaturii"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Alege aspectul tastaturii"</string>
<string name="keyboard_layout_default_label" msgid="1997292217218546957">"Prestabilit"</string>
- <string name="turn_screen_on_title" msgid="3266937298097573424">"Activați ecranul"</string>
+ <string name="turn_screen_on_title" msgid="3266937298097573424">"Activează ecranul"</string>
<string name="allow_turn_screen_on" msgid="6194845766392742639">"Permiteți activarea ecranului"</string>
- <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Permiteți unei aplicații să activeze ecranul. Dacă acordați permisiunea, aplicația poate să activeze oricând ecranul, fără intenția dvs. explicită."</string>
- <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Opriți difuzarea <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
- <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Dacă difuzați <xliff:g id="SWITCHAPP">%1$s</xliff:g> sau schimbați rezultatul, difuzarea actuală se va opri"</string>
- <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Difuzați <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
- <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Schimbați rezultatul"</string>
+ <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Permite unei aplicații să activeze ecranul. Dacă acorzi permisiunea, aplicația poate să activeze oricând ecranul, fără intenția ta explicită."</string>
+ <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Oprești difuzarea <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Dacă difuzezi <xliff:g id="SWITCHAPP">%1$s</xliff:g> sau schimbi rezultatul, difuzarea actuală se va opri"</string>
+ <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Difuzează <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
+ <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Schimbă rezultatul"</string>
<string name="back_navigation_animation" msgid="8105467568421689484">"Animații pentru gestul înapoi predictiv"</string>
- <string name="back_navigation_animation_summary" msgid="741292224121599456">"Activați animațiile de sistem pentru gestul înapoi predictiv."</string>
+ <string name="back_navigation_animation_summary" msgid="741292224121599456">"Activează animațiile de sistem pentru gestul înapoi predictiv."</string>
<string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Această setare activează animațiile de sistem pentru animația gesturilor predictive. Necesită setarea valorii true în cazul atributului enableOnBackInvokedCallback pentru fiecare aplicație în fișierul manifest."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index c27b55e..5871fe5 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: зарядка приостановлена"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Идет зарядка"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Быстрая зарядка"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Медленная зарядка"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Беспроводная зарядка"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Зарядка"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Не заряжается"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Подключено, не заряжается"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Батарея заряжена"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Устройство отключено от Ethernet."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Совершение вызовов невозможно."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Время"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Дата"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Погода"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Качество воздуха"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Данные о трансляции"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Автоматизация дома"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"SmartSpace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Выберите фото профиля"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Значок пользователя по умолчанию"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Физическая клавиатура"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index dfc7bf9..80555dc 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"සම්පූර්ණ වීමට <xliff:g id="TIME">%1$s</xliff:g>ක් ඉතිරියි"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - සම්පූර්ණ වීමට <xliff:g id="TIME">%2$s</xliff:g>ක් ඉතිරියි"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය විරාම කර ඇත"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"නොදනී"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ආරෝපණය වෙමින්"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ශීඝ්ර ආරෝපණය"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"සෙමින් ආරෝපණය"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"නොරැහැන්ව ආරෝපණය වේ"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ආරෝපණය වේ"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ආරෝපණය නොවේ"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"සම්බන්ධයි, ආරෝපණය නොවේ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"අරෝපිතයි"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ඊතර්නෙට් විසන්ධි කරන ලදී."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ඊතර්නෙට්."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"ඇමතුම් නැත."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"වේලාව"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"දිනය"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"කාලගුණය"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"වායු ගුණත්වය"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"විකාශ තතු"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"නිවෙස් පාලන"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"ස්මාර්ට් අවකාශය"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"පැතිකඩ පින්තූරයක් තේරීම"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"පෙරනිමි පරිශීලක නිරූපකය"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"භෞතික යතුරු පුවරුව"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 8f435fb..8cb0084 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do úplného nabitia"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Nabíjanie je pozastavené"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Neznáme"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíja sa"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rýchle nabíjanie"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Pomalé nabíjanie"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Nabíja sa bezdrôtovo"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Nabíja sa"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nenabíja sa"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Pripojené, nenabíja sa"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Nabité"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Sieť ethernet je odpojená"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Žiadne volanie."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Čas"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Dátum"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Počasie"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvalita vzduchu"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Informácie o prenose"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Ovládanie domácnosti"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Výber profilovej fotky"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Predvolená ikona používateľa"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fyzická klávesnica"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index b3a29063..8271d02 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Še <xliff:g id="TIME">%1$s</xliff:g> do napolnjenosti"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – še <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Polnjenje je začasno zaustavljeno"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Neznano"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Polnjenje"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hitro polnjenje"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Počasno polnjenje"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Brezžično polnjenje"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Polnjenje"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Se ne polni"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Povezano, se ne polni"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Napolnjeno"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernetna povezava je prekinjena."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Klicanje ni mogoče."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Ura"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Datum"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Vreme"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kakovost zraka"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"O zasedbi"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Nadzor doma"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Hitri pregled"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Izbira profilne slike"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Privzeta ikona uporabnika"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fizična tipkovnica"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 83d95a3..ad6cb5c 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> derisa të mbushet"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të mbushet"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Karikimi është vendosur në pauzë"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"I panjohur"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Po karikohet"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Karikim i shpejtë"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Po karikohet ngadalë"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Po karikohet pa tel"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Po karikohet"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nuk po karikohet"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Lidhur, jo në karikim"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Karikuar"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Lidhja e eternetit u shkëput."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Eternet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Telefonatat nuk ofrohen"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Ora"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Data"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Moti"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Cilësia e ajrit"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Të dhënat e aktorëve"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Kontrollet e shtëpisë"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Zgjidh një fotografi profili"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikona e parazgjedhur e përdoruesit"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Tastiera fizike"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index ea370f6..8345bfa 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до краја пуњења"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до краја пуњења"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Пуњење је заустављено"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Пуни се"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо се пуни"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Споро се пуни"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Бежично пуњење"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Пуњење"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Не пуни се"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Повезано, не пуни се"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Напуњено"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Веза са етернетом је прекинута."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Етернет."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Без позивања."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Време"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Датум"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Време"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Квалитет ваздуха"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Подаци о пребацивању"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Управљање домом"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"SmartSpace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Одаберите слику профила"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Подразумевана икона корисника"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Физичка тастатура"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 970f549..ca46d50d2 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> kvar tills fulladdat"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kvar tills fulladdat"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Laddningen har pausats"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Okänd"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Laddar"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laddas snabbt"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Laddas långsamt"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Laddas trådlöst"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Laddas"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Laddar inte"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ansluten, laddas inte"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Laddat"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet har kopplats från."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Inga anrop."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Tid"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Datum"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Väder"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luftkvalitet"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info om rollistan"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Hemstyrning"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Välj en profilbild"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikon för standardanvändare"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fysiskt tangentbord"</string>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index 53dc6e5..6ed4d5a 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -76,7 +76,7 @@
<item msgid="1963366694959681026">"avrcp16"</item>
</string-array>
<string-array name="bluetooth_map_versions">
- <item msgid="8786402640610987099">"RAMANI YA 1.2 (Chaguomsingi)"</item>
+ <item msgid="8786402640610987099">"MAP 1.2 (Chaguomsingi)"</item>
<item msgid="6817922176194686449">"RAMANI YA 1.3"</item>
<item msgid="3423518690032737851">"RAMANI YA 1.4"</item>
</string-array>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 476daf9..624c466 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -288,8 +288,8 @@
<string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Washa Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Toleo la Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Chagua Toleo la Bluetooth AVRCP"</string>
- <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Toleo la Ramani ya Bluetooth"</string>
- <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Chagua Toleo la Ramani ya Bluetooth"</string>
+ <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Toleo la Bluetooth MAP"</string>
+ <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Chagua Toleo la Bluetooth MAP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Kodeki ya Sauti ya Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Weka Kodeki ya Sauti ya Bluetooth\nUteuzi"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Kiwango cha Sampuli ya Sauti ya Bluetooth"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Zimesalia <xliff:g id="TIME">%1$s</xliff:g> ijae chaji"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> zimesalia ijae chaji"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Imesitisha kuchaji"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Haijulikani"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Inachaji"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Inachaji kwa kasi"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Inachaji pole pole"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Inachaji bila kutumia waya"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Inachaji"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Haichaji"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Imeunganishwa, haichaji"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Imechajiwa"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethaneti imeondolewa."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethaneti."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Huwezi kupiga wala kupokea simu."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Saa"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Tarehe"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Hali ya Hewa"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ubora wa Hewa"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Maelezo ya Wahusika"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Udhibiti wa Vifaa Nyumbani"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Chagua picha ya wasifu"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Aikoni chaguomsingi ya mtumiaji"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Kibodi halisi"</string>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 957bd61..236f899 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -76,7 +76,7 @@
<item msgid="1963366694959681026">"avrcp16"</item>
</string-array>
<string-array name="bluetooth_map_versions">
- <item msgid="8786402640610987099">"MAP 1.2 (இயல்பாக)"</item>
+ <item msgid="8786402640610987099">"MAP 1.2 (இயல்பு)"</item>
<item msgid="6817922176194686449">"MAP 1.3"</item>
<item msgid="3423518690032737851">"MAP 1.4"</item>
</string-array>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 962ec34..84c5a69 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -283,7 +283,7 @@
<string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"வைஃபையில் MAC முகவரியை ரேண்டம் ஆக்குதல்"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"மொபைல் டேட்டாவை எப்போதும் இயக்கத்திலேயே வை"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"வன்பொருள் விரைவுப்படுத்துதல் இணைப்பு முறை"</string>
- <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"பெயர்கள் இல்லாத புளூடூத் சாதனங்களைக் காட்டு"</string>
+ <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"பெயர்கள் இல்லாமல் புளூடூத் சாதனங்களைக் காட்டு"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"அப்சல்யூட் ஒலியளவு அம்சத்தை முடக்கு"</string>
<string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorscheவை இயக்கு"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"புளூடூத் AVRCP பதிப்பு"</string>
@@ -337,7 +337,7 @@
<string name="dev_settings_warning_message" msgid="37741686486073668">"இந்த அமைப்பு மேம்பட்டப் பயன்பாட்டிற்காக மட்டுமே. உங்கள் சாதனம் மற்றும் அதில் உள்ள பயன்பாடுகளைச் சிதைக்கும் அல்லது தவறாகச் செயல்படும் வகையில் பாதிப்பை ஏற்படுத்தும்."</string>
<string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB ஆப்ஸைச் சரிபார்"</string>
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"தீங்கு விளைவிக்கும் செயல்பாட்டை அறிய ADB/ADT மூலம் நிறுவப்பட்ட ஆப்ஸைச் சரிபார்."</string>
- <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"பெயர்கள் இல்லாத புளூடூத் சாதனங்கள் (MAC முகவரிகள் மட்டும்) காட்டப்படும்"</string>
+ <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"பெயர்கள் இல்லாமல் புளூடூத் சாதனங்கள் (MAC முகவரிகள் மட்டும்) காட்டப்படும்"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"மிகவும் அதிகமான ஒலியளவு அல்லது கட்டுப்பாடு இழப்பு போன்ற தொலைநிலைச் சாதனங்களில் ஏற்படும் ஒலி தொடர்பான சிக்கல்கள் இருக்கும் சமயங்களில், புளூடூத் அப்சல்யூட் ஒலியளவு அம்சத்தை முடக்கும்."</string>
<string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"புளூடூத்தின் Gabeldorsche அம்சங்களை இயக்கும்."</string>
<string name="enhanced_connectivity_summary" msgid="1576414159820676330">"மேம்படுத்தப்பட்ட இணைப்புநிலை அம்சத்தை இயக்கும்."</string>
@@ -408,8 +408,7 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், பல சாளரத்திற்கு எல்லா செயல்பாடுகளையும் அளவுமாறக்கூடியதாக அமை."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"குறிப்பிட்ட வடிவமில்லாத சாளரங்களை இயக்கு"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"சாளரங்களை அளவுமாற்ற மற்றும் எங்கும் நகர்த்த அனுமதிக்கும் பரிசோதனைக்குரிய அம்சத்திற்கான ஆதரவை இயக்கு."</string>
- <!-- no translation found for desktop_mode (2389067840550544462) -->
- <skip />
+ <string name="desktop_mode" msgid="2389067840550544462">"டெஸ்க்டாப் பயன்முறை"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"டெஸ்க்டாப் காப்புப்பிரதி கடவுச்சொல்"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"டெஸ்க்டாப்பின் முழு காப்புப்பிரதிகள் தற்போது பாதுகாக்கப்படவில்லை"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"டெஸ்க்டாப்பின் முழுக் காப்புப் பிரதிகளுக்கான கடவுச்சொல்லை மாற்ற அல்லது அகற்ற, தட்டவும்"</string>
@@ -478,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"முழுவதும் சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழுவதும் சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - சார்ஜ் ஏறுவது இடைநிறுத்தப்பட்டுள்ளது"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"அறியப்படாத"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"சார்ஜ் ஆகிறது"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"வேகமாக சார்ஜாகிறது"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"மெதுவாக சார்ஜாகிறது"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"வயரின்றி சார்ஜாகிறது"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"சார்ஜாகிறது"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"சார்ஜ் செய்யப்படவில்லை"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"இணைக்கப்பட்டுள்ளது, சார்ஜாகவில்லை"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"சார்ஜாகிவிட்டது"</string>
@@ -659,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ஈத்தர்நெட் துண்டிக்கப்பட்டது."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ஈதர்நெட்."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"அழைப்பை மேற்கொள்ள முடியவில்லை."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"நேரம்"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"தேதி"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"வானிலை"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"காற்றின் தரம்"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"அலைபரப்புத் தகவல்"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ஹோம் கன்ட்ரோல்கள்"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"சுயவிவரப் படத்தைத் தேர்வுசெய்யுங்கள்"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"இயல்புநிலைப் பயனர் ஐகான்"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"கீபோர்டு"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index cc1f291..5d5ebe7 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -234,7 +234,7 @@
<string name="apn_settings_not_available" msgid="1147111671403342300">"యాక్సెస్ స్థానం పేరు సెట్టింగ్లు ఈ వినియోగదారుకి అందుబాటులో లేవు"</string>
<string name="enable_adb" msgid="8072776357237289039">"USB డీబగ్గింగ్"</string>
<string name="enable_adb_summary" msgid="3711526030096574316">"USB కనెక్ట్ చేయబడినప్పుడు డీబగ్ మోడ్"</string>
- <string name="clear_adb_keys" msgid="3010148733140369917">"USB డీబగ్ ప్రామాణీకరణలను ఉపసంహరించు"</string>
+ <string name="clear_adb_keys" msgid="3010148733140369917">"USB డీబగ్ ప్రామాణీకరణలు ఉపసంహరించండి"</string>
<string name="enable_adb_wireless" msgid="6973226350963971018">"వైర్లెస్ డీబగ్గింగ్"</string>
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi కనెక్ట్ అయి ఉన్నప్పుడు, డీబగ్ మోడ్లో ఉంచు"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"ఎర్రర్"</string>
@@ -283,8 +283,8 @@
<string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Wi‑Fi నిరంతరం కాని MAC ర్యాండమైజేషన్"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"మొబైల్ డేటాను ఎల్లప్పుడూ యాక్టివ్గా ఉంచు"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"టెథెరింగ్ హార్డ్వేర్ యాగ్జిలరేషన్"</string>
- <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"పేర్లు లేని బ్లూటూత్ పరికరాలు చూపించు"</string>
- <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"సంపూర్ణ వాల్యూమ్ను డిజేబుల్ చేయి"</string>
+ <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"పేర్లు లేని బ్లూటూత్ పరికరాలు చూపించండి"</string>
+ <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"సంపూర్ణ వాల్యూమ్ను డిజేబుల్ చేయండి"</string>
<string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorscheను ఎనేబుల్ చేయి"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"బ్లూటూత్ AVRCP వెర్షన్"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"బ్లూటూత్ AVRCP వెర్షన్ను ఎంచుకోండి"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జింగ్ పాజ్ చేయబడింది"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"తెలియదు"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ఛార్జ్ అవుతోంది"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"వేగవంతమైన ఛార్జింగ్"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"నెమ్మదిగా ఛార్జింగ్"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"వైర్లెస్ ఛార్జింగ్"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ఛార్జ్ అవుతోంది"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ఛార్జ్ కావడం లేదు"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"కనెక్ట్ చేయబడింది, ఛార్జ్ చేయబడలేదు"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ఛార్జ్ చేయబడింది"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ఈథర్నెట్ డిస్కనెక్ట్ చేయబడింది."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ఈథర్నెట్."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"కాలింగ్ మోడ్ ఆఫ్లో ఉంది."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"సమయం"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"తేదీ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"వాతావరణం"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"గాలి క్వాలిటీ"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"కాస్ట్ సమాచారం"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"హోమ్ కంట్రోల్స్"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"స్మార్ట్స్పేస్"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ప్రొఫైల్ ఫోటోను ఎంచుకోండి"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ఆటోమేటిక్ సెట్టింగ్ యూజర్ చిహ్నం"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"భౌతిక కీబోర్డ్"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 65744b2..c08a755 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -288,8 +288,8 @@
<string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"เปิดใช้ Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"เวอร์ชันของบลูทูธ AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"เลือกเวอร์ชันของบลูทูธ AVRCP"</string>
- <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"เวอร์ชัน MAP ของบลูทูธ"</string>
- <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"เลือกเวอร์ชัน MAP ของบลูทูธ"</string>
+ <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"เวอร์ชันของบลูทูธ MAP"</string>
+ <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"เลือกเวอร์ชันของบลูทูธ MAP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ตัวแปลงสัญญาณเสียงบลูทูธ"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ทริกเกอร์การเลือกตัวแปลงรหัส\nเสียงบลูทูธ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"อัตราตัวอย่างเสียงบลูทูธ"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"อีก <xliff:g id="TIME">%1$s</xliff:g>จึงจะเต็ม"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - อีก <xliff:g id="TIME">%2$s</xliff:g> จึงจะเต็ม"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - การชาร์จหยุดชั่วคราว"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"ไม่ทราบ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"กำลังชาร์จ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"กำลังชาร์จอย่างเร็ว"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"กำลังชาร์จอย่างช้าๆ"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"กำลังชาร์จแบบไร้สาย"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"กำลังชาร์จ"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ไม่ได้ชาร์จ"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"เชื่อมต่ออยู่ ไม่ได้ชาร์จ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ชาร์จแล้ว"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ยกเลิกการเชื่อมต่ออีเทอร์เน็ตแล้ว"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"อีเทอร์เน็ต"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"ไม่มีการโทร"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"เวลา"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"วันที่"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"สภาพอากาศ"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"คุณภาพอากาศ"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ข้อมูลแคสต์"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ระบบควบคุมอุปกรณ์ในบ้าน"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"เลือกรูปโปรไฟล์"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ไอคอนผู้ใช้เริ่มต้น"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"แป้นพิมพ์จริง"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 6b1411d..b219fd5 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> na lang bago mapuno"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> na lang bago mapuno"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Naka-pause ang pag-charge"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Hindi Kilala"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Nagcha-charge"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mabilis na charge"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Mabagal na charge"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Wireless na nagcha-charge"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Nagcha-charge"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Hindi nagcha-charge"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Nakakonekta, hindi nagcha-charge"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Nasingil"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Nadiskonekta ang Ethernet."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Hindi makakatawag."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Oras"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Petsa"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Lagay ng Panahon"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kalidad ng Hangin"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Impormasyon ng Cast"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Pumili ng larawan sa profile"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icon ng default na user"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Pisikal na keyboard"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index af51c68..09c380b 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Tamamen şarj olmasına <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tamamen şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: Şarj işlemi duraklatıldı"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Bilinmiyor"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Şarj oluyor"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hızlı şarj oluyor"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Yavaş şarj oluyor"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Kablosuz şarj oluyor"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Şarj Etme"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Şarj olmuyor"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Bağlandı, şarj olmuyor"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Şarj oldu"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet bağlantısı kesildi."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Çağrı yok."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Saat"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Tarih"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Hava durumu"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Hava Kalitesi"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Yayın Bilgisi"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Ev Kontrolleri"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Profil fotoğrafı seçin"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Varsayılan kullanıcı simgesi"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fiziksel klavye"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 8e102e4..cac7269 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до повного заряду"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Заряджання призупинено"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Невідомо"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Заряджається"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Швидке заряджання"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Повільне заряджання"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Бездротове заряджання"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Заряджання"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Не заряджається"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Підключено, не заряджається"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Заряджено"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet відключено."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Виклики недоступні."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Час"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Дата"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Погода"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Якість повітря"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Акторський склад"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Автоматизація дому"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Виберіть зображення профілю"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Значок користувача за умовчанням"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Фізична клавіатура"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 9e22b90..a956d0c 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -232,9 +232,9 @@
<string name="vpn_settings_not_available" msgid="2894137119965668920">"VPN ترتیبات اس صارف کیلئے دستیاب نہیں ہیں"</string>
<string name="tethering_settings_not_available" msgid="266821736434699780">"ٹیدرنگ ترتیبات اس صارف کیلئے دستیاب نہیں ہیں"</string>
<string name="apn_settings_not_available" msgid="1147111671403342300">"رسائی کی جگہ کے نام کی ترتیبات اس صارف کیلئے دستیاب نہیں ہیں"</string>
- <string name="enable_adb" msgid="8072776357237289039">"USB ڈیبگ کرنا"</string>
+ <string name="enable_adb" msgid="8072776357237289039">"USB ڈیبگنگ"</string>
<string name="enable_adb_summary" msgid="3711526030096574316">"USB مربوط ہونے پر ڈيبگ کرنے کی وضع"</string>
- <string name="clear_adb_keys" msgid="3010148733140369917">"USB ڈیبگ کرنے کی اجازت دہندگیوں کو منسوخ کریں"</string>
+ <string name="clear_adb_keys" msgid="3010148733140369917">"USB ڈیبگنگ کی اجازت دہندگیوں کو منسوخ کریں"</string>
<string name="enable_adb_wireless" msgid="6973226350963971018">"وائرلیس ڈیبگنگ"</string>
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi سے منسلک ہونے پر ڈیبگ موڈ"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"خرابی"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"مکمل چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"مکمل چارج ہونے میں <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - چارجنگ موقوف ہے"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"نامعلوم"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"چارج ہو رہا ہے"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"تیزی سے چارج ہو رہا ہے"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"آہستہ چارج ہو رہی ہے"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"وائرلیس طریقے سے چارج ہو رہی ہے"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"چارج ہو رہی ہے"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"چارج نہیں ہو رہا ہے"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"منسلک ہے، چارج نہیں ہو رہی ہے"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"چارج ہو گئی"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ایتھرنیٹ منقطع ہے۔"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"ایتھرنیٹ۔"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"کوئی کالنگ نہیں ہے۔"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"وقت"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"تاریخ"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"موسم"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"ہوا کا معیار"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"کاسٹ کرنے کی معلومات"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ہوم کنٹرولز"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"پروفائل کی تصویر منتخب کریں"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ڈیفالٹ صارف کا آئیکن"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"فزیکل کی بورڈ"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index c66b6cf..656d590 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Toʻlishiga <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Toʻlishiga <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quvvatlash pauza qilindi"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Noma’lum"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Quvvat olmoqda"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Tezkor quvvat olmoqda"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Sekin quvvat olmoqda"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Simsiz quvvat olmoqda"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Quvvat olmoqda"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Quvvat olmayapti"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ulangan, quvvat olmayapti"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Quvvat oldi"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Qurilma Ethernet tarmog‘idan uzildi."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Chaqiruv imkonsiz."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Vaqt"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Sana"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Ob-havo"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Havo sifati"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Translatsiya axboroti"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Uy boshqaruvi"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Profil rasmini tanlash"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Foydalanuvchining standart belgisi"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Tashqi klaviatura"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index ed78108..f868c69 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> nữa là pin đầy"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là pin đầy"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Đã tạm dừng sạc"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Không xác định"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Đang sạc"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Đang sạc nhanh"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Đang sạc chậm"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Đang sạc không dây"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Đang sạc"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Hiện không sạc"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Đã kết nối nhưng chưa sạc"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Đã sạc"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Đã ngắt kết nối Ethernet."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Không thể gọi điện."</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Giờ"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Ngày"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Thời tiết"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Chất lượng không khí"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Thông tin về dàn nghệ sĩ"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Điều khiển nhà"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Chọn một ảnh hồ sơ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Biểu tượng người dùng mặc định"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Bàn phím thực"</string>
@@ -677,7 +668,7 @@
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Nếu bạn phát <xliff:g id="SWITCHAPP">%1$s</xliff:g> hoặc thay đổi đầu ra, phiên truyền phát hiện tại sẽ dừng"</string>
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Phát <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
<string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Thay đổi đầu ra"</string>
- <string name="back_navigation_animation" msgid="8105467568421689484">"Ảnh động vuốt ngược dự đoán"</string>
- <string name="back_navigation_animation_summary" msgid="741292224121599456">"Cho phép sử dụng ảnh động hệ thống cho chức năng vuốt ngược dự đoán."</string>
+ <string name="back_navigation_animation" msgid="8105467568421689484">"Ảnh xem trước thao tác quay lại"</string>
+ <string name="back_navigation_animation_summary" msgid="741292224121599456">"Bật ảnh của hệ thống để xem trước thao tác quay lại"</string>
<string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Cài đặt này cho phép sử dụng ảnh động hệ thống cho ảnh động cử chỉ dự đoán. Nó yêu cầu cài đặt cho mỗi ứng dụng chuyển enableOnBackInvokedCallback thành lệnh true trong tệp kê khai."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index e1e50ae..a9ca33d 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -338,7 +338,7 @@
<string name="verify_apps_over_usb_title" msgid="6031809675604442636">"通过 USB 验证应用"</string>
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"检查通过 ADB/ADT 安装的应用是否存在有害行为。"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"系统将显示没有名称(只有 MAC 地址)的蓝牙设备"</string>
- <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"停用蓝牙绝对音量功能,即可避免在连接到远程设备时出现音量问题(例如音量高得让人无法接受或无法控制音量等)。"</string>
+ <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"停用蓝牙绝对音量功能,以防在连接到远程设备时出现音量问题(例如音量高得让人无法接受或无法控制音量等)。"</string>
<string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"启用“蓝牙 Gabeldorsche”功能堆栈。"</string>
<string name="enhanced_connectivity_summary" msgid="1576414159820676330">"启用增强连接性功能。"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"本地终端"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"还需<xliff:g id="TIME">%1$s</xliff:g>充满"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充电已暂停"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"正在充电"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充电"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"正在慢速充电"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"正在无线充电"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"正在充电"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"未在充电"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"已连接,未充电"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"已充满电"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"以太网已断开连接。"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"以太网。"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"不启用通话。"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"时间"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"日期"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"天气"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"空气质量"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"投放信息"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"家居控制"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"SmartSpace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"选择个人资料照片"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"默认用户图标"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"实体键盘"</string>
@@ -677,7 +668,7 @@
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"如果广播“<xliff:g id="SWITCHAPP">%1$s</xliff:g>”的内容或更改输出来源,当前的广播就会停止"</string>
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"广播“<xliff:g id="SWITCHAPP">%1$s</xliff:g>”的内容"</string>
<string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"更改输出来源"</string>
- <string name="back_navigation_animation" msgid="8105467568421689484">"预测性返回手势动画"</string>
- <string name="back_navigation_animation_summary" msgid="741292224121599456">"启用系统动画作为预测性返回手势动画。"</string>
+ <string name="back_navigation_animation" msgid="8105467568421689484">"预见式返回动画"</string>
+ <string name="back_navigation_animation_summary" msgid="741292224121599456">"启用系统动画作为预见式返回动画。"</string>
<string name="back_navigation_animation_dialog" msgid="8696966520944625596">"此设置将启用系统动画作为预测性手势动画。这要求在清单文件中将单个应用的 enableOnBackInvokedCallback 设为 true。"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 1a6648f..4c0d6bc 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -408,7 +408,7 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"在任何資訊清單值下,允許系統配合多重視窗環境調整所有活動的尺寸。"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"啟用自由形態視窗"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"啟用實驗版自由形態視窗的支援功能。"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"電腦模式"</string>
+ <string name="desktop_mode" msgid="2389067840550544462">"桌面模式"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"桌面電腦備份密碼"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"桌面電腦的完整備份目前未受保護"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"輕按即可變更或移除桌面電腦完整備份的密碼"</string>
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>後充滿電"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充滿電"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - 已暫停充電"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"慢速充電中"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"無線充電中"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"正在充電"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"非充電中"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"已連接,非充電中"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"已充滿電"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"以太網連接中斷。"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"以太網絡。"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"不啟用通話。"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"時間"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"日期"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"天氣"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"空氣質素"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"投放資料"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"智能家居"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"選擇個人檔案相片"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"預設使用者圖示"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"實體鍵盤"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 991dcad..ba0eee2 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>後充飽"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - 已暫停充電"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"慢速充電中"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"正在進行無線充電"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"充電中"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"非充電中"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"已連接,尚未充電"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"充電完成"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"未連上乙太網路。"</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"乙太網路。"</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"不顯示在螢幕上。"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"時間"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"日期"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"天氣"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"空氣品質"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"演出者資訊"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"居家控制系統"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"智慧空間"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"選擇個人資料相片"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"預設使用者圖示"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"實體鍵盤"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index f1f736c7..8c68b93 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -477,15 +477,13 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> okusele kuze kugcwale"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> okusele kuze kugcwale"</string>
- <!-- no translation found for power_charging_limited (6971664137170239141) -->
- <skip />
+ <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ukushaja kumisiwe okwesikhashana"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Akwaziwa"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Iyashaja"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ishaja ngokushesha"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Ishaja kancane"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Iyashaja ngaphandle kwentambo"</string>
- <!-- no translation found for battery_info_status_charging_dock (8573274094093364791) -->
- <skip />
+ <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Iyashaja"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Ayishaji"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ixhunyiwe, ayishaji"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Kushajiwe"</string>
@@ -658,13 +656,6 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"I-Ethernet inqanyuliwe."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"I-Ethernet."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"Akukho ukwenza ikholi"</string>
- <string name="dream_complication_title_time" msgid="701747800712893499">"Isikhathi"</string>
- <string name="dream_complication_title_date" msgid="8661176085446135789">"Ilanga"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Isimo sezulu"</string>
- <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ikhwalithi Yomoya"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Ulwazi Lokusakaza"</string>
- <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Izilawuli Zasekhaya"</string>
- <string name="dream_complication_title_smartspace" msgid="4197829945636051120">"I-Smartspace"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Khetha isithombe sephrofayela"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Isithonjana somsebenzisi sokuzenzakalelayo"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Ikhibhodi ephathekayo"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 0e60caa..949bbfb 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1601,21 +1601,6 @@
<!-- Content description of the no calling for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_no_calling">No calling.</string>
- <!-- Screensaver overlay which displays the time. [CHAR LIMIT=20] -->
- <string name="dream_complication_title_time">Time</string>
- <!-- Screensaver overlay which displays the date. [CHAR LIMIT=20] -->
- <string name="dream_complication_title_date">Date</string>
- <!-- Screensaver overlay which displays the weather. [CHAR LIMIT=20] -->
- <string name="dream_complication_title_weather">Weather</string>
- <!-- Screensaver overlay which displays air quality. [CHAR LIMIT=20] -->
- <string name="dream_complication_title_aqi">Air Quality</string>
- <!-- Screensaver overlay which displays cast info. [CHAR LIMIT=20] -->
- <string name="dream_complication_title_cast_info">Cast Info</string>
- <!-- Screensaver overlay which displays home controls. [CHAR LIMIT=20] -->
- <string name="dream_complication_title_home_controls">Home Controls</string>
- <!-- Screensaver overlay which displays smartspace. [CHAR LIMIT=20] -->
- <string name="dream_complication_title_smartspace">Smartspace</string>
-
<!-- Title for a screen allowing the user to choose a profile picture. [CHAR LIMIT=NONE] -->
<string name="avatar_picker_title">Choose a profile picture</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 62c83cf..51812f0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -367,8 +367,14 @@
if (bondState == BluetoothDevice.BOND_NONE) {
// Check if we need to remove other Coordinated set member devices / Hearing Aid
// devices
+ if (DEBUG) {
+ Log.d(TAG, "BondStateChangedHandler: cachedDevice.getGroupId() = "
+ + cachedDevice.getGroupId() + ", cachedDevice.getHiSyncId()= "
+ + cachedDevice.getHiSyncId());
+ }
if (cachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID
|| cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
+ Log.d(TAG, "BondStateChangedHandler: Start onDeviceUnpaired");
mDeviceManager.onDeviceUnpaired(cachedDevice);
}
int reason = intent.getIntExtra(BluetoothDevice.EXTRA_UNBOND_REASON,
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 32d5b78..3ca94db 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -1431,11 +1431,10 @@
* first connected device in the coordinated set, and then switch the content of the main
* device and member devices.
*
- * @param prevMainDevice the previous Main device, it will be added into the member device set.
- * @param newMainDevice the new Main device, it will be removed from the member device set.
+ * @param newMainDevice the new Main device which is from the previous main device's member
+ * list.
*/
- public void switchMemberDeviceContent(CachedBluetoothDevice prevMainDevice,
- CachedBluetoothDevice newMainDevice) {
+ public void switchMemberDeviceContent(CachedBluetoothDevice newMainDevice) {
// Backup from main device
final BluetoothDevice tmpDevice = mDevice;
final short tmpRssi = mRssi;
@@ -1444,8 +1443,7 @@
mDevice = newMainDevice.mDevice;
mRssi = newMainDevice.mRssi;
mJustDiscovered = newMainDevice.mJustDiscovered;
- addMemberDevice(prevMainDevice);
- mMemberDevices.remove(newMainDevice);
+
// Set sub device from backup
newMainDevice.mDevice = tmpDevice;
newMainDevice.mRssi = tmpRssi;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index cd3242a..26a2080 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -17,6 +17,7 @@
package com.android.settingslib.bluetooth;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
@@ -317,12 +318,14 @@
}
public synchronized void onDeviceUnpaired(CachedBluetoothDevice device) {
+ device.setGroupId(BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
CachedBluetoothDevice mainDevice = mCsipDeviceManager.findMainDevice(device);
final Set<CachedBluetoothDevice> memberDevices = device.getMemberDevice();
if (!memberDevices.isEmpty()) {
// Main device is unpaired, to unpair the member device
for (CachedBluetoothDevice memberDevice : memberDevices) {
memberDevice.unpair();
+ memberDevice.setGroupId(BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
device.removeMemberDevice(memberDevice);
}
} else if (mainDevice != null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
index fc70ba4..9b38238 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
@@ -231,7 +231,7 @@
// When both LE Audio devices are disconnected, receiving member device
// connection. To switch content and dispatch to notify UI change
mBtManager.getEventManager().dispatchDeviceRemoved(mainDevice);
- mainDevice.switchMemberDeviceContent(mainDevice, cachedDevice);
+ mainDevice.switchMemberDeviceContent(cachedDevice);
mainDevice.refresh();
// It is necessary to do remove and add for updating the mapping on
// preference and device
@@ -255,10 +255,11 @@
for (CachedBluetoothDevice device: memberSet) {
if (device.isConnected()) {
+ log("set device: " + device + " as the main device");
// Main device is disconnected and sub device is connected
// To copy data from sub device to main device
mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
- cachedDevice.switchMemberDeviceContent(device, cachedDevice);
+ cachedDevice.switchMemberDeviceContent(device);
cachedDevice.refresh();
// It is necessary to do remove and add for updating the mapping on
// preference and device
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index 2258617..1606540 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -17,7 +17,6 @@
package com.android.settingslib.dream;
import android.annotation.IntDef;
-import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -32,17 +31,14 @@
import android.provider.Settings;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
-import android.text.TextUtils;
import android.util.Log;
-import com.android.settingslib.R;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Comparator;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -64,18 +60,21 @@
public String toString() {
StringBuilder sb = new StringBuilder(DreamInfo.class.getSimpleName());
sb.append('[').append(caption);
- if (isActive)
+ if (isActive) {
sb.append(",active");
+ }
sb.append(',').append(componentName);
- if (settingsComponentName != null)
+ if (settingsComponentName != null) {
sb.append("settings=").append(settingsComponentName);
+ }
return sb.append(']').toString();
}
}
@Retention(RetentionPolicy.SOURCE)
@IntDef({WHILE_CHARGING, WHILE_DOCKED, EITHER, NEVER})
- public @interface WhenToDream {}
+ public @interface WhenToDream {
+ }
public static final int WHILE_CHARGING = 0;
public static final int WHILE_DOCKED = 1;
@@ -96,7 +95,8 @@
COMPLICATION_TYPE_SMARTSPACE
})
@Retention(RetentionPolicy.SOURCE)
- public @interface ComplicationType {}
+ public @interface ComplicationType {
+ }
public static final int COMPLICATION_TYPE_TIME = 1;
public static final int COMPLICATION_TYPE_DATE = 2;
@@ -114,8 +114,6 @@
private final boolean mDreamsActivatedOnDockByDefault;
private final Set<ComponentName> mDisabledDreams;
private final Set<Integer> mSupportedComplications;
- private final Set<Integer> mDefaultEnabledComplications;
-
private static DreamBackend sInstance;
public static DreamBackend getInstance(Context context) {
@@ -147,13 +145,6 @@
com.android.internal.R.array.config_supportedDreamComplications))
.boxed()
.collect(Collectors.toSet());
-
- mDefaultEnabledComplications = Arrays.stream(resources.getIntArray(
- com.android.internal.R.array.config_dreamComplicationsEnabledByDefault))
- .boxed()
- // A complication can only be enabled by default if it is also supported.
- .filter(mSupportedComplications::contains)
- .collect(Collectors.toSet());
}
public List<DreamInfo> getDreamInfos() {
@@ -251,11 +242,12 @@
return null;
}
- public @WhenToDream int getWhenToDreamSetting() {
+ @WhenToDream
+ public int getWhenToDreamSetting() {
return isActivatedOnDock() && isActivatedOnSleep() ? EITHER
: isActivatedOnDock() ? WHILE_DOCKED
- : isActivatedOnSleep() ? WHILE_CHARGING
- : NEVER;
+ : isActivatedOnSleep() ? WHILE_CHARGING
+ : NEVER;
}
public void setWhenToDream(@WhenToDream int whenToDream) {
@@ -283,22 +275,24 @@
}
}
- /** Returns whether a particular complication is enabled */
- public boolean isComplicationEnabled(@ComplicationType int complication) {
- return getEnabledComplications().contains(complication);
- }
-
/** Gets all complications which have been enabled by the user. */
public Set<Integer> getEnabledComplications() {
- final String enabledComplications = Settings.Secure.getString(
+ return getComplicationsEnabled() ? mSupportedComplications : Collections.emptySet();
+ }
+
+ /** Sets complication enabled state. */
+ public void setComplicationsEnabled(boolean enabled) {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.SCREENSAVER_COMPLICATIONS_ENABLED, enabled ? 1 : 0);
+ }
+
+ /**
+ * Gets whether complications are enabled on this device
+ */
+ public boolean getComplicationsEnabled() {
+ return Settings.Secure.getInt(
mContext.getContentResolver(),
- Settings.Secure.SCREENSAVER_ENABLED_COMPLICATIONS);
-
- if (enabledComplications == null) {
- return mDefaultEnabledComplications;
- }
-
- return parseFromString(enabledComplications);
+ Settings.Secure.SCREENSAVER_COMPLICATIONS_ENABLED, 1) == 1;
}
/** Gets all dream complications which are supported on this device. **/
@@ -306,77 +300,6 @@
return mSupportedComplications;
}
- /**
- * Enables or disables a particular dream complication.
- *
- * @param complicationType The dream complication to be enabled/disabled.
- * @param value If true, the complication is enabled. Otherwise it is disabled.
- */
- public void setComplicationEnabled(@ComplicationType int complicationType, boolean value) {
- if (!mSupportedComplications.contains(complicationType)) return;
-
- Set<Integer> enabledComplications = getEnabledComplications();
- if (value) {
- enabledComplications.add(complicationType);
- } else {
- enabledComplications.remove(complicationType);
- }
-
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.SCREENSAVER_ENABLED_COMPLICATIONS,
- convertToString(enabledComplications));
- }
-
- /**
- * Gets the title of a particular complication type to be displayed to the user. If there
- * is no title, null is returned.
- */
- @Nullable
- public CharSequence getComplicationTitle(@ComplicationType int complicationType) {
- int res = 0;
- switch (complicationType) {
- case COMPLICATION_TYPE_TIME:
- res = R.string.dream_complication_title_time;
- break;
- case COMPLICATION_TYPE_DATE:
- res = R.string.dream_complication_title_date;
- break;
- case COMPLICATION_TYPE_WEATHER:
- res = R.string.dream_complication_title_weather;
- break;
- case COMPLICATION_TYPE_AIR_QUALITY:
- res = R.string.dream_complication_title_aqi;
- break;
- case COMPLICATION_TYPE_CAST_INFO:
- res = R.string.dream_complication_title_cast_info;
- break;
- case COMPLICATION_TYPE_HOME_CONTROLS:
- res = R.string.dream_complication_title_home_controls;
- break;
- case COMPLICATION_TYPE_SMARTSPACE:
- res = R.string.dream_complication_title_smartspace;
- break;
- default:
- return null;
- }
- return mContext.getString(res);
- }
-
- private static String convertToString(Set<Integer> set) {
- return set.stream()
- .map(String::valueOf)
- .collect(Collectors.joining(","));
- }
-
- private static Set<Integer> parseFromString(String string) {
- if (TextUtils.isEmpty(string)) {
- return new HashSet<>();
- }
- return Arrays.stream(string.split(","))
- .map(Integer::parseInt)
- .collect(Collectors.toSet());
- }
-
public boolean isEnabled() {
return getBoolean(Settings.Secure.SCREENSAVER_ENABLED, mDreamsEnabledByDefault);
}
@@ -416,10 +339,11 @@
public void setActiveDream(ComponentName dream) {
logd("setActiveDream(%s)", dream);
- if (mDreamManager == null)
+ if (mDreamManager == null) {
return;
+ }
try {
- ComponentName[] dreams = { dream };
+ ComponentName[] dreams = {dream};
mDreamManager.setDreamComponents(dream == null ? null : dreams);
} catch (RemoteException e) {
Log.w(TAG, "Failed to set active dream to " + dream, e);
@@ -427,8 +351,9 @@
}
public ComponentName getActiveDream() {
- if (mDreamManager == null)
+ if (mDreamManager == null) {
return null;
+ }
try {
ComponentName[] dreams = mDreamManager.getDreamComponents();
return dreams != null && dreams.length > 0 ? dreams[0] : null;
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/OWNERS b/packages/SettingsLib/src/com/android/settingslib/media/OWNERS
new file mode 100644
index 0000000..d40f322
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/OWNERS
@@ -0,0 +1,2 @@
+# Default reviewers for this and subdirectories.
+shaoweishen@google.com
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index bef1d9c..62552f91 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -25,6 +25,7 @@
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
@@ -518,7 +519,8 @@
*/
@Test
public void onDeviceUnpaired_unpairCsipMainDevice() {
- when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+ when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
cachedDevice1.setGroupId(1);
@@ -527,7 +529,12 @@
// Call onDeviceUnpaired for the one in mCachedDevices.
mCachedDeviceManager.onDeviceUnpaired(cachedDevice1);
+
verify(mDevice2).removeBond();
+ assertThat(cachedDevice1.getGroupId()).isEqualTo(
+ BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
+ assertThat(cachedDevice2.getGroupId()).isEqualTo(
+ BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
}
/**
@@ -536,6 +543,7 @@
@Test
public void onDeviceUnpaired_unpairCsipSubDevice() {
when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
cachedDevice1.setGroupId(1);
@@ -544,7 +552,10 @@
// Call onDeviceUnpaired for the one in mCachedDevices.
mCachedDeviceManager.onDeviceUnpaired(cachedDevice2);
+
verify(mDevice1).removeBond();
+ assertThat(cachedDevice2.getGroupId()).isEqualTo(
+ BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
}
/**
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 76c066c..79e9938 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -1050,4 +1050,23 @@
assertThat(mCachedDevice.mDrawableCache.size()).isEqualTo(0);
}
+
+ @Test
+ public void switchMemberDeviceContent_switchMainDevice_switchesSuccessful() {
+ mCachedDevice.mRssi = RSSI_1;
+ mCachedDevice.mJustDiscovered = JUSTDISCOVERED_1;
+ mSubCachedDevice.mRssi = RSSI_2;
+ mSubCachedDevice.mJustDiscovered = JUSTDISCOVERED_2;
+ mCachedDevice.addMemberDevice(mSubCachedDevice);
+
+ mCachedDevice.switchMemberDeviceContent(mSubCachedDevice);
+
+ assertThat(mCachedDevice.mRssi).isEqualTo(RSSI_2);
+ assertThat(mCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_2);
+ assertThat(mCachedDevice.mDevice).isEqualTo(mSubDevice);
+ assertThat(mSubCachedDevice.mRssi).isEqualTo(RSSI_1);
+ assertThat(mSubCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
+ assertThat(mSubCachedDevice.mDevice).isEqualTo(mDevice);
+ assertThat(mCachedDevice.getMemberDevice().contains(mSubCachedDevice)).isTrue();
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/dream/DreamBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/dream/DreamBackendTest.java
index 86f7850..52b9227 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/dream/DreamBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/dream/DreamBackendTest.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
@@ -34,29 +35,35 @@
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowSettings;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowSettings.ShadowSecure.class})
public final class DreamBackendTest {
private static final int[] SUPPORTED_DREAM_COMPLICATIONS = {1, 2, 3};
- private static final int[] DEFAULT_DREAM_COMPLICATIONS = {1, 3, 4};
+ private static final List<Integer> SUPPORTED_DREAM_COMPLICATIONS_LIST = Arrays.stream(
+ SUPPORTED_DREAM_COMPLICATIONS).boxed().collect(
+ Collectors.toList());
@Mock
private Context mContext;
+ @Mock
+ private ContentResolver mMockResolver;
private DreamBackend mBackend;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getApplicationContext()).thenReturn(mContext);
+ when(mContext.getContentResolver()).thenReturn(mMockResolver);
final Resources res = mock(Resources.class);
when(mContext.getResources()).thenReturn(res);
when(res.getIntArray(
com.android.internal.R.array.config_supportedDreamComplications)).thenReturn(
SUPPORTED_DREAM_COMPLICATIONS);
- when(res.getIntArray(
- com.android.internal.R.array.config_dreamComplicationsEnabledByDefault)).thenReturn(
- DEFAULT_DREAM_COMPLICATIONS);
when(res.getStringArray(
com.android.internal.R.array.config_disabledDreamComponents)).thenReturn(
new String[]{});
@@ -69,31 +76,25 @@
}
@Test
- public void testSupportedComplications() {
- assertThat(mBackend.getSupportedComplications()).containsExactly(1, 2, 3);
+ public void testComplicationsEnabledByDefault() {
+ assertThat(mBackend.getComplicationsEnabled()).isTrue();
+ assertThat(mBackend.getEnabledComplications()).containsExactlyElementsIn(
+ SUPPORTED_DREAM_COMPLICATIONS_LIST);
}
@Test
- public void testGetEnabledDreamComplications_default() {
- assertThat(mBackend.getEnabledComplications()).containsExactly(1, 3);
+ public void testEnableComplicationExplicitly() {
+ mBackend.setComplicationsEnabled(true);
+ assertThat(mBackend.getEnabledComplications()).containsExactlyElementsIn(
+ SUPPORTED_DREAM_COMPLICATIONS_LIST);
+ assertThat(mBackend.getComplicationsEnabled()).isTrue();
}
@Test
- public void testEnableComplication() {
- mBackend.setComplicationEnabled(/* complicationType= */ 2, true);
- assertThat(mBackend.getEnabledComplications()).containsExactly(1, 2, 3);
- }
-
- @Test
- public void testEnableComplication_notSupported() {
- mBackend.setComplicationEnabled(/* complicationType= */ 5, true);
- assertThat(mBackend.getEnabledComplications()).containsExactly(1, 3);
- }
-
- @Test
- public void testDisableComplication() {
- mBackend.setComplicationEnabled(/* complicationType= */ 1, false);
- assertThat(mBackend.getEnabledComplications()).containsExactly(3);
+ public void testDisableComplications() {
+ mBackend.setComplicationsEnabled(false);
+ assertThat(mBackend.getEnabledComplications()).isEmpty();
+ assertThat(mBackend.getComplicationsEnabled()).isFalse();
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/MainSwitchBarTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/MainSwitchBarTest.java
index d86bd01..24037ca 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/MainSwitchBarTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/MainSwitchBarTest.java
@@ -16,6 +16,8 @@
package com.android.settingslib.widget;
+import static android.graphics.text.LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE;
+
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
@@ -97,4 +99,14 @@
assertThat(mBar.getVisibility()).isEqualTo(View.GONE);
}
+
+ @Test
+ public void setTitle_shouldSetCorrectLineBreakStyle() {
+ final String title = "title";
+
+ mBar.setTitle(title);
+ final TextView textView = ((TextView) mBar.findViewById(R.id.switch_text));
+
+ assertThat(textView.getLineBreakWordStyle()).isEqualTo(LINE_BREAK_WORD_STYLE_PHRASE);
+ }
}
diff --git a/packages/SettingsProvider/res/values-ro/strings.xml b/packages/SettingsProvider/res/values-ro/strings.xml
index 561a213..db13019 100644
--- a/packages/SettingsProvider/res/values-ro/strings.xml
+++ b/packages/SettingsProvider/res/values-ro/strings.xml
@@ -21,5 +21,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Stocare setări"</string>
<string name="wifi_softap_config_change" msgid="5688373762357941645">"Setările hotspotului s-au modificat"</string>
- <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Atingeți pentru detalii"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Atinge pentru detalii"</string>
</resources>
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 86d2eb8..36fbf8f 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -210,6 +210,8 @@
Settings.Secure.LOCKSCREEN_SHOW_WALLET,
Settings.Secure.LOCK_SCREEN_SHOW_QR_CODE_SCANNER,
Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK,
- Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON
+ Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON,
+ Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED,
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED
};
}
diff --git a/packages/Shell/res/values-es/strings.xml b/packages/Shell/res/values-es/strings.xml
index 223d167..69c704b 100644
--- a/packages/Shell/res/values-es/strings.xml
+++ b/packages/Shell/res/values-es/strings.xml
@@ -19,7 +19,7 @@
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_notification_channel" msgid="2574150205913861141">"Informes de errores"</string>
<string name="bugreport_in_progress_title" msgid="4311705936714972757">"Se está generando el informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
- <string name="bugreport_finished_title" msgid="4429132808670114081">"Informe de errores <xliff:g id="ID">#%d</xliff:g> capturado"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"Informe de errores <xliff:g id="ID">#%d</xliff:g> registrado"</string>
<string name="bugreport_updating_title" msgid="4423539949559634214">"Añadiendo detalles al informe de errores"</string>
<string name="bugreport_updating_wait" msgid="3322151947853929470">"Espera…"</string>
<string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"El informe de errores aparecerá en el teléfono en breve"</string>
diff --git a/packages/Shell/res/values-nb/strings.xml b/packages/Shell/res/values-nb/strings.xml
index 625b15a..ce39385 100644
--- a/packages/Shell/res/values-nb/strings.xml
+++ b/packages/Shell/res/values-nb/strings.xml
@@ -18,8 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Kommandoliste"</string>
<string name="bugreport_notification_channel" msgid="2574150205913861141">"Feilrapporter"</string>
- <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Feilrapporten <xliff:g id="ID">#%d</xliff:g> blir generert"</string>
- <string name="bugreport_finished_title" msgid="4429132808670114081">"Feilrapporten <xliff:g id="ID">#%d</xliff:g> er fullført"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Feilrapport <xliff:g id="ID">#%d</xliff:g> blir generert"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"Feilrapport <xliff:g id="ID">#%d</xliff:g> er fullført"</string>
<string name="bugreport_updating_title" msgid="4423539949559634214">"Legger til detaljer i feilrapporten"</string>
<string name="bugreport_updating_wait" msgid="3322151947853929470">"Vent litt"</string>
<string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Feilrapporten vises snart på telefonen"</string>
@@ -38,7 +38,7 @@
<string name="bugreport_screenshot_action" msgid="8677781721940614995">"Skjermdump"</string>
<string name="bugreport_screenshot_taken" msgid="5684211273096253120">"Skjermdumpen er tatt."</string>
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Skjermdumpen kunne ikke tas."</string>
- <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detaljer om feilrapporten <xliff:g id="ID">#%d</xliff:g>"</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detaljer om feilrapport <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filnavn"</string>
<string name="bugreport_info_title" msgid="2306030793918239804">"Navn på feil"</string>
<string name="bugreport_info_description" msgid="5072835127481627722">"Oppsummering av feil"</string>
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index cd3a722..ff4c748 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -230,6 +230,7 @@
libs: [
"android.test.runner",
"android.test.base",
+ "android.test.mock",
],
kotlincflags: ["-Xjvm-default=enable"],
aaptflags: [
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 78dea89..7649de6 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -85,7 +85,6 @@
<uses-permission android:name="android.permission.CONTROL_VPN" />
<uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/>
<uses-permission android:name="android.permission.READ_WIFI_CREDENTIAL"/>
- <uses-permission android:name="android.permission.NETWORK_STACK"/>
<!-- Physical hardware -->
<uses-permission android:name="android.permission.MANAGE_USB" />
<uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS" />
@@ -95,6 +94,7 @@
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
<uses-permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY" />
+ <uses-permission android:name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT" />
<!-- ActivityManager -->
<uses-permission android:name="android.permission.REAL_GET_TASKS" />
@@ -152,6 +152,9 @@
<uses-permission android:name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS" />
<uses-permission android:name="android.permission.GET_RUNTIME_PERMISSIONS" />
+ <!-- For auto-grant the access to the Settings' slice preferences, e.g. volume slices. -->
+ <uses-permission android:name="android.permission.READ_SEARCH_INDEXABLES" />
+
<!-- Needed for WallpaperManager.clear in ImageWallpaper.updateWallpaperLocked -->
<uses-permission android:name="android.permission.SET_WALLPAPER"/>
@@ -956,5 +959,13 @@
</intent-filter>
</receiver>
+ <receiver android:name=".volume.VolumePanelDialogReceiver"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.settings.panel.action.VOLUME" />
+ <action android:name="com.android.systemui.action.LAUNCH_VOLUME_PANEL_DIALOG" />
+ <action android:name="com.android.systemui.action.DISMISS_VOLUME_PANEL_DIALOG" />
+ </intent-filter>
+ </receiver>
</application>
</manifest>
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index fa855ab..546f0d2 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -13,7 +13,7 @@
brockman@google.com
brzezinski@google.com
brycelee@google.com
-ccassidy@google.com
+caitlinshk@google.com
chrisgollner@google.com
cinek@google.com
cwren@google.com
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index 8ddd430..7d4dcf8 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -311,8 +311,7 @@
@JvmStatic
fun fromView(view: View, cujType: Int? = null): Controller? {
if (view.parent !is ViewGroup) {
- // TODO(b/192194319): Throw instead of just logging.
- Log.wtf(
+ Log.e(
TAG,
"Skipping animation as view $view is not attached to a ViewGroup",
Exception()
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index 8f9ced6..eac5d275 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -113,6 +113,19 @@
}
val animateFrom = animatedParent?.dialogContentWithBackground ?: view
+ if (animatedParent == null && animateFrom !is LaunchableView) {
+ // Make sure the View we launch from implements LaunchableView to avoid visibility
+ // issues. Given that we don't own dialog decorViews so we can't enforce it for launches
+ // from a dialog.
+ // TODO(b/243636422): Throw instead of logging to enforce this.
+ Log.w(
+ TAG,
+ "A dialog was launched from a View that does not implement LaunchableView. This " +
+ "can lead to subtle bugs where the visibility of the View we are " +
+ "launching from is not what we expected."
+ )
+ }
+
// Make sure we don't run the launch animation from the same view twice at the same time.
if (animateFrom.getTag(TAG_LAUNCH_ANIMATION_RUNNING) != null) {
Log.e(TAG, "Not running dialog launch animation as there is already one running")
@@ -156,9 +169,14 @@
openedDialogs.firstOrNull { it.dialog == animateFrom }?.dialogContentWithBackground
?: throw IllegalStateException(
"The animateFrom dialog was not animated using " +
- "DialogLaunchAnimator.showFrom(View|Dialog)")
+ "DialogLaunchAnimator.showFrom(View|Dialog)"
+ )
showFromView(
- dialog, view, animateBackgroundBoundsChange = animateBackgroundBoundsChange, cuj = cuj)
+ dialog,
+ view,
+ animateBackgroundBoundsChange = animateBackgroundBoundsChange,
+ cuj = cuj
+ )
}
/**
@@ -197,7 +215,7 @@
// bouncer.
if (
!dialog.isShowing ||
- (!callback.isUnlocked() && !callback.isShowingAlternateAuthOnUnlock())
+ (!callback.isUnlocked() && !callback.isShowingAlternateAuthOnUnlock())
) {
return null
}
@@ -556,11 +574,12 @@
window.setDecorFitsSystemWindows(false)
val viewWithInsets = (dialogContentWithBackground.parent as ViewGroup)
viewWithInsets.setOnApplyWindowInsetsListener { view, windowInsets ->
- val type = if (wasFittingNavigationBars) {
- WindowInsets.Type.displayCutout() or WindowInsets.Type.navigationBars()
- } else {
- WindowInsets.Type.displayCutout()
- }
+ val type =
+ if (wasFittingNavigationBars) {
+ WindowInsets.Type.displayCutout() or WindowInsets.Type.navigationBars()
+ } else {
+ WindowInsets.Type.displayCutout()
+ }
val insets = windowInsets.getInsets(type)
view.setPadding(insets.left, insets.top, insets.right, insets.bottom)
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
new file mode 100644
index 0000000..8ce372d
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.animation
+
+import android.view.View
+
+/** A piece of UI that can be expanded into a Dialog or an Activity. */
+interface Expandable {
+ /**
+ * Create an [ActivityLaunchAnimator.Controller] that can be used to expand this [Expandable]
+ * into an Activity, or return `null` if this [Expandable] should not be animated (e.g. if it is
+ * currently not attached or visible).
+ *
+ * @param cujType the CUJ type from the [com.android.internal.jank.InteractionJankMonitor]
+ * associated to the launch that will use this controller.
+ */
+ fun activityLaunchController(cujType: Int? = null): ActivityLaunchAnimator.Controller?
+
+ // TODO(b/230830644): Introduce DialogLaunchAnimator and a function to expose it here.
+
+ companion object {
+ /**
+ * Create an [Expandable] that will animate [view] when expanded.
+ *
+ * Note: The background of [view] should be a (rounded) rectangle so that it can be properly
+ * animated.
+ */
+ fun fromView(view: View): Expandable {
+ return object : Expandable {
+ override fun activityLaunchController(
+ cujType: Int?,
+ ): ActivityLaunchAnimator.Controller? {
+ return ActivityLaunchAnimator.Controller.fromView(view, cujType)
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
index 7499302..67b59e0 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -16,15 +16,79 @@
package com.android.systemui.animation
+import android.view.View
+
/** A view that can expand/launch into an app or a dialog. */
interface LaunchableView {
/**
- * Set whether this view should block/prevent all visibility changes. This ensures that this
- * view remains invisible during the launch animation given that it is ghosted and already drawn
+ * Set whether this view should block/postpone all visibility changes. This ensures that this
+ * view:
+ * - remains invisible during the launch animation given that it is ghosted and already drawn
* somewhere else.
+ * - remains invisible as long as a dialog expanded from it is shown.
+ * - restores its expected visibility once the dialog expanded from it is dismissed.
*
* Note that when this is set to true, both the [normal][android.view.View.setVisibility] and
* [transition][android.view.View.setTransitionVisibility] visibility changes must be blocked.
+ *
+ * @param block whether we should block/postpone all calls to `setVisibility` and
+ * `setTransitionVisibility`.
*/
fun setShouldBlockVisibilityChanges(block: Boolean)
}
+
+/** A delegate that can be used by views to make the implementation of [LaunchableView] easier. */
+class LaunchableViewDelegate(
+ private val view: View,
+
+ /**
+ * The lambda that should set the actual visibility of [view], usually by calling
+ * super.setVisibility(visibility).
+ */
+ private val superSetVisibility: (Int) -> Unit,
+
+ /**
+ * The lambda that should set the actual transition visibility of [view], usually by calling
+ * super.setTransitionVisibility(visibility).
+ */
+ private val superSetTransitionVisibility: (Int) -> Unit,
+) {
+ private var blockVisibilityChanges = false
+ private var lastVisibility = view.visibility
+
+ /** Call this when [LaunchableView.setShouldBlockVisibilityChanges] is called. */
+ fun setShouldBlockVisibilityChanges(block: Boolean) {
+ if (block == blockVisibilityChanges) {
+ return
+ }
+
+ blockVisibilityChanges = block
+ if (block) {
+ lastVisibility = view.visibility
+ } else {
+ superSetVisibility(lastVisibility)
+ }
+ }
+
+ /** Call this when [View.setVisibility] is called. */
+ fun setVisibility(visibility: Int) {
+ if (blockVisibilityChanges) {
+ lastVisibility = visibility
+ return
+ }
+
+ superSetVisibility(visibility)
+ }
+
+ /** Call this when [View.setTransitionVisibility] is called. */
+ fun setTransitionVisibility(visibility: Int) {
+ if (blockVisibilityChanges) {
+ // View.setTransitionVisibility just sets the visibility flag, so we don't have to save
+ // the transition visibility separately from the normal visibility.
+ lastVisibility = visibility
+ return
+ }
+
+ superSetTransitionVisibility(visibility)
+ }
+}
diff --git a/packages/SystemUI/compose/gallery/Android.bp b/packages/SystemUI/compose/gallery/Android.bp
index b0f5cc1..5a7a1e1 100644
--- a/packages/SystemUI/compose/gallery/Android.bp
+++ b/packages/SystemUI/compose/gallery/Android.bp
@@ -54,6 +54,11 @@
"testables",
"truth-prebuilt",
"androidx.test.uiautomator",
+ "kotlinx_coroutines_test",
+ ],
+
+ libs: [
+ "android.test.mock",
],
kotlincflags: ["-Xjvm-default=all"],
diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/qs/footer/Fakes.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/qs/footer/Fakes.kt
new file mode 100644
index 0000000..11477f9
--- /dev/null
+++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/qs/footer/Fakes.kt
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.footer
+
+import android.content.Context
+import android.os.UserHandle
+import android.view.View
+import com.android.internal.util.UserIcons
+import com.android.systemui.R
+import com.android.systemui.animation.Expandable
+import com.android.systemui.classifier.FalsingManagerFake
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel
+import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
+import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
+import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
+import com.android.systemui.util.mockito.mock
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
+
+/** A list of fake [FooterActionsViewModel] to be used in screenshot tests and the gallery. */
+fun fakeFooterActionsViewModels(
+ @Application context: Context,
+): List<FooterActionsViewModel> {
+ return listOf(
+ fakeFooterActionsViewModel(context),
+ fakeFooterActionsViewModel(context, showPowerButton = false, isGuestUser = true),
+ fakeFooterActionsViewModel(context, showUserSwitcher = false),
+ fakeFooterActionsViewModel(context, showUserSwitcher = false, foregroundServices = 4),
+ fakeFooterActionsViewModel(
+ context,
+ foregroundServices = 4,
+ hasNewForegroundServices = true,
+ userId = 1,
+ ),
+ fakeFooterActionsViewModel(
+ context,
+ securityText = "Security",
+ foregroundServices = 4,
+ showUserSwitcher = false,
+ ),
+ fakeFooterActionsViewModel(
+ context,
+ securityText = "Security (not clickable)",
+ securityClickable = false,
+ foregroundServices = 4,
+ hasNewForegroundServices = true,
+ userId = 2,
+ ),
+ )
+}
+
+private fun fakeFooterActionsViewModel(
+ @Application context: Context,
+ securityText: String? = null,
+ securityClickable: Boolean = true,
+ foregroundServices: Int = 0,
+ hasNewForegroundServices: Boolean = false,
+ showUserSwitcher: Boolean = true,
+ showPowerButton: Boolean = true,
+ userId: Int = UserHandle.USER_OWNER,
+ isGuestUser: Boolean = false,
+): FooterActionsViewModel {
+ val interactor =
+ FakeFooterActionsInteractor(
+ securityButtonConfig =
+ flowOf(
+ securityText?.let { text ->
+ SecurityButtonConfig(
+ icon = Icon.Resource(R.drawable.ic_info_outline),
+ text = text,
+ isClickable = securityClickable,
+ )
+ }
+ ),
+ foregroundServicesCount = flowOf(foregroundServices),
+ hasNewForegroundServices = flowOf(hasNewForegroundServices),
+ userSwitcherStatus =
+ flowOf(
+ if (showUserSwitcher) {
+ UserSwitcherStatusModel.Enabled(
+ currentUserName = "foo",
+ currentUserImage =
+ UserIcons.getDefaultUserIcon(
+ context.resources,
+ userId,
+ /* light= */ false,
+ ),
+ isGuestUser = isGuestUser,
+ )
+ } else {
+ UserSwitcherStatusModel.Disabled
+ }
+ ),
+ deviceMonitoringDialogRequests = flowOf(),
+ )
+
+ return FooterActionsViewModel(
+ context,
+ interactor,
+ FalsingManagerFake(),
+ globalActionsDialogLite = mock(),
+ showPowerButton = showPowerButton,
+ )
+}
+
+private class FakeFooterActionsInteractor(
+ override val securityButtonConfig: Flow<SecurityButtonConfig?> = flowOf(null),
+ override val foregroundServicesCount: Flow<Int> = flowOf(0),
+ override val hasNewForegroundServices: Flow<Boolean> = flowOf(false),
+ override val userSwitcherStatus: Flow<UserSwitcherStatusModel> =
+ flowOf(UserSwitcherStatusModel.Disabled),
+ override val deviceMonitoringDialogRequests: Flow<Unit> = flowOf(),
+ private val onShowDeviceMonitoringDialogFromView: (View) -> Unit = {},
+ private val onShowDeviceMonitoringDialog: (Context) -> Unit = {},
+ private val onShowForegroundServicesDialog: (View) -> Unit = {},
+ private val onShowPowerMenuDialog: (GlobalActionsDialogLite, View) -> Unit = { _, _ -> },
+ private val onShowSettings: (Expandable) -> Unit = {},
+ private val onShowUserSwitcher: (View) -> Unit = {},
+) : FooterActionsInteractor {
+ override fun showDeviceMonitoringDialog(view: View) {
+ onShowDeviceMonitoringDialogFromView(view)
+ }
+
+ override fun showDeviceMonitoringDialog(quickSettingsContext: Context) {
+ onShowDeviceMonitoringDialog(quickSettingsContext)
+ }
+
+ override fun showForegroundServicesDialog(view: View) {
+ onShowForegroundServicesDialog(view)
+ }
+
+ override fun showPowerMenuDialog(globalActionsDialogLite: GlobalActionsDialogLite, view: View) {
+ onShowPowerMenuDialog(globalActionsDialogLite, view)
+ }
+
+ override fun showSettings(expandable: Expandable) {
+ onShowSettings(expandable)
+ }
+
+ override fun showUserSwitcher(view: View) {
+ onShowUserSwitcher(view)
+ }
+}
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
new file mode 100644
index 0000000..51cc195
--- /dev/null
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -0,0 +1,877 @@
++packages/SystemUI
+-packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
+-packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
+-packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
+-packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+-packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/BindServiceViaContextDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/BroadcastSentViaContextDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/GetMainLooperViaContextDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/BindServiceViaContextDetectorTest.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/BroadcastSentViaContextDetectorTest.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/GetMainLooperViaContextDetectorTest.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/RegisterReceiverViaContextDetectorTest.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt
+-packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+-packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+-packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/FlagListenable.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/FlagSerializer.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/FlagSettingsHelper.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSamplingInstance.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonPositionCalculator.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerManager.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt
+-packages/SystemUI/shared/src/com/android/systemui/unfold/system/ActivityManagerActivityTypeProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/unfold/system/DeviceStateManagerFoldProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt
+-packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
+-packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
+-packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt
+-packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt
+-packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherAnchor.kt
+-packages/SystemUI/src/com/android/keyguard/clock/ClockPalette.kt
+-packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+-packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/BootCompleteCache.kt
+-packages/SystemUI/src/com/android/systemui/BootCompleteCacheImpl.kt
+-packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt
+-packages/SystemUI/src/com/android/systemui/ChooserSelector.kt
+-packages/SystemUI/src/com/android/systemui/DarkReceiverImpl.kt
+-packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
+-packages/SystemUI/src/com/android/systemui/DualToneHandler.kt
+-packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
+-packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
+-packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt
+-packages/SystemUI/src/com/android/systemui/SystemUIInitializerFactory.kt
+-packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt
+-packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt
+-packages/SystemUI/src/com/android/systemui/assist/AssistantInvocationEvent.kt
+-packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt
+-packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AlternateUdfpsTouchProvider.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceIconController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricIconController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDrawable.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpDrawable.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherViewController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsHapticsSimulator.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayParams.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcherStartable.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/PendingRemovalStore.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
+-packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
+-packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
+-packages/SystemUI/src/com/android/systemui/camera/CameraIntentsWrapper.kt
+-packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
+-packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
+-packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLogger.kt
+-packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLoggerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
+-packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt
+-packages/SystemUI/src/com/android/systemui/controls/TooltipManager.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlInfo.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfiguration.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/StatefulControlSubscriber.kt
+-packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
+-packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsFeatureEnabled.kt
+-packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestReceiver.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ManagementPageIndicator.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlWithState.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/CornerDrawable.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt
+-packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+-packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt
+-packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
+-packages/SystemUI/src/com/android/systemui/decor/DecorProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
+-packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
+-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
+-packages/SystemUI/src/com/android/systemui/demomode/DemoModeAvailabilityTracker.kt
+-packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
+-packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
+-packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt
+-packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
+-packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt
+-packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
+-packages/SystemUI/src/com/android/systemui/dump/DumpsysTableLogger.kt
+-packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
+-packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt
+-packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
+-packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
+-packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
+-packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
+-packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
+-packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
+-packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt
+-packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt
+-packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
+-packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
+-packages/SystemUI/src/com/android/systemui/media/AnimationBindHandler.kt
+-packages/SystemUI/src/com/android/systemui/media/ColorSchemeTransition.kt
+-packages/SystemUI/src/com/android/systemui/media/GutsViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/media/IlluminationDrawable.kt
+-packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
+-packages/SystemUI/src/com/android/systemui/media/LightSourceDrawable.kt
+-packages/SystemUI/src/com/android/systemui/media/LocalMediaManagerFactory.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaCarouselControllerLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaData.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaFeatureFlag.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaHostStatesManager.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaProjectionCaptureTarget.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaScrollView.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaTimeoutLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaUiEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaViewLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/MetadataAnimationHandler.kt
+-packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowserLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
+-packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
+-packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt
+-packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaDataProvider.kt
+-packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt
+-packages/SystemUI/src/com/android/systemui/media/dagger/MediaProjectionModule.kt
+-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
+-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
+-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
+-packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionCli.kt
+-packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManager.kt
+-packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerFactory.kt
+-packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesManager.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipRootView.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
+-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
+-packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt
+-packages/SystemUI/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitor.kt
+-packages/SystemUI/src/com/android/systemui/privacy/MediaProjectionPrivacyItemMonitor.kt
+-packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipEvent.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyConfig.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogEvent.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+-packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
+-packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
+-packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
+-packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
+-packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
+-packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSExpansionPathInterpolator.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSUtils.kt
+-packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt
+-packages/SystemUI/src/com/android/systemui/qs/VisibilityChangedDispatcher.kt
+-packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt
+-packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/CustomTileStatePersister.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/QSExternalModule.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialogEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
+-packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
+-packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
+-packages/SystemUI/src/com/android/systemui/qs/tileimpl/IgnorableChildLinearLayout.kt
+-packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+-packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
+-packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
+-packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
+-packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
+-packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
+-packages/SystemUI/src/com/android/systemui/ripple/RippleShaderUtilLibrary.kt
+-packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
+-packages/SystemUI/src/com/android/systemui/ripple/SdfShaderLibrary.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
+-packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt
+-packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserContentResolverProvider.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserFileManager.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+-packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
+-packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
+-packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
+-packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
+-packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
+-packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt
+-packages/SystemUI/src/com/android/systemui/shade/NotifPanelEvents.kt
+-packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
+-packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+-packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/SmartspacePrecondition.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/SmartspaceTargetFilter.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceViewComponent.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/preconditions/LockscreenPrecondition.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/AbstractLockscreenShadeTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarWifiView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LockScreenShadeOverScroller.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeScrimTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScroller.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/commandline/CommandRegistry.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileStatusTrackerFactory.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalCallback.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiStatusTrackerFactory.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/TapGestureDetector.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/FeedbackIcon.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManagerLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/ViewGroupFadeHelper.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineDumper.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DebugModeCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/BindEventManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/BindEventManagerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTracker.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtender.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/NotificationVisibilityProviderImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionHeaderVisibilityProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/MediaContainerController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGroupController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewListener.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifShadeEventSource.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotificationVisibilityProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderExtensions.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RootNodeController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconBuilder.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/NotificationPersonExtractor.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/RemoteInputViewModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenOffAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHideIconsForBouncerManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocationPublisher.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemBarAttributesListener.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarIconBlocklist.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallFlags.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelStateListener.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserInfoTracker.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/ConnectivityInfoProcessor.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiActivityModel.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiConstants.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/WalletController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/WalletControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/RemoteInput.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/SmartRepliesInflationModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
+-packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
+-packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
+-packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt
+-packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt
+-packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt
+-packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt
+-packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
+-packages/SystemUI/src/com/android/systemui/unfold/UnfoldProgressProvider.kt
+-packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
+-packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
+-packages/SystemUI/src/com/android/systemui/user/UserSwitcherPopupMenu.kt
+-packages/SystemUI/src/com/android/systemui/user/UserSwitcherRootView.kt
+-packages/SystemUI/src/com/android/systemui/util/AsyncActivityLauncher.kt
+-packages/SystemUI/src/com/android/systemui/util/ColorUtil.kt
+-packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt
+-packages/SystemUI/src/com/android/systemui/util/DelayableMarqueeTextView.kt
+-packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt
+-packages/SystemUI/src/com/android/systemui/util/InitializationChecker.kt
+-packages/SystemUI/src/com/android/systemui/util/LargeScreenUtils.kt
+-packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt
+-packages/SystemUI/src/com/android/systemui/util/NeverExactlyLinearLayout.kt
+-packages/SystemUI/src/com/android/systemui/util/NoRemeasureMotionLayout.kt
+-packages/SystemUI/src/com/android/systemui/util/PluralMessageFormater.kt
+-packages/SystemUI/src/com/android/systemui/util/RingerModeTracker.kt
+-packages/SystemUI/src/com/android/systemui/util/RingerModeTrackerImpl.kt
+-packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt
+-packages/SystemUI/src/com/android/systemui/util/SafeMarqueeTextView.kt
+-packages/SystemUI/src/com/android/systemui/util/SparseArrayUtils.kt
+-packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt
+-packages/SystemUI/src/com/android/systemui/util/UserAwareController.kt
+-packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/AnimationUtil.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/MeasurementInput.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
+-packages/SystemUI/src/com/android/systemui/util/collection/RingBuffer.kt
+-packages/SystemUI/src/com/android/systemui/util/concurrency/Execution.kt
+-packages/SystemUI/src/com/android/systemui/util/concurrency/PendingTasksContainer.kt
+-packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt
+-packages/SystemUI/src/com/android/systemui/util/kotlin/CoroutinesModule.kt
+-packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
+-packages/SystemUI/src/com/android/systemui/util/kotlin/IpcSerializer.kt
+-packages/SystemUI/src/com/android/systemui/util/kotlin/nullability.kt
+-packages/SystemUI/src/com/android/systemui/util/view/ViewUtil.kt
+-packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt
+-packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
+-packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt
+-packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardUserSwitcherAnchorTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/clock/ClockPaletteTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/clock/ViewPreviewerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/BootCompleteCacheTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/DisplayCutoutBaseViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/InstanceIdSequenceFake.kt
+-packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastSenderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/PendingRemovalStoreTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/camera/CameraIntentsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/CustomIconCacheTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/AllModelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/AppAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoritesModelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/DumpsysTableLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/lifecycle/InstantTaskExecutorRule.kt
+-packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/AnimationBindHandlerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/ColorSchemeTransitionTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaTestUtils.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MetadataAnimationHandlerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/ResumeMediaBrowserTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/SmartspaceMediaDataTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyChipBuilderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyConfigFlagsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSContainerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelSwitchToParentTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/SettingObserverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/carrier/CellSignalStateTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileStatePersisterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogEventLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/ResourceIconTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/TilesStatesTextTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/ripple/RippleViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageCaptureImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplingInstanceTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/DisableFlagsLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/LightRevealScrimTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScrollerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateEventTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/VibratorHelperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtenderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/MediaContainerViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemBarAttributesListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FlashlightControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
+-packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/user/UserSwitcherActivityTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/FakeSharedPreferencesTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/FloatingContentCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/ListenerSetTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/collection/RingBufferTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/drawable/DrawableSizeTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/IpcSerializerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/view/ViewUtilTest.kt
+-packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
+-packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt
+-packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSharedPreferences.kt
+-packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/ScreenSizeFoldProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/SizeScreenStatusProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldMain.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index 0c191607..01e5d86 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -13,9 +13,9 @@
*/
package com.android.systemui.plugins
+import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.view.View
-import com.android.internal.colorextraction.ColorExtractor
import com.android.systemui.plugins.annotations.ProvidesInterface
import java.io.PrintWriter
import java.util.Locale
@@ -57,7 +57,15 @@
val events: ClockEvents
/** Triggers for various animations */
- val animation: ClockAnimation
+ val animations: ClockAnimations
+
+ /** Initializes various rendering parameters. If never called, provides reasonable defaults. */
+ fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
+ events.onColorPaletteChanged(resources, true, true)
+ animations.doze(dozeFraction)
+ animations.fold(foldFraction)
+ events.onTimeTick()
+ }
/** Optional method for dumping debug information */
fun dump(pw: PrintWriter) { }
@@ -80,15 +88,16 @@
/** Call whenever font settings change */
fun onFontSettingChanged() { }
- /** Call whenever the color pallete should update */
- fun onColorPaletteChanged(palette: ColorExtractor.GradientColors) { }
+ /** Call whenever the color palette should update */
+ fun onColorPaletteChanged(
+ resources: Resources,
+ smallClockIsDark: Boolean,
+ largeClockIsDark: Boolean
+ ) { }
}
/** Methods which trigger various clock animations */
-interface ClockAnimation {
- /** Initializes the doze & fold animation positions. Defaults to neither folded nor dozing. */
- fun initialize(dozeFraction: Float, foldFraction: Float) { }
-
+interface ClockAnimations {
/** Runs an enter animation (if any) */
fun enter() { }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
index bd628cc..1aaf19e 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
@@ -102,6 +102,12 @@
*/
boolean isFalseDoubleTap();
+ /**
+ * Whether the last proximity event reported NEAR. May be used to short circuit motion events
+ * that require the proximity sensor is not covered.
+ */
+ boolean isProximityNear();
+
boolean isClassifierEnabled();
boolean shouldEnforceBouncer();
diff --git a/packages/SystemUI/res-keyguard/font/clock.xml b/packages/SystemUI/res-keyguard/font/clock.xml
deleted file mode 100644
index 0137dc3..0000000
--- a/packages/SystemUI/res-keyguard/font/clock.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2020, 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.
-*/
--->
-
-<!--
-** AOD/LockScreen Clock font.
-** Should include all numeric glyphs in all supported locales.
-** Recommended: font with variable width to support AOD => LS animations
--->
-<!-- TODO: Remove when clock migration complete -->
-<font-family xmlns:android="http://schemas.android.com/apk/res/android">
- <font android:typeface="monospace"/>
-</font-family>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/fgs_footer.xml b/packages/SystemUI/res-keyguard/layout/fgs_footer.xml
index 6757acf..ee588f99 100644
--- a/packages/SystemUI/res-keyguard/layout/fgs_footer.xml
+++ b/packages/SystemUI/res-keyguard/layout/fgs_footer.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+<!-- TODO(b/242040009): Remove this file. -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
diff --git a/packages/SystemUI/res-keyguard/layout/footer_actions.xml b/packages/SystemUI/res-keyguard/layout/footer_actions.xml
index a7e6102..1ce106e 100644
--- a/packages/SystemUI/res-keyguard/layout/footer_actions.xml
+++ b/packages/SystemUI/res-keyguard/layout/footer_actions.xml
@@ -16,16 +16,17 @@
-->
<!-- Action buttons for footer in QS/QQS, containing settings button, power off button etc -->
+<!-- TODO(b/242040009): Clean up this file. -->
<com.android.systemui.qs.FooterActionsView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/footer_actions_height"
android:elevation="@dimen/qs_panel_elevation"
- android:paddingTop="8dp"
+ android:paddingTop="@dimen/qs_footer_actions_top_padding"
android:paddingBottom="@dimen/qs_footer_actions_bottom_padding"
android:background="@drawable/qs_footer_actions_background"
- android:gravity="center_vertical"
+ android:gravity="center_vertical|end"
android:layout_gravity="bottom"
>
diff --git a/packages/SystemUI/res-keyguard/layout/footer_actions_icon_button.xml b/packages/SystemUI/res-keyguard/layout/footer_actions_icon_button.xml
new file mode 100644
index 0000000..fad41c82
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/footer_actions_icon_button.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/qs_footer_action_button_size"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:visibility="gone">
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="@dimen/qs_footer_icon_size"
+ android:layout_height="@dimen/qs_footer_icon_size"
+ android:layout_gravity="center"
+ android:scaleType="centerInside" />
+</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/footer_actions_number_button.xml b/packages/SystemUI/res-keyguard/layout/footer_actions_number_button.xml
new file mode 100644
index 0000000..a7ffe9c
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/footer_actions_number_button.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/qs_footer_action_button_size"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:background="@drawable/qs_footer_action_circle"
+ android:visibility="gone">
+ <TextView
+ android:id="@+id/number"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.QS.SecurityFooter"
+ android:layout_gravity="center"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="18sp"/>
+ <ImageView
+ android:id="@+id/new_dot"
+ android:layout_width="12dp"
+ android:layout_height="12dp"
+ android:scaleType="fitCenter"
+ android:layout_gravity="bottom|end"
+ android:src="@drawable/fgs_dot"
+ android:contentDescription="@string/fgs_dot_content_description" />
+</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/footer_actions_text_button.xml b/packages/SystemUI/res-keyguard/layout/footer_actions_text_button.xml
new file mode 100644
index 0000000..fc18132
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/footer_actions_text_button.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.systemui.common.ui.view.LaunchableLinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/qs_security_footer_single_line_height"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:paddingHorizontal="@dimen/qs_footer_padding"
+ android:gravity="center_vertical"
+ android:layout_marginEnd="@dimen/qs_footer_action_inset"
+ android:background="@drawable/qs_security_footer_background"
+ android:visibility="gone">
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="@dimen/qs_footer_icon_size"
+ android:layout_height="@dimen/qs_footer_icon_size"
+ android:gravity="start"
+ android:layout_marginEnd="12dp"
+ android:contentDescription="@null"
+ android:src="@drawable/ic_info_outline"
+ android:tint="?android:attr/textColorSecondary" />
+
+ <TextView
+ android:id="@+id/text"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:maxLines="1"
+ android:ellipsize="end"
+ android:textAppearance="@style/TextAppearance.QS.SecurityFooter"
+ android:textColor="?android:attr/textColorSecondary"/>
+
+ <ImageView
+ android:id="@+id/new_dot"
+ android:layout_width="12dp"
+ android:layout_height="12dp"
+ android:scaleType="fitCenter"
+ android:src="@drawable/fgs_dot"
+ android:contentDescription="@string/fgs_dot_content_description"
+ />
+
+ <ImageView
+ android:id="@+id/chevron_icon"
+ android:layout_width="@dimen/qs_footer_icon_size"
+ android:layout_height="@dimen/qs_footer_icon_size"
+ android:layout_marginStart="8dp"
+ android:contentDescription="@null"
+ android:src="@*android:drawable/ic_chevron_end"
+ android:autoMirrored="true"
+ android:tint="?android:attr/textColorSecondary" />
+</com.android.systemui.common.ui.view.LaunchableLinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index 6a38507..3ad7c8c 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -23,6 +23,7 @@
android:id="@+id/keyguard_clock_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:clipChildren="false"
android:layout_gravity="center_horizontal|top">
<FrameLayout
android:id="@+id/lockscreen_clock_view"
@@ -30,44 +31,13 @@
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
- android:paddingStart="@dimen/clock_padding_start">
- <com.android.systemui.shared.clocks.AnimatableClockView
- android:id="@+id/animatable_clock_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start"
- android:gravity="start"
- android:textSize="@dimen/clock_text_size"
- android:fontFamily="@font/clock"
- android:elegantTextHeight="false"
- android:singleLine="true"
- android:fontFeatureSettings="pnum"
- chargeAnimationDelay="350"
- dozeWeight="200"
- lockScreenWeight="400"
- />
- </FrameLayout>
+ android:paddingStart="@dimen/clock_padding_start" />
<FrameLayout
android:id="@+id/lockscreen_clock_view_large"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/keyguard_slice_view"
- android:visibility="gone">
- <com.android.systemui.shared.clocks.AnimatableClockView
- android:id="@+id/animatable_clock_view_large"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:gravity="center_horizontal"
- android:textSize="@dimen/large_clock_text_size"
- android:fontFamily="@font/clock"
- android:typeface="monospace"
- android:elegantTextHeight="false"
- chargeAnimationDelay="200"
- dozeWeight="200"
- lockScreenWeight="400"
- />
- </FrameLayout>
+ android:layout_height="match_parent"
+ android:layout_marginTop="@dimen/keyguard_large_clock_top_margin"
+ android:visibility="gone" />
<!-- Not quite optimal but needed to translate these items as a group. The
NotificationIconContainer has its own logic for translation. -->
diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml
index 169ccaa..d5e84f9 100644
--- a/packages/SystemUI/res-keyguard/values-af/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-af/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ongeldige kaart."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Gelaai"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans draadloos"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laaidok"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans vinnig"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans stadig"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laaiproses word tydelik beperk"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laaiproses is onderbreek om battery te beskerm"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk Kieslys om te ontsluit."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk is gesluit"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Geen SIM-kaart nie"</string>
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index b528269..be52c44 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ልክ ያልሆነ ካርድ።"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"ባትሪ ሞልቷል"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በገመድ አልባ ኃይል በመሙላት ላይ"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • የባትሪ ኃይል መሙያ መትከያ"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ኃይል በመሙላት ላይ"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ኃይል በመሙላት ላይ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ኃይል መሙላት ለጊዜው ተገድቧል"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ባትሪን ለመጠበቅ ኃይል መሙላት ባለበት ቆሟል"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ለመክፈት ምናሌ ተጫን።"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"አውታረ መረብ ተቆልፏል"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ምንም ሲም ካርድ የለም"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index 534dbaa..adb57b6 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"بطاقة غير صالحة."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"تم الشحن"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن لاسلكيًا"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن على وحدة الإرساء"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن سريعًا"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن ببطء"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • الشحن محدود مؤقتًا"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تم إيقاف الشحن مؤقتًا لحماية البطارية"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"اضغط على \"القائمة\" لإلغاء التأمين."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"الشبكة مؤمّنة"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ليست هناك شريحة SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml
index 537b5b8..b22655a 100644
--- a/packages/SystemUI/res-keyguard/values-as/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-as/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ব্যৱহাৰৰ অযোগ্য ছিম কাৰ্ড"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"চ্চার্জ কৰা হ’ল"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • বেতাঁৰৰ জৰিয়তে চাৰ্জ কৰি থকা হৈছে"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চাৰ্জিং ডক"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চাৰ্জ কৰি থকা হৈছে"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চ্চার্জ কৰি থকা হৈছে"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্ৰুত গতিৰে চ্চাৰ্জ কৰি থকা হৈছে"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • লাহে লাহে চ্চাৰ্জ কৰি থকা হৈছে"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চাৰ্জ কৰাটো সাময়িকভাৱে সীমিত কৰা হৈছে"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • বেটাৰী সুৰক্ষিত কৰিবলৈ চাৰ্জিং পজ কৰা হৈছে"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক কৰিবলৈ মেনু টিপক।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটৱর্ক লক কৰা অৱস্থাত আছে"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"কোনো ছিম কাৰ্ড নাই"</string>
diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml
index 3fd2f04..6ec1061 100644
--- a/packages/SystemUI/res-keyguard/values-az/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-az/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Yanlış Kart."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Enerji yığılıb"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Simsiz şəkildə batareya yığır"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj Doku"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj edilir"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Enerji yığır"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sürətlə enerji yığır"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş enerji yığır"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj müvəqqəti məhdudlaşdırılıb"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batareyanı qorumaq üçün şarj durdurulub"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmaq üçün Menyu düyməsinə basın."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Şəbəkə kilidlidir"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM kart yoxdur."</string>
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index b0059d8..13d6613 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Nevažeća kartica."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Napunjena je"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bežično punjenje"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bazna stanica za punjenje"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Puni se"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Puni se"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo se puni"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo se puni"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je privremeno ograničeno"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je pauzirano da bi se zaštitila baterija"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Meni da biste otključali."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nema SIM kartice"</string>
diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml
index ebcca07..616d31a 100644
--- a/packages/SystemUI/res-keyguard/values-be/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-be/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Несапраўдная картка."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Зараджаны"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе бесправадная зарадка"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе зарадка праз док-станцыю"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе зарадка"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе зарадка"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе хуткая зарадка"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе павольная зарадка"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарадка часова абмежавана"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарадка прыпынена дзеля ашчады акумулятара"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Націсніце кнопку \"Меню\", каб разблакіраваць."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Сетка заблакіравана"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Няма SIM-карты"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml
index a08409e..366a7f4 100644
--- a/packages/SystemUI/res-keyguard/values-bg/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Картата е невалидна."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Заредена"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се безжично"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Докинг станция за зареждане"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бързо"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бавно"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зареждането временно е ограничено"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зареждането е поставено на пауза с цел да се запази батерията"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натиснете „Меню“, за да отключите."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заключена"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Няма SIM карта"</string>
@@ -74,7 +74,7 @@
<string name="kg_password_pin_failed" msgid="5136259126330604009">"Операцията с ПИН кода за SIM картата не бе успешна!"</string>
<string name="kg_password_puk_failed" msgid="6778867411556937118">"Операцията с PUK кода за SIM картата не бе успешна!"</string>
<string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Превключване на метода на въвеждане"</string>
- <string name="airplane_mode" msgid="2528005343938497866">"Самолетен режим"</string>
+ <string name="airplane_mode" msgid="2528005343938497866">"Самолет. режим"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"След рестартиране на устройството се изисква фигура"</string>
<string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"След рестартиране на устройството се изисква ПИН код"</string>
<string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"След рестартиране на устройството се изисква парола"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index cb9e900..c20be5d 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ভুল কার্ড।"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"চার্জ হয়েছে"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ওয়্যারলেস পদ্ধতিতে চার্জ হচ্ছে"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জিং ডক"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ হচ্ছে"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ হচ্ছে"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্রুত চার্জ হচ্ছে"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ধীরে চার্জ হচ্ছে"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ করা সাময়িকভাবে বন্ধ রাখা হয়েছে"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ব্যাটারি সুরক্ষিত রাখতে চার্জিং পজ করা হয়েছে"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক করতে মেনুতে টিপুন।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটওয়ার্ক লক করা আছে"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"কোনো সিম কার্ড নেই"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index 280d354..f1c00a9 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Nevažeća kartica."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Napunjeno"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bežično punjenje"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Priključna stanica za punjenje"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo punjenje"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo punjenje"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je privremeno ograničeno"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je pauzirano radi zaštite baterije"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite meni da otključate."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nema SIM kartice"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index b1f5a3f..709407c 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"La targeta no és vàlida."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Bateria carregada"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant sense fil"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Base de càrrega"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant ràpidament"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant lentament"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Càrrega limitada temporalment"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • La càrrega s\'ha posat en pausa per protegir la bateria"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prem Menú per desbloquejar."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"La xarxa està bloquejada"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"No hi ha cap SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml
index 1b52635..a44658c 100644
--- a/packages/SystemUI/res-keyguard/values-cs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Neplatná karta."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Nabito"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bezdrátové nabíjení"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjecí dok"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjení"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjení"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rychlé nabíjení"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pomalé nabíjení"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjení je dočasně omezeno"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjení je pozastaveno za účelem ochrany baterie"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Klávesy odemknete stisknutím tlačítka nabídky."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Síť je blokována"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Chybí SIM karta"</string>
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index cb8ad8f..331c355 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ugyldigt kort."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Opladet"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Trådløs opladning"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader i dockingstation"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader hurtigt"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader langsomt"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladningen er midlertidigt begrænset"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladningen er sat på pause for at beskytte batteriet"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tryk på menuen for at låse op."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netværket er låst"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Intet SIM-kort"</string>
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index 579c514..c19b357 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ungültige Karte."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Aufgeladen"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kabelloses Laden"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladestation"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird geladen"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird geladen"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird schnell geladen"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird langsam geladen"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laden vorübergehend eingeschränkt"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladevorgang angehalten, um den Akku zu schonen"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Zum Entsperren die Menütaste drücken."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netzwerk gesperrt"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Keine SIM-Karte"</string>
diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml
index 8dd5d20..1d6ec82 100644
--- a/packages/SystemUI/res-keyguard/values-el/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-el/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Μη έγκυρη κάρτα."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Φορτίστηκε"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ασύρματη φόρτιση"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Βάση φόρτισης"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Φόρτιση"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Φόρτιση"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Γρήγορη φόρτιση"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Αργή φόρτιση"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Προσωρινός περιορισμός φόρτισης"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Η φόρτιση τέθηκε σε παύση για την προστασία της μπαταρίας"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Πατήστε \"Μενού\" για ξεκλείδωμα."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Κλειδωμένο δίκτυο"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Δεν υπάρχει SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index 865ebab..2b78f96 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Invalid card."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Charged"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging dock"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging temporarily limited"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging is paused to protect battery"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"No SIM card"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
index 9b4df35..e1c2532 100644
--- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Invalid card."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Charged"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging dock"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging temporarily limited"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging is paused to protect battery"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"No SIM card"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index 865ebab..2b78f96 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Invalid card."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Charged"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging dock"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging temporarily limited"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging is paused to protect battery"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"No SIM card"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index 865ebab..2b78f96 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Invalid card."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Charged"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging dock"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging temporarily limited"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging is paused to protect battery"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"No SIM card"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
index afb3d65..9052e4f 100644
--- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Invalid Card."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Charged"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging Dock"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging temporarily limited"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging is paused to protect battery"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"No SIM card"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
index ea3b8a7..fc9c402 100644
--- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Tarjeta no válida"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Cargada"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando de manera inalámbrica"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Conectado y cargando"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga limitada temporalmente"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se pausó la carga para proteger la batería"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Presiona Menú para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Sin tarjeta SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml
index 0c267aa..4053161 100644
--- a/packages/SystemUI/res-keyguard/values-es/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Tarjeta no válida."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Cargado"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando sin cables"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Base de carga"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga limitada temporalmente"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • La carga se pausa para proteger la batería"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pulsa el menú para desbloquear la pantalla."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Falta la tarjeta SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml
index f4c99c4..dceb78e 100644
--- a/packages/SystemUI/res-keyguard/values-et/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-et/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Kehtetu kaart."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Laetud"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Juhtmeta laadimine"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimisdokk"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kiirlaadimine"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Aeglane laadimine"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine on ajutiselt piiratud"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine on peatatud, et akut kaitsta"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Vajutage avamiseks menüüklahvi."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Võrk on lukus"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM-kaarti pole"</string>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index bf94915..8431268 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Txartelak ez du balio."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Kargatuta"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hari gabe kargatzen"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oinarrian kargatzen"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzen"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzen"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzeko aukera mugatuta dago aldi baterako"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatze-prozesua pausatuta dago bateria babesteko"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Desblokeatzeko, sakatu Menua."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Sarea blokeatuta dago"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Ez dago SIM txartelik"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml
index ca22227..37bb260 100644
--- a/packages/SystemUI/res-keyguard/values-fa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"کارت نامعتبر"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"شارژ کامل شد"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ بیسیم"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • پایه شارژ"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ شدن"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ شدن"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آهستهآهسته شارژ میشود"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • شارژ موقتاً محدود شده است"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • برای محافظت از باتری، شارژ موقتاً متوقف شده است"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"برای باز کردن قفل روی «منو» فشار دهید."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"شبکه قفل شد"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"سیمکارت موجود نیست"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml
index da74b9a1..f8cec42 100644
--- a/packages/SystemUI/res-keyguard/values-fi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Virheellinen kortti"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Ladattu"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan langattomasti"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan telineellä"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan nopeasti"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan hitaasti"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lataamista rajoitettu väliaikaisesti"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lataus on keskeytetty akun suojaamiseksi"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Poista lukitus painamalla Valikkoa."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Verkko lukittu"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Ei SIM-korttia"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index b812503..92ab77e 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cette carte n\'est pas valide."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Chargé"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • En recharge sans fil"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Station de recharge"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge en cours…"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"En recharge : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge temporairement limitée"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • La recharge a été mise en pause pour protéger la pile"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur la touche Menu pour déverrouiller l\'appareil."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Aucune carte SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml
index 0b21a40..01facd1 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Carte non valide."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Chargé"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • En charge sans fil"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Station de charge"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge…"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge rapide…"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge lente…"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge momentanément limitée"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • La recharge est en pause pour protéger la batterie"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur \"Menu\" pour déverrouiller le clavier."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Pas de carte SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index 628a885..4fbdd67 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"A tarxeta non é válida."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Cargado"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando sen fíos"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Base de carga"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rapidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga limitada temporalmente"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carga púxose en pausa para protexer a batería"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Preme Menú para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada pola rede"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Sen tarxeta SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml
index 4dd994c..6caac8a 100644
--- a/packages/SystemUI/res-keyguard/values-gu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"અમાન્ય કાર્ડ."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"ચાર્જ થઈ ગયું"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • વાયરલેસથી ચાર્જિંગ"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ડૉકથી ચાર્જ થઈ રહ્યું છે"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જિંગ"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જિંગ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ઝડપથી ચાર્જિંગ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ધીમેથી ચાર્જિંગ"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જ કરવાનું થોડા સમય માટે મર્યાદિત કરવામાં આવ્યું છે"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • બૅટરીની સુરક્ષા કરવા માટે ચાર્જિંગ થોભાવવામાં આવ્યું છે"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"અનલૉક કરવા માટે મેનૂ દબાવો."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"નેટવર્ક લૉક થયું"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"કોઈ સિમ કાર્ડ નથી"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index 44a9c0e..627576e 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"गलत कार्ड."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"चार्ज हो गई है"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वायरलेस तरीके से चार्ज हो रहा है"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • डॉक पर चार्ज हो रहा है"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हो रहा है"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हो रहा है"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • धीरे चार्ज हो रहा है"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • कुछ समय के लिए चार्जिंग रोक दी गई"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बैटरी को सुरक्षित रखने के लिए, चार्जिंग को रोका गया है"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"लॉक खोलने के लिए मेन्यू दबाएं."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक किया हुआ है"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"कोई सिम कार्ड नहीं है"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml
index 299d811..8b1b504 100644
--- a/packages/SystemUI/res-keyguard/values-hr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Nevažeća kartica."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Napunjeno"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • bežično punjenje"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Priključna stanica za punjenje"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • punjenje"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • punjenje"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brzo punjenje"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • sporo punjenje"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je privremeno ograničeno"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • punjenje je pauzirano radi zaštite baterije"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Izbornik da biste otključali."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nema SIM kartice"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml
index 6201e95..6b75e72 100644
--- a/packages/SystemUI/res-keyguard/values-hu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Érvénytelen kártya."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Feltöltve"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Vezeték nélküli töltés"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Töltődokk"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Töltés…"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Töltés"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Gyors töltés"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lassú töltés"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Töltés ideiglenesen korlátozva"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Az akkumulátor védelmének biztosítása érdekében a töltés szünetel"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"A feloldáshoz nyomja meg a Menü gombot."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Hálózat zárolva"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nincs SIM-kártya"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml
index 5d65da0..3412026 100644
--- a/packages/SystemUI/res-keyguard/values-hy/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Սխալ քարտ"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Լիցքավորված է"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Անլար լիցքավորում"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորում դոկ-կայանի միջոցով"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորում"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորում"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Արագ լիցքավորում"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Դանդաղ լիցքավորում"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորումը ժամանակավորապես սահմանափակված է"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորումը դադարեցվել է՝ մարտկոցը պաշտպանելու համար"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ապակողպելու համար սեղմեք Ընտրացանկը:"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Ցանցը կողպված է"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM քարտ չկա"</string>
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index c42f5eb..1afb791 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Kartu Tidak Valid"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Terisi penuh"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya secara nirkabel"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi Daya dengan Dok"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan lambat"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengisian daya dibatasi sementara"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengisian daya dijeda untuk melindungi baterai"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Jaringan terkunci"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Tidak ada kartu SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml
index ea1a8ee..6abdc82 100644
--- a/packages/SystemUI/res-keyguard/values-is/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-is/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ógilt kort."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Fullhlaðin"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Í þráðlausri hleðslu"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hleður í dokku"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Í hleðslu"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Í hleðslu"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hröð hleðsla"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hæg hleðsla"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hleðsla takmörkuð tímabundið"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Gert var hlé á hleðslu til að vernda rafhlöðuna"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ýttu á valmyndarhnappinn til að taka úr lás."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Net læst"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Ekkert SIM-kort"</string>
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index f1583b1..d3a683b 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Scheda non valida."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Carico"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica wireless"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica nel dock"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica veloce"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica lenta"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica momentaneamente limitata"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica in pausa per proteggere la batteria"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Premi Menu per sbloccare."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rete bloccata"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nessuna SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index 470dd72..b5b1c53 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"כרטיס לא חוקי."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"הסוללה טעונה"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה אלחוטית"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • אביזר העגינה בטעינה"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה מהירה"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה איטית"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • הטעינה מוגבלת באופן זמני"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • הטעינה הושהתה כדי להגן על הסוללה"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"יש ללחוץ על \'תפריט\' כדי לבטל את הנעילה."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"הרשת נעולה"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"אין כרטיס SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index efe13ec..afe0159 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"無効なカードです。"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"充電が完了しました"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ワイヤレス充電中"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ホルダーで充電中"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 低速充電中"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電を一時的に制限しています"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • バッテリーを保護するため、充電を一時停止しました"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"メニューからロックを解除できます。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ネットワークがロックされました"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM カードなし"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml
index 67f85f0..b32caa7 100644
--- a/packages/SystemUI/res-keyguard/values-ka/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ბარათი არასწორია."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"დატენილია"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • იტენება უსადენოდ"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • დამტენი სამაგრი"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • იტენება"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • იტენება"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • სწრაფად იტენება"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ნელა იტენება"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • დატენვა დროებით შეზღუდულია"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • დატენვა ᲨეᲩერებულია ბატარეის დაცვის მიზნიᲗ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"განსაბლოკად დააჭირეთ მენიუს."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ქსელი ჩაკეტილია"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM ბარ. არაა"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index 71e9a9d..d6d5bcd 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Жарамсыз карта."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Зарядталды"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Сымсыз зарядталуда"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Қондыру станциясында зарядталуда"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядталып жатыр."</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядталуда"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жылдам зарядталуда"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Баяу зарядталуда"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядтау уақытша шектелген"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяны қорғау мақсатында зарядтау кідіртілді."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ашу үшін \"Мәзір\" пернесін басыңыз."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Желі құлыптаулы"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM картасы салынбаған"</string>
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index 645f638..00bfe05 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"បណ្ណមិនត្រឹមត្រូវទេ។"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"បានសាកថ្មពេញ"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្មឥតខ្សែ"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ឧបករណ៍ភ្ជាប់សាកថ្ម"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្ម"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្ម"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្មយឺត"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • បានដាក់កំហិតលើការសាកថ្មជាបណ្ដោះអាសន្ន"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ការសាកថ្មត្រូវបានផ្អាក ដើម្បីការពារថ្ម"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ចុចម៉ឺនុយ ដើម្បីដោះសោ។"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"បណ្ដាញជាប់សោ"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"គ្មានស៊ីមកាតទេ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml
index e5e4a5f..80a98e6 100644
--- a/packages/SystemUI/res-keyguard/values-kn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ಅಮಾನ್ಯ ಕಾರ್ಡ್."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೈರ್ಲೆಸ್ ಆಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜಿಂಗ್ ಡಾಕ್"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ಸೀಮಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಬ್ಯಾಟರಿಯನ್ನು ರಕ್ಷಿಸಲು ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ಅನ್ಲಾಕ್ ಮಾಡಲು ಮೆನು ಒತ್ತಿರಿ."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ನೆಟ್ವರ್ಕ್ ಲಾಕ್ ಆಗಿದೆ"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ಸಿಮ್ ಕಾರ್ಡ್ ಇಲ್ಲ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index 4c1cfb7..b952f1b 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"유효하지 않은 카드"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"충전됨"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 무선 충전 중"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전 도크"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전 중"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전 중"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 저속 충전 중"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전이 일시적으로 제한됨"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 배터리 보호를 위해 충전이 일시중지됨"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"잠금 해제하려면 메뉴를 누르세요."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"네트워크 잠김"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM 카드 없음"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index ec276fe..485337d 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"SIM-карта жараксыз."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Кубатталды"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зымсыз кубатталууда"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубаттоо догу"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубатталууда"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубатталууда"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тез кубатталууда"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жай кубатталууда"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубаттоо убактылуу чектелген"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяны коргоо үчүн кубаттоо тындырылды"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Кулпуну ачуу үчүн Менюну басыңыз."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Тармак кулпуланган"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM карта жок"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml
index 44051d8..17584b5 100644
--- a/packages/SystemUI/res-keyguard/values-lo/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ບັດບໍ່ຖືກຕ້ອງ."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"ສາກເຕັມແລ້ວ."</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກໄຟໄຮ້ສາຍ"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກໄຟຜ່ານດັອກ"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກໄຟ"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບດ່ວນ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບຊ້າ"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ຈຳກັດການສາກໄຟຊົ່ວຄາວແລ້ວ"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ການສາກໄຟຖືກຢຸດໄວ້ຊົ່ວຄາວເພື່ອປົກປ້ອງແບັດເຕີຣີ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ກົດ \"ເມນູ\" ເພື່ອປົດລັອກ."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ເຄືອຂ່າຍຖືກລັອກ"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ບໍ່ມີຊິມກາດ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml
index 26c54c0..a066a66 100644
--- a/packages/SystemUI/res-keyguard/values-lt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Netinkama kortelė."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Įkrauta"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kraunama be laidų"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkraunama doke"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkraunama"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkraunama"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Greitai įkraunama"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lėtai įkraunama"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkrovimas laikinai apribotas"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkrovimas pristabdytas siekiant apsaugoti akumuliatorių"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Paspauskite meniu, jei norite atrakinti."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Tinklas užrakintas"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nėra SIM kortelės"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml
index fb913ea..d371a4b 100644
--- a/packages/SystemUI/res-keyguard/values-lv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Nederīga karte."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Akumulators uzlādēts"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek bezvadu uzlāde"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek uzlāde dokā"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek uzlāde"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek uzlāde"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek ātrā uzlāde"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek lēnā uzlāde"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Uzlāde īslaicīgi ierobežota"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Uzlāde ir pārtraukta, lai aizsargātu akumulatoru"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lai atbloķētu, nospiediet izvēlnes ikonu."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Tīkls ir bloķēts."</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nav SIM kartes."</string>
diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml
index 9769c7e..ef22564 100644
--- a/packages/SystemUI/res-keyguard/values-mk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Неважечка картичка."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Полна"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни безжично"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни на док"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо полнење"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бавно полнење"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Полнењето е привремено ограничено"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Полнењето е паузирано за да се заштити батеријата"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притиснете „Мени“ за отклучување."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заклучена"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Нема SIM-картичка"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml
index e1d3f82..63a542a 100644
--- a/packages/SystemUI/res-keyguard/values-ml/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"അസാധുവായ കാർഡ്."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"ചാർജായി"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വയർലെസ്സ് ആയി ചാർജ് ചെയ്യുന്നു"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജിംഗ് ഡോക്ക്"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജ് ചെയ്യുന്നു"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജ് ചെയ്യുന്നു"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജിംഗ് താൽക്കാലികമായി പരിമിതപ്പെടുത്തിയിരിക്കുന്നു"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ബാറ്ററി പരിരക്ഷിക്കാൻ ചാർജിംഗ് താൽക്കാലികമായി നിർത്തി"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"അൺലോക്കുചെയ്യാൻ മെനു അമർത്തുക."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"നെറ്റ്വർക്ക് ലോക്കുചെയ്തു"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"സിം കാർഡില്ല"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml
index 8c42abc..71c913f 100644
--- a/packages/SystemUI/res-keyguard/values-mn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Карт хүчингүй байна."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Цэнэглэсэн"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Утасгүй цэнэглэж байна"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэх холбогч"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэж байна"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэж байна"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Хурдан цэнэглэж байна"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Удаан цэнэглэж байна"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэхийг түр хязгаарласан"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батарейг хамгаалахын тулд цэнэглэхийг түр зогсоосон"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Түгжээг тайлах бол цэсийг дарна уу."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Сүлжээ түгжигдсэн"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM карт алга"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index 2c0bf0f..6ac13bd 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"अवैध कार्ड."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"चार्ज झाली"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वायरलेस पद्धतीने चार्ज करत आहे"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्जिंग डॉक"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज होत आहे"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज होत आहे"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वेगाने चार्ज होत आहे"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • सावकाश चार्ज होत आहे"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्जिंग तात्पुरते मर्यादित आहे"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बॅटरीचे संरक्षण करण्यासाठी चार्ज करणे थांबवले आहे"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलॉक करण्यासाठी मेनू दाबा."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक केले"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"सिम कार्ड नाही"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index fc18b42..453afc3 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Kad Tidak Sah."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Sudah dicas"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas secara wayarles"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan Dok"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan cepat"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan perlahan"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengecasan terhad sementara"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengecasan dijeda untuk melindungi bateri"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rangkaian dikunci"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Tiada kad SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index 38d94e4..1cc46b1 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ကတ် မမှန်ကန်ပါ။"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"အားသွင်းပြီးပါပြီ"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ကြိုးမဲ့ အားသွင်းနေသည်"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းအထိုင်"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းနေသည်"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းနေသည်"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အမြန်အားသွင်းနေသည်"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည်"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းခြင်းကို လောလောဆယ် ကန့်သတ်ထားသည်"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ဘက်ထရီကို ကာကွယ်ရန် အားသွင်းခြင်းကို ခဏရပ်ထားသည်"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"မီနူးကို နှိပ်၍ လော့ခ်ဖွင့်ပါ။"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ကွန်ရက်ကို လော့ခ်ချထားသည်"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ဆင်းမ်ကတ် မရှိပါ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml
index 8730723..5310a730 100644
--- a/packages/SystemUI/res-keyguard/values-nb/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ugyldig kort."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Oppladet"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader trådløst"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladedokk"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader raskt"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader sakte"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lading er midlertidig begrenset"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladingen er satt på pause for å beskytte batteriet"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Trykk på menyknappen for å låse opp."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Nettverket er låst"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM-kort mangler"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index 98e9813..534164b 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"अमान्य कार्ड।"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"चार्ज भयो"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तारविनै चार्ज गर्दै"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • डक चार्ज हुँदै छ"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हुँदै छ"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज गरिँदै"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै छ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • मन्द गतिमा चार्ज गरिँदै"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्जिङ केही समयका लागि सीमित पारिएको छ"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ब्याट्री जोगाउन चार्ज गर्ने प्रक्रिया रोकिएको छ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलक गर्न मेनु थिच्नुहोस्।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लक भएको छ"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM कार्ड छैन"</string>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index 77bf29c..08e226d4 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ongeldige kaart."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Opgeladen"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Draadloos opladen"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplaaddock"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Snel opladen"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Langzaam opladen"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen tijdelijk beperkt"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen is onderbroken om de batterij te beschermen"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk op Menu om te ontgrendelen."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk vergrendeld"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Geen simkaart"</string>
diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml
index 8765781..3cdd264 100644
--- a/packages/SystemUI/res-keyguard/values-or/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-or/strings.xml
@@ -26,18 +26,18 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ଅମାନ୍ୟ କାର୍ଡ।"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"ଚାର୍ଜ ହୋଇଗଲା"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"ୱାୟାର୍ଲେସ୍ଭାବରେ <xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜ ହୋଇଛି"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଡକରୁ ଚାର୍ଜ ହେଉଛି"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜ ହେଉଛି"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜ ହେଉଛି"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଦ୍ରୁତ ଭାବେ ଚାର୍ଜ ହେଉଛି"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜିଂ ଅସ୍ଥାୟୀ ଭାବେ ସୀମିତ କରାଯାଇଛି"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ବେଟେରୀକୁ ସୁରକ୍ଷିତ ରଖିବା ପାଇଁ ଚାର୍ଜିଂକୁ ବିରତ କରାଯାଇଛି"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ଅନଲକ୍ କରିବା ପାଇଁ ମେନୁକୁ ଦବାନ୍ତୁ।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ନେଟୱର୍କକୁ ଲକ୍ କରାଯାଇଛି"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"କୌଣସି SIM କାର୍ଡ ନାହିଁ"</string>
<string name="keyguard_missing_sim_instructions" msgid="1162120926141335918">"ଗୋଟିଏ SIM କାର୍ଡ ଭର୍ତ୍ତି କରନ୍ତୁ।"</string>
<string name="keyguard_missing_sim_instructions_long" msgid="2712623293749378570">"SIM କାର୍ଡ ନାହିଁ କିମ୍ବା ଖରାପ ଅଛି। SIM କାର୍ଡ ଭର୍ତ୍ତି କରନ୍ତୁ।"</string>
<string name="keyguard_permanent_disabled_sim_message_short" msgid="5842745213110966962">"SIM କାର୍ଡଟିକୁ ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ।"</string>
- <string name="keyguard_permanent_disabled_sim_instructions" msgid="2490584154727897806">"ଆପଣଙ୍କ SIM କାର୍ଡକୁ ସ୍ଥାୟୀ ରୂପେ ଅକ୍ଷମ କରିଦିଆଯାଇଛି।\n ଅନ୍ୟ SIM କାର୍ଡ ପାଇଁ ଆପଣଙ୍କ ୱାୟରଲେସ୍ ସେବା ପ୍ରଦାତାଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="keyguard_permanent_disabled_sim_instructions" msgid="2490584154727897806">"ଆପଣଙ୍କ SIM କାର୍ଡକୁ ସ୍ଥାୟୀ ରୂପେ ଅକ୍ଷମ କରିଦିଆଯାଇଛି।\n ଅନ୍ୟ SIM କାର୍ଡ ପାଇଁ ଆପଣଙ୍କ ୱାୟରଲେସ ସେବା ପ୍ରଦାତାଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="keyguard_sim_locked_message" msgid="4343544458476911044">"SIM କାର୍ଡ ଲକ୍ ହୋଇଯାଇଛି।"</string>
<string name="keyguard_sim_puk_locked_message" msgid="6253830777745450550">"SIM କାର୍ଡଟି PUK ଲକ୍ ହୋଇଯାଇଛି।"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="2394023844117630429">"SIM କାର୍ଡ ଅନଲକ୍ କରାଯାଉଛି…"</string>
@@ -57,8 +57,8 @@
<string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIMର PIN ଲେଖନ୍ତୁ।"</string>
<string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" ପାଇଁ SIMର PIN ଲେଖନ୍ତୁ।"</string>
<string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> ବିନା ମୋବାଇଲ୍ ସେବାରେ ଡିଭାଇସ୍କୁ ବ୍ୟବହାର କରିବା ପାଇଁ eSIMକୁ ଅକ୍ଷମ କରନ୍ତୁ।"</string>
- <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM ବର୍ତ୍ତମାନ ଅକ୍ଷମ ଅଟେ। ଜାରି ରଖିବାକୁ PUK କୋଡ୍ ଏଣ୍ଟର୍ କରନ୍ତୁ। ବିବରଣୀ ପାଇଁ ନିଜ କେରିଅର୍ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
- <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ବର୍ତ୍ତମାନ ଅକ୍ଷମ କରାଯାଇଛି। ଜାରିରଖିବାକୁ PUK କୋଡ୍ ଲେଖନ୍ତୁ। ବିବରଣୀ ପାଇଁ କେରିଅରଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM ବର୍ତ୍ତମାନ ଅକ୍ଷମ ଅଟେ। ଜାରି ରଖିବାକୁ PUK କୋଡ ଲେଖନ୍ତୁ। ବିବରଣୀ ପାଇଁ ନିଜ କ୍ଯାରିଅରଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
+ <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ବର୍ତ୍ତମାନ ଅକ୍ଷମ କରାଯାଇଛି। ଜାରିରଖିବାକୁ PUK କୋଡ ଲେଖନ୍ତୁ। ବିବରଣୀ ପାଇଁ କ୍ଯାରିଅରଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"ନିଜ ଇଚ୍ଛାର PIN କୋଡ୍ ଲେଖନ୍ତୁ"</string>
<string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"ନିଜ ଇଚ୍ଛାର PIN କୋଡ୍ ନିଶ୍ଚିତ କରନ୍ତୁ"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM କାର୍ଡ ଅନଲକ୍ କରାଯାଉଛି…"</string>
@@ -67,9 +67,9 @@
<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_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ଭୁଲ SIM PIN କୋଡ୍, ଆପଣଙ୍କ ଡିଭାଇସକୁ ଅନଲକ୍ କରିବା ପାଇଁ ଏବେ ହିଁ ନିଜ କେରିଅର୍ଙ୍କ ସହ ସମ୍ପର୍କ କରନ୍ତୁ।"</string>
- <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{ଭୁଲ SIM PIN କୋଡ, ଆପଣଙ୍କ ଡିଭାଇସକୁ ଅନଲକ କରିବା ପାଇଁ ଆପଣ ଆପଣଙ୍କର କ୍ୟାରିଅର ସହ ନିଶ୍ଚିତରୂପେ ଯୋଗାଯୋଗ କରିବା ପୂର୍ବରୁ ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି।}other{ଭୁଲ SIM PIN କୋଡ, ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି। }}"</string>
- <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ। ନିଜ କେରିଅର୍ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ଭୁଲ SIM PIN କୋଡ, ଆପଣଙ୍କ ଡିଭାଇସକୁ ଅନଲକ କରିବା ପାଇଁ ଏବେ ହିଁ ନିଜ କ୍ଯାରିଅରଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
+ <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{ଭୁଲ SIM PIN କୋଡ, ଆପଣଙ୍କ ଡିଭାଇସକୁ ଅନଲକ କରିବା ପାଇଁ ଆପଣ ଆପଣଙ୍କର କ୍ୟାରିଅର ସହ ନିଶ୍ଚିତରୂପେ କଣ୍ଟାକ୍ଟ କରିବା ପୂର୍ବରୁ ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି।}other{ଭୁଲ SIM PIN କୋଡ, ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି।}}"</string>
+ <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ। ନିଜ କ୍ଯାରିଅରଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{ଭୁଲ SIM PUK କୋଡ, SIM ସ୍ଥାୟୀ ଭାବେ ବ୍ୟବହାର ଅଯୋଗ୍ୟ ହେବା ପୂର୍ବରୁ ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି।}other{ଭୁଲ SIM PUK କୋଡ, SIM ସ୍ଥାୟୀ ଭାବେ ବ୍ୟବହାର ଅଯୋଗ୍ୟ ହେବା ପୂର୍ବରୁ ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି।}}"</string>
<string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN କାମ ବିଫଳ ହେଲା!"</string>
<string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUKର କାମ ବିଫଳ ହେଲା!"</string>
@@ -85,8 +85,8 @@
<string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ଡିଭାଇସ୍ ମାନୁଆଲ ଭାବେ ଲକ୍ କରାଗଲା"</string>
<string name="kg_face_not_recognized" msgid="7903950626744419160">"ଚିହ୍ନଟ ହେଲାନାହିଁ"</string>
<string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"ଫେସ ଅନଲକର ବ୍ୟବହାର ପାଇଁ ସେଟିଂସରେ କ୍ୟାମେରାକୁ ଆକ୍ସେସ ଦିଅ"</string>
- <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{SIM PIN ଲେଖନ୍ତୁ। ଆପଣଙ୍କ ଡିଭାଇସକୁ ଅନଲକ କରିବା ପାଇଁ ଆପଣ ଆପଣଙ୍କର କ୍ୟାରିଅର ସହ ନିଶ୍ଚିତରୂପେ ଯୋଗାଯୋଗ କରିବା ପୂର୍ବରୁ ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି।}other{SIM PIN ଲେଖନ୍ତୁ। ଆପଣଙ୍କର #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି।}}"</string>
- <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{SIMକୁ ବର୍ତ୍ତମାନ ଅକ୍ଷମ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ PUK କୋଡ ଲେଖନ୍ତୁ। SIM ସ୍ଥାୟୀ ଭାବେ ବ୍ୟବହାର ଅଯୋଗ୍ୟ ହେବା ପୂର୍ବରୁ ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି। ବିବରଣୀ ପାଇଁ କ୍ୟାରିଅର ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।}other{SIMକୁ ବର୍ତ୍ତମାନ ଅକ୍ଷମ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ PUK କୋଡ ଲେଖନ୍ତୁ। SIM ସ୍ଥାୟୀ ଭାବେ ବ୍ୟବହାର ଅଯୋଗ୍ୟ ହେବା ପୂର୍ବରୁ ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି। ବିବରଣୀ ପାଇଁ କ୍ୟାରିଅର ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।}}"</string>
+ <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{SIM PIN ଲେଖନ୍ତୁ। ଆପଣଙ୍କ ଡିଭାଇସକୁ ଅନଲକ କରିବା ପାଇଁ ଆପଣ ଆପଣଙ୍କର କ୍ୟାରିଅର ସହ ନିଶ୍ଚିତରୂପେ କଣ୍ଟାକ୍ଟ କରିବା ପୂର୍ବରୁ ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି।}other{SIM PIN ଲେଖନ୍ତୁ। ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି।}}"</string>
+ <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{SIMକୁ ବର୍ତ୍ତମାନ ଅକ୍ଷମ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ PUK କୋଡ ଲେଖନ୍ତୁ। SIM ସ୍ଥାୟୀ ଭାବେ ବ୍ୟବହାର ଅଯୋଗ୍ୟ ହେବା ପୂର୍ବରୁ ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି। ବିବରଣୀ ପାଇଁ କ୍ୟାରିଅର ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।}other{SIMକୁ ବର୍ତ୍ତମାନ ଅକ୍ଷମ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ PUK କୋଡ ଲେଖନ୍ତୁ। SIM ସ୍ଥାୟୀ ଭାବେ ବ୍ୟବହାର ଅଯୋଗ୍ୟ ହେବା ପୂର୍ବରୁ ଆପଣଙ୍କ ପାଖରେ #ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି। ବିବରଣୀ ପାଇଁ କ୍ୟାରିଅର ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।}}"</string>
<string name="clock_title_default" msgid="6342735240617459864">"ଡିଫଲ୍ଟ"</string>
<string name="clock_title_bubble" msgid="2204559396790593213">"ବବଲ୍"</string>
<string name="clock_title_analog" msgid="8409262532900918273">"ଆନାଲଗ୍"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index e1c7d26..409f727 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ਅਵੈਧ ਕਾਰਡ।"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"ਚਾਰਜ ਹੋ ਗਿਆ"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਬਿਨਾਂ ਤਾਰ ਤੋਂ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਡੌਕ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਚਾਰਜਿੰਗ ਕੁਝ ਸਮੇਂ ਲਈ ਰੋਕੀ ਗਈ"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਬੈਟਰੀ ਦੀ ਸੁਰੱਖਿਆ ਲਈ ਚਾਰਜਿੰਗ ਨੂੰ ਰੋਕਿਆ ਗਿਆ ਹੈ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ਅਣਲਾਕ ਕਰਨ ਲਈ \"ਮੀਨੂ\" ਦਬਾਓ।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ਨੈੱਟਵਰਕ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ਕੋਈ ਸਿਮ ਕਾਰਡ ਨਹੀਂ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index 7cf1784..52bc982 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Nieprawidłowa karta."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Naładowana"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie bezprzewodowe"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie na stacji dokującej"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Szybkie ładowanie"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wolne ładowanie"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie tymczasowo ograniczone"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wstrzymano ładowanie, aby chronić baterię"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Naciśnij Menu, aby odblokować."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieć zablokowana"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Brak karty SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
index 863a419..76ced12 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cartão inválido."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Carregado"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando sem fio"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando na base"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento temporariamente limitado"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • O carregamento foi pausado para proteger a bateria"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Sem chip"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 6073951c..94afc5f 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cartão inválido."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Carregada"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar sem fios"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar na estação de ancoragem"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar…"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar rapidamente…"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar lentamente…"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento limitado temporariamente"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • O carregamento está pausado para proteger a bateria"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prima Menu para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nenhum cartão SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml
index 863a419..76ced12 100644
--- a/packages/SystemUI/res-keyguard/values-pt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cartão inválido."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Carregado"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando sem fio"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando na base"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento temporariamente limitado"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • O carregamento foi pausado para proteger a bateria"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Sem chip"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml
index 5a0dfed..dcc9050 100644
--- a/packages/SystemUI/res-keyguard/values-ro/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Card nevalid"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Încărcată"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă wireless"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Suport de încărcare"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă rapid"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă lent"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Încărcare limitată temporar"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Încărcarea s-a întrerupt pentru a proteja bateria"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Apăsați pe Meniu pentru a debloca."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rețea blocată"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Niciun card SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index a21dd6d..2b8f8d6 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ошибка SIM-карты."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Батарея заряжена"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Беспроводная зарядка"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядка от док-станции"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядка"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"Идет зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"Идет медленная зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядка временно ограничена"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Чтобы продлить срок службы батареи, зарядка приостановлена"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Для разблокировки нажмите \"Меню\"."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Сеть заблокирована"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Нет SIM-карты."</string>
diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml
index 0f828c1..4e911de 100644
--- a/packages/SystemUI/res-keyguard/values-si/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-si/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"වලංගු නොවන කාඩ්පත."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"අරෝපිතයි"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • නොරැහැන්ව ආරෝපණ කෙරේ"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණය වන ඩොකය"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණය වෙමින්"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණය වෙමින්"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින්"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • සෙමින් ආරෝපණය වෙමින්"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණය කිරීම තාවකාලිකව සීමා කර ඇත"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • බැටරිය ආරක්ෂා කිරීම සඳහා ආරෝපණය විරාම කර ඇත"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"අගුලු හැරීමට මෙනුව ඔබන්න."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ජාලය අගුළු දමා ඇත"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM පත නැත"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml
index e98157c..f2d68e3 100644
--- a/packages/SystemUI/res-keyguard/values-sk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Neplatná karta."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Nabité"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa bezdrôtovo"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjací dok"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa rýchlo"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa pomaly"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjanie je dočasne obmedzené"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjanie je pozastavené z dôvodu ochrany batérie"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Odomknete stlačením tlačidla ponuky."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieť je zablokovaná"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Žiadna SIM karta"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml
index 1ad1926..772308f 100644
--- a/packages/SystemUI/res-keyguard/values-sl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Neveljavna kartica"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Baterija napolnjena"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brezžično polnjenje"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Polnjenje na nosilcu"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Polnjenje"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • polnjenje"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • počasno polnjenje"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Polnjenje začasno omejeno"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Zaradi zaščite baterije je polnjenje začasno zaustavljeno"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Če želite odkleniti, pritisnite meni."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Omrežje je zaklenjeno"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Ni kartice SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index 7eb442c..c758462 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Karta e pavlefshme."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"I karikuar"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me valë"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet në stacion"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet ngadalë"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Karikimi përkohësisht i kufizuar"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Karikimi është vendosur në pauzë për të mbrojtur baterinë"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Shtyp \"Meny\" për të shkyçur."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rrjeti është i kyçur"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nuk ka kartë SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml
index 568be9f..e6fe853 100644
--- a/packages/SystemUI/res-keyguard/values-sr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Неважећа картица."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Напуњена је"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бежично пуњење"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Базна станица за пуњење"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуни се"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуни се"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо се пуни"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Споро се пуни"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуњење је привремено ограничено"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуњење је паузирано да би се заштитила батерија"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притисните Мени да бисте откључали."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежа је закључана"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Нема SIM картице"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml
index e0414c8..fa241d9 100644
--- a/packages/SystemUI/res-keyguard/values-sv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ogiltigt kort."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Laddat"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas trådlöst"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Dockningsstation"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas snabbt"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas långsamt"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddning har begränsats tillfälligt"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddningen har pausats för att skydda batteriet"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lås upp genom att trycka på Meny."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Nätverk låst"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Inget SIM-kort"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index 7048364..791bceb 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Kadi si Sahihi."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Betri imejaa"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji bila kutumia waya"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kituo cha Kuchaji"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji kwa kasi"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji pole pole"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kuchaji kumedhibitiwa kwa muda"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Imesitisha kuchaji ili kulinda betri"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Bonyeza Menyu ili kufungua."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mtandao umefungwa"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Hakuna SIM kadi"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index ca51935..271657d 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"செல்லாத சிம் கார்டு."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"சார்ஜ் செய்யப்பட்டது"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வயர்லெஸ் முறையில் சார்ஜாகிறது"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • டாக் மூலம் சார்ஜாகிறது"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜாகிறது"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜாகிறது"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வேகமாகச் சார்ஜாகிறது"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • மெதுவாகச் சார்ஜாகிறது"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜிங் தற்காலிகமாக வரம்பிடப்பட்டுள்ளது"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • பேட்டரியைப் பாதுகாக்க சார்ஜ் ஏறுவது இடைநிறுத்தப்பட்டுள்ளது"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"அன்லாக் செய்ய மெனுவை அழுத்தவும்."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"நெட்வொர்க் பூட்டப்பட்டது"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"சிம் கார்டு இல்லை"</string>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index b6ae96d..f62e667 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"చెల్లని కార్డ్."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"ఛార్జ్ చేయబడింది"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వైర్ లేకుండా ఛార్జ్ అవుతోంది"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జింగ్ డాక్"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జ్ అవుతోంది"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జ్ అవుతోంది"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జింగ్ తాత్కాలికంగా పరిమితం చేయబడింది"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • బ్యాటరీని రక్షించడానికి ఛార్జింగ్ పాజ్ చేయబడింది"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"అన్లాక్ చేయడానికి మెనూను నొక్కండి."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"నెట్వర్క్ లాక్ చేయబడింది"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM కార్డ్ లేదు"</string>
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index 00092bb..62a83bc 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"การ์ดไม่ถูกต้อง"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"ชาร์จแล้ว"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จแบบไร้สาย"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จบนแท่นชาร์จ"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จ"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างเร็ว"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างช้าๆ"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • จำกัดการชาร์จชั่วคราว"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • การชาร์จหยุดชั่วคราวเพื่อปกป้องแบตเตอรี่ของคุณ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"กด \"เมนู\" เพื่อปลดล็อก"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"เครือข่ายถูกล็อก"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ไม่มีซิมการ์ด"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml
index 7b07251..524ea47 100644
--- a/packages/SystemUI/res-keyguard/values-tl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Di-wasto ang Card."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Tapos nang mag-charge"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wireless na nagcha-charge"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging Dock"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nagcha-charge"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nagcha-charge"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabilis na nagcha-charge"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabagal na nagcha-charge"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pansamantalang limitado ang pag-charge"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Naka-pause ang pag-charge para maprotektahan ang baterya"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pindutin ang Menu upang i-unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Naka-lock ang network"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Walang SIM card"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml
index 7ec5642..54aaae3 100644
--- a/packages/SystemUI/res-keyguard/values-tr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Geçersiz Kart."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Şarj oldu"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kablosuz olarak şarj ediliyor"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yuvada Şarj Oluyor"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj oluyor"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj oluyor"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hızlı şarj oluyor"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş şarj oluyor"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj etme geçici olarak sınırlı"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj işlemi pili korumak için duraklatıldı"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmak için Menü\'ye basın."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Ağ kilitli"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM kart yok"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml
index 096adb7f..6144c1c 100644
--- a/packages/SystemUI/res-keyguard/values-uk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Недійсна картка."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Заряджено"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бездротове заряджання"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Док-станція для заряджання"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Швидке заряджання"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Повільне заряджання"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання тимчасово обмежено"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання призупинено, щоб захистити акумулятор"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натисніть меню, щоб розблокувати."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Мережу заблоковано"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Немає SIM-карти"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml
index c30dbfc..4e77841 100644
--- a/packages/SystemUI/res-keyguard/values-ur/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"غلط کارڈ۔"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"چارج ہوگئی"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • وائرلیس طریقے سے چارج ہو رہا ہے"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارجنگ ڈاک"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارج ہو رہا ہے"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارج ہو رہا ہے"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تیزی سے چارج ہو رہا ہے"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آہستہ چارج ہو رہا ہے"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارجنگ عارضی طور پر محدود ہے"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • بیٹری کی حفاظت کے لیے چارجنگ رک گیا ہے"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"غیر مقفل کرنے کیلئے مینو دبائیں۔"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"نیٹ ورک مقفل ہو گیا"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"کوئی SIM کارڈ نہیں ہے"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index dedf432..afaf746 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"SIM karta yaroqsiz."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Quvvat oldi"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Simsiz quvvatlanyapti"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvatlash dok-stansiyasi"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvat olmoqda"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvat olmoqda"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Tezkor quvvat olmoqda"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sekin quvvat olmoqda"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvatlash vaqtincha cheklangan"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvatlash batareyani himoyalash uchun pauza qilindi"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Qulfdan chiqarish uchun Menyu tugmasini bosing."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Tarmoq qulflangan"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM karta solinmagan"</string>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index 9a0eb44..1d6cfa8 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Thẻ không hợp lệ."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Đã sạc đầy"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc không dây"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đế sạc"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc chậm"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Chức năng sạc tạm thời bị hạn chế"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đã tạm dừng sạc để bảo vệ pin"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Nhấn vào Menu để mở khóa."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mạng đã bị khóa"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Không có thẻ SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index 26e3db7..8c8507e 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"SIM 卡无效。"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"已充满电"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在无线充电"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在基座上充电"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充电"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充电"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充电"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在慢速充电"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充电暂时受限"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 为保护电池,充电已暂停"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按“菜单”即可解锁。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"网络已锁定"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"没有 SIM 卡"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
index 2bd2105..c331a92 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"SIM 卡無效。"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"已完成充電"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 無線充電中"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在插座上充電"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充電"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充電"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電暫時受限"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 為保護電池,已暫停充電"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按下 [選單] 即可解鎖。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"網絡已鎖定"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"沒有 SIM 卡"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index a662553..1e1bec3 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"卡片無效。"</string>
<string name="keyguard_charged" msgid="5478247181205188995">"充電完成"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 無線充電"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在座架上充電"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 已暫時限制充電"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 為保護電池,系統已暫停充電"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按選單鍵解鎖。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"網路已鎖定"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"沒有 SIM 卡"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml
index 8c7f8309..c8f78ea 100644
--- a/packages/SystemUI/res-keyguard/values-zu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml
@@ -26,11 +26,11 @@
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ikhadi elingavumelekile."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Kushajiwe"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Iyashaja ngaphandle kwentambo"</string>
- <string name="keyguard_plugged_in_dock" msgid="449722738270908674">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Idokhu Yokushaja"</string>
+ <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Iyashaja"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Iyashaja"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kaningi"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kancane"</string>
- <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ukushaja kukhawulelwe okwesikhashana"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="1709413803451065875">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ukushaja kumisiwe okwesikhashana ukuze kuvikelwe ibhethri"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Chofoza Menyu ukuvula."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Inethiwekhi ivaliwe"</string>
<string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Alikho ikhadi le-SIM."</string>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 8fa2204..d90156d 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -217,7 +217,7 @@
the force lock button. [CHAR LIMIT=80] -->
<string name="kg_prompt_reason_user_request">Device was locked manually</string>
- <!-- Face hint message when finger was not recognized. [CHAR LIMIT=20] -->
+ <!-- Face hint message when face was not recognized. [CHAR LIMIT=20] -->
<string name="kg_face_not_recognized">Not recognized</string>
<!-- Error message indicating that the camera privacy sensor has been turned on [CHAR LIMIT=53] -->
diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml b/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml
index 3bf44a4..acb47f7 100644
--- a/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml
@@ -14,17 +14,15 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<TextClock
+<com.android.systemui.dreams.complication.DoubleShadowTextClock
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/time_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:fontFamily="@font/clock"
+ android:fontFamily="@*android:string/config_clockFontFamily"
android:textColor="@android:color/white"
android:format12Hour="@string/dream_time_complication_12_hr_time_format"
android:format24Hour="@string/dream_time_complication_24_hr_time_format"
- android:shadowColor="@color/keyguard_shadow_color"
- android:shadowRadius="?attr/shadowRadius"
android:fontFeatureSettings="pnum, lnum"
android:letterSpacing="0.02"
android:textSize="@dimen/dream_overlay_complication_clock_time_text_size"/>
diff --git a/packages/SystemUI/res/layout/dream_overlay_media_entry_chip.xml b/packages/SystemUI/res/layout/dream_overlay_media_entry_chip.xml
new file mode 100644
index 0000000..50f3ffc
--- /dev/null
+++ b/packages/SystemUI/res/layout/dream_overlay_media_entry_chip.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+-->
+<ImageView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/media_entry_chip"
+ android:layout_height="@dimen/keyguard_affordance_fixed_height"
+ android:layout_width="@dimen/keyguard_affordance_fixed_width"
+ android:layout_gravity="bottom|start"
+ android:scaleType="center"
+ android:tint="?android:attr/textColorPrimary"
+ android:src="@drawable/ic_music_note"
+ android:background="@drawable/keyguard_bottom_affordance_bg"
+ android:layout_marginStart="@dimen/keyguard_affordance_horizontal_offset"
+ android:layout_marginBottom="@dimen/keyguard_affordance_vertical_offset"
+ android:contentDescription="@string/controls_media_title" />
diff --git a/packages/SystemUI/res/layout/notification_stack_scroll_layout.xml b/packages/SystemUI/res/layout/notification_stack_scroll_layout.xml
new file mode 100644
index 0000000..65cf81e
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_stack_scroll_layout.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+-->
+
+<!-- This XML is served to be overridden by other OEMs/device types. -->
+<com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/notification_stack_scroller"
+ android:layout_marginTop="@dimen/notification_panel_margin_top"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_marginHorizontal="@dimen/notification_panel_margin_horizontal"
+ android:layout_marginBottom="@dimen/notification_panel_margin_bottom"
+ android:importantForAccessibility="no"
+ systemui:layout_constraintStart_toStartOf="parent"
+ systemui:layout_constraintEnd_toEndOf="parent"
+/>
diff --git a/packages/SystemUI/res/layout/people_strip.xml b/packages/SystemUI/res/layout/people_strip.xml
deleted file mode 100644
index ec00429..0000000
--- a/packages/SystemUI/res/layout/people_strip.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2019 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.
- -->
-
-<com.android.systemui.statusbar.notification.stack.PeopleHubView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="@dimen/notification_section_header_height"
- android:paddingStart="4dp"
- android:paddingEnd="4dp"
- android:focusable="true"
- android:clickable="true"
->
-
- <LinearLayout
- android:id="@+id/people_list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginEnd="8dp"
- android:gravity="bottom"
- android:orientation="horizontal"
- android:forceHasOverlappingRendering="false"
- android:clipChildren="false">
-
- <FrameLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="start|center_vertical"
- android:layout_weight="1"
- android:forceHasOverlappingRendering="false">
-
- <TextView
- android:id="@+id/header_label"
- style="@style/TextAppearance.NotificationSectionHeaderButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/notification_section_header_conversations"
- />
-
- </FrameLayout>
-
- <ImageView
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:padding="8dp"
- android:scaleType="fitCenter"
- android:forceHasOverlappingRendering="false"
- android:visibility="gone"
- />
-
- <ImageView
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:padding="8dp"
- android:scaleType="fitCenter"
- android:forceHasOverlappingRendering="false"
- android:visibility="gone"
- />
-
- <ImageView
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:padding="8dp"
- android:scaleType="fitCenter"
- android:forceHasOverlappingRendering="false"
- android:visibility="gone"
- />
-
- <ImageView
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:padding="8dp"
- android:scaleType="fitCenter"
- android:forceHasOverlappingRendering="false"
- android:visibility="gone"
- />
-
- <ImageView
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:padding="8dp"
- android:scaleType="fitCenter"
- android:forceHasOverlappingRendering="false"
- android:visibility="gone"
- />
-
- </LinearLayout>
-
-</com.android.systemui.statusbar.notification.stack.PeopleHubView>
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index 0c847ed..7c86bc7 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -49,7 +49,8 @@
android:id="@+id/user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="center_horizontal" />
+ android:gravity="center_horizontal"
+ android:hyphenationFrequency="full"/>
<ImageView
android:id="@+id/restricted_padlock"
android:layout_width="@dimen/qs_tile_text_size"
diff --git a/packages/SystemUI/res/layout/quick_settings_security_footer.xml b/packages/SystemUI/res/layout/quick_settings_security_footer.xml
index 1b11816..194f3dd 100644
--- a/packages/SystemUI/res/layout/quick_settings_security_footer.xml
+++ b/packages/SystemUI/res/layout/quick_settings_security_footer.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+<!-- TODO(b/242040009): Remove this file. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
diff --git a/packages/SystemUI/res/layout/sidefps_view.xml b/packages/SystemUI/res/layout/sidefps_view.xml
index 921f788..73050c2 100644
--- a/packages/SystemUI/res/layout/sidefps_view.xml
+++ b/packages/SystemUI/res/layout/sidefps_view.xml
@@ -23,4 +23,4 @@
app:lottie_autoPlay="true"
app:lottie_loop="true"
app:lottie_rawRes="@raw/sfps_pulse"
- android:contentDescription="@string/accessibility_fingerprint_label"/>
+ android:importantForAccessibility="no"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 6423a50..f0e49d5 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -109,17 +109,10 @@
systemui:layout_constraintGuide_percent="0.5"
android:orientation="vertical"/>
- <com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
- android:id="@+id/notification_stack_scroller"
- android:layout_marginTop="@dimen/notification_panel_margin_top"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_marginHorizontal="@dimen/notification_panel_margin_horizontal"
- android:layout_marginBottom="@dimen/notification_panel_margin_bottom"
- android:importantForAccessibility="no"
- systemui:layout_constraintStart_toStartOf="parent"
- systemui:layout_constraintEnd_toEndOf="parent"
- />
+ <!-- This layout should always include a version of
+ NotificationStackScrollLayout, as it is expected from
+ NotificationPanelViewController. -->
+ <include layout="@layout/notification_stack_scroll_layout" />
<include layout="@layout/photo_preview_overlay" />
diff --git a/packages/SystemUI/res/layout/volume_panel_dialog.xml b/packages/SystemUI/res/layout/volume_panel_dialog.xml
new file mode 100644
index 0000000..99a1b5c
--- /dev/null
+++ b/packages/SystemUI/res/layout/volume_panel_dialog.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/volume_panel_dialog"
+ android:layout_width="@dimen/large_dialog_width"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/Widget.SliceView.Panel"
+ android:gravity="center_vertical|center_horizontal"
+ android:layout_marginTop="@dimen/dialog_top_padding"
+ android:layout_marginBottom="@dimen/dialog_bottom_padding"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/volume_panel_dialog_title"
+ android:ellipsize="end"
+ android:gravity="center_vertical|center_horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/sound_settings"
+ android:textAppearance="@style/TextAppearance.Dialog.Title"/>
+ </LinearLayout>
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/volume_panel_parent_layout"
+ android:scrollbars="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:minHeight="304dp"
+ android:layout_weight="1"
+ android:overScrollMode="never"/>
+
+ <LinearLayout
+ android:id="@+id/button_layout"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/dialog_button_vertical_padding"
+ android:layout_marginStart="@dimen/dialog_side_padding"
+ android:layout_marginEnd="@dimen/dialog_side_padding"
+ android:layout_marginBottom="@dimen/dialog_bottom_padding"
+ android:baselineAligned="false"
+ android:clickable="false"
+ android:focusable="false">
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_gravity="start|center_vertical"
+ android:orientation="vertical">
+ <Button
+ android:id="@+id/settings_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/volume_panel_dialog_settings_button"
+ android:ellipsize="end"
+ android:maxLines="1"
+ style="@style/Widget.Dialog.Button.BorderButton"
+ android:clickable="true"
+ android:focusable="true"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/dialog_button_horizontal_padding"
+ android:layout_gravity="end|center_vertical">
+ <Button
+ android:id="@+id/done_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/inline_done_button"
+ style="@style/Widget.Dialog.Button"
+ android:maxLines="1"
+ android:ellipsize="end"
+ android:clickable="true"
+ android:focusable="true"/>
+ </LinearLayout>
+ </LinearLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/volume_panel_slice_slider_row.xml b/packages/SystemUI/res/layout/volume_panel_slice_slider_row.xml
new file mode 100644
index 0000000..d1303ed
--- /dev/null
+++ b/packages/SystemUI/res/layout/volume_panel_slice_slider_row.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/slice_slider_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <androidx.slice.widget.SliceView
+ android:id="@+id/slice_view"
+ style="@style/Widget.SliceView.Panel.Slider"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingVertical="@dimen/volume_panel_slice_vertical_padding"
+ android:paddingHorizontal="@dimen/volume_panel_slice_horizontal_padding"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/fingerprint_dialogue_error_to_success_lottie.json b/packages/SystemUI/res/raw/fingerprint_dialogue_error_to_success_lottie.json
new file mode 100644
index 0000000..c5ed827
--- /dev/null
+++ b/packages/SystemUI/res/raw/fingerprint_dialogue_error_to_success_lottie.json
@@ -0,0 +1 @@
+{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":80,"h":80,"nm":"RearFPS_error_to_success","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".green200","cl":"green200","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[28,47,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-10.556,-9.889],[7.444,6.555],[34.597,-20.486]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.658823529412,0.854901960784,0.709803921569,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":10,"s":[0]},{"t":20,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":10,"op":910,"st":10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red200","cl":"red200","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[39.95,40,0],"ix":2,"l":2},"a":{"a":0,"k":[30,30,0],"ix":1,"l":2},"s":{"a":0,"k":[120,120,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-1.721,-7.982],[1.721,-7.982],[1.721,7.5],[-1.721,7.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[30.002,32.488],"ix":2},"a":{"a":0,"k":[0.002,7.488],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.659,0.6],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":0,"s":[100,100]},{"i":{"x":[0.6,0.92],"y":[1,1.096]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":4,"s":[100,110]},{"t":10,"s":[100,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top!","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-1.681,-1.25],[1.681,-1.25],[1.681,2.213],[-1.681,2.213]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[30,38.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.6,0.6],"y":[1,1]},"o":{"x":[0.853,0.853],"y":[0,0]},"t":0,"s":[100,100]},{"i":{"x":[0.92,0.92],"y":[1.06,1.06]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":4,"s":[110,110]},{"t":10,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom!","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":86,"st":-30,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green200","cl":"green200","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":15,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[93.5,93.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.658823529412,0.854901960784,0.709803921569,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":15,"s":[100]}],"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[0]},{"t":20,"s":[4]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":10,"op":21,"st":10,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".red200","cl":"red200","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[100]},{"t":10,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[93.5,93.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[100]},{"t":10,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[100]},{"t":10,"s":[0]}],"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[4]},{"t":10,"s":[0]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":10,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_success_lottie.json b/packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_success_lottie.json
new file mode 100644
index 0000000..3eb95ef
--- /dev/null
+++ b/packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_success_lottie.json
@@ -0,0 +1 @@
+{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":80,"h":80,"nm":"RearFPS_fingerprint_to_success","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".green200","cl":"green200","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[28,47,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-10.556,-9.889],[7.444,6.555],[34.597,-20.486]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.658823529412,0.854901960784,0.709803921569,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":10,"s":[0]},{"t":20,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":10,"op":910,"st":10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".green200","cl":"green200","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":15,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[93.5,93.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.658823529412,0.854901960784,0.709803921569,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":15,"s":[100]}],"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[0]},{"t":20,"s":[4]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":10,"op":21,"st":10,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".colorAccentPrimary","cl":"colorAccentPrimary","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":10,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40.091,40,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.701,0.42],[-1.757,0],[-1.577,-0.381],[-1.485,-0.816]],"o":[[1.455,-0.799],[1.608,-0.397],[1.719,0],[1.739,0.42],[0,0]],"v":[[-9.818,1.227],[-5.064,-0.618],[0,-1.227],[4.96,-0.643],[9.818,1.227]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.446,1.161],[-1.168,0.275],[-1.439,0],[-1.301,-0.304],[-1.225,-0.66],[-1.11,-1.844]],"o":[[1.23,-2.044],[1.024,-0.486],[1.312,-0.31],[1.425,0],[1.454,0.34],[2.122,1.143],[0,0]],"v":[[-13.091,3.273],[-7.438,-1.646],[-4.14,-2.797],[0,-3.273],[4.104,-2.805],[8.141,-1.29],[13.091,3.273]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.53,0],[0,-5.793],[0,0],[2.159,0],[0.59,1.489],[0,0],[1.587,0],[0,-2.16],[-0.81,-1.363],[-0.844,-0.674],[0,0]],"o":[[-0.753,-2.095],[0,-5.793],[6.529,0],[0,0],[0,2.16],[-1.604,0],[0,0],[-0.589,-1.489],[-2.161,0],[0,1.62],[0.54,0.909],[0,0],[0,0]],"v":[[-10.702,5.728],[-11.454,1.506],[0.001,-9],[11.454,1.506],[11.454,1.817],[7.544,5.728],[3.926,3.273],[2.618,0],[-0.997,-2.454],[-4.91,1.457],[-3.657,6.014],[-1.57,8.412],[-0.818,9]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.307,-0.561],[0.894,-0.16],[0.706,0],[0.844,0.193],[0.728,0.334],[0.967,0.901]],"o":[[-1.038,0.967],[-0.817,0.351],[-0.673,0.12],[-0.9,0],[-0.794,-0.182],[-1.203,-0.551],[0,0]],"v":[[8.182,-0.386],[4.642,1.931],[2.07,2.703],[-0.001,2.886],[-2.621,2.591],[-4.909,1.813],[-8.182,-0.386]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey700","cl":"grey700","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.278431385756,0.278431385756,0.278431385756,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":20,"s":[0]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 45a3738..0626058d 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Kan nie gesig herken nie. Gebruik eerder vingerafdruk."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth gekoppel."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batterypersentasie is onbekend."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Gekoppel aan <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ontsluit met gesig. Druk om oop te maak."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Gesig is herken. Druk om oop te maak."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Gesig is herken. Druk die ontsluitikoon om oop te maak."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ontsluit met gesig"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Gesig is herken"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Beweeg links"</item>
<item msgid="5558598599408514296">"Beweeg af"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans vinnig • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans stadig • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laaidok • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Wissel gebruiker"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aftrekkieslys"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle programme en data in hierdie sessie sal uitgevee word."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Welkom terug, gas!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Wiil jy jou sessie voortsit?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Onderskrifteoorlegger"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktiveer"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiveer"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Klank en vibrasie"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Instellings"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Program is vasgespeld"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Dit hou dit in sig totdat jy dit ontspeld. Raak en hou Terug en Oorsig om dit te ontspeld."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Dit hou dit in sig totdat jy dit ontspeld. Raak en hou Terug en Tuis om dit te ontspeld."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index af6357b..651769f 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"መልክን መለየት አልተቻለም። በምትኩ የጣት አሻራ ይጠቀሙ።"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ብሉቱዝ ተያይዟል።"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"የባትሪ መቶኛ አይታወቅም።"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"ከ<xliff:g id="BLUETOOTH">%s</xliff:g> ጋር ተገናኝቷል።"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"በመልክ ተከፍቷል። ለመክፈት ይጫኑ።"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"መልክ ተለይቶ ታውቋል። ለመክፈት ይጫኑ።"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"መልክ ተለይቶ ታውቋል። ለመክፈት የመክፈቻ አዶውን ይጫኑ።"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"በመልክ ተከፍቷል"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"መልክ ተለይቶ ታውቋል"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"ወደ ግራ ውሰድ"</item>
<item msgid="5558598599408514296">"ወደ ታች ውሰድ"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ኃይል በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • የባትሪ ኃይል መሙያ መትከያ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ኃይል በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ተጠቃሚ ቀይር"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ወደታች ተጎታች ምናሌ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"በዚህ ክፍለ-ጊዜ ውስጥ ያሉ ሁሉም መተግበሪያዎች እና ውሂብ ይሰረዛሉ።"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"እንኳን በደህና ተመለሱ እንግዳ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ክፍለ-ጊዜዎን መቀጠል ይፈልጋሉ?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"የሥዕል መግለጫ ጽሑፎች ንብርብር"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"አንቃ"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"አሰናክል"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"መተግበሪያ ተሰክቷል"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል ተመለስ እና አጠቃላይ ዕይታ የሚለውን ይጫኑ እና ይያዙ።"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል ተመለስ እና መነሻ የሚለውን ይንኩ እና ይያዙ።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 1cd0d89..73a9e9b 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -21,7 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"واجهة مستخدم النظام"</string>
<string name="battery_low_title" msgid="5319680173344341779">"هل تريد تفعيل ميزة \"توفير شحن البطارية\"؟"</string>
- <string name="battery_low_description" msgid="3282977755476423966">"يتبقى لديك <xliff:g id="PERCENTAGE">%s</xliff:g> من شحن البطارية. يؤدي استخدام ميزة \"توفير شحن البطارية\" إلى تفعيل وضع \"المظهر الداكن\" وتقييد الأنشطة في الخلفية وتأخير الإشعارات."</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"يتبقى لديك <xliff:g id="PERCENTAGE">%s</xliff:g> من شحن البطارية. يؤدي استخدام ميزة \"توفير شحن البطارية\" إلى تفعيل وضع \"المظهر الداكن\" وحظر الأنشطة في الخلفية وتأخير الإشعارات."</string>
<string name="battery_low_intro" msgid="5148725009653088790">"يؤدي استخدام ميزة \"توفير شحن البطارية\" إلى تفعيل وضع \"المظهر الداكن\" وتقييد الأنشطة في الخلفية وتأخير الإشعارات."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"متبقي <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"يتعذّر الشحن باستخدام USB."</string>
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"يتعذّر التعرّف على الوجه. استخدِم بصمة الإصبع بدلاً من ذلك."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"تم توصيل البلوتوث."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"نسبة شحن البطارية غير معروفة."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"متصل بـ <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"تم فتح قفل جهازك عند تقريبه من وجهك. اضغط لفتح الجهاز."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"تم التعرّف على الوجه. اضغط لفتح الجهاز."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"تم التعرّف على الوجه. اضغط على رمز فتح القفل لفتح الجهاز."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"تم فتح قفل جهازك عند تقريبه من وجهك."</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"تم التعرّف على الوجه."</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"نقل لليسار"</item>
<item msgid="5558598599408514296">"نقل للأسفل"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن سريعًا • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن ببطء • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن على وحدة الإرساء • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تبديل المستخدم"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"القائمة المنسدلة"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"سيتم حذف كل التطبيقات والبيانات في هذه الجلسة."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"مرحبًا بك مجددًا في جلسة الضيف"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"هل تريد متابعة جلستك؟"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"تراكب الشرح"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"تفعيل"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"إيقاف"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"تم تثبيت الشاشة على التطبيق"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. المس مع الاستمرار الزرين \"رجوع\" و\"نظرة عامة\" لإزالة التثبيت."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. المس مع الاستمرار الزرين \"رجوع\" و\"الشاشة الرئيسية\" لإزالة التثبيت."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 1185752..8fe8377 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"মুখাৱয়ব চিনিব নোৱাৰি। ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক।"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ব্লুটুথ সংযোগ হ’ল।"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"বেটাৰীৰ চাৰ্জৰ শতাংশ অজ্ঞাত।"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>ৰ লগত সংযোগ কৰা হ’ল।"</string>
@@ -300,7 +304,7 @@
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"অৱলোকন ট’গল কৰক"</string>
<string name="zen_priority_introduction" msgid="3159291973383796646">"আপুনি নিৰ্দিষ্ট কৰা এলাৰ্ম, ৰিমাইণ্ডাৰ, ইভেন্ট আৰু কল কৰোঁতাৰ বাহিৰে আন কোনো শব্দৰ পৰা আপুনি অসুবিধা নাপাব। কিন্তু, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি আপুনি প্লে কৰিব খোজা যিকোনো বস্তু তথাপি শুনিব পাৰিব।"</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"আপুনি নিৰ্দিষ্ট কৰা এলাৰ্মৰ বাহিৰে আন কোনো ধ্বনি আৰু কম্পনৰ পৰা আপুনি অসুবিধা নাপাব। কিন্তু, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি আপুনি প্লে কৰিব খোজা যিকোনো বস্তু তথাপি শুনিব পাৰিব।"</string>
- <string name="zen_priority_customize_button" msgid="4119213187257195047">"নিজৰ উপযোগিতা অনুসৰি"</string>
+ <string name="zen_priority_customize_button" msgid="4119213187257195047">"কাষ্টমাইজ কৰক"</string>
<string name="zen_silence_introduction_voice" msgid="853573681302712348">"এই কার্যই এলার্ম, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি আটাইবোৰৰ বাবে ধ্বনি আৰু কম্পন অৱৰোধ কৰিব। আপুনি ফ\'ন কল তথাপি কৰিবলৈ সক্ষম হ\'ব।"</string>
<string name="zen_silence_introduction" msgid="6117517737057344014">"এই কার্যই এলার্ম, মিউজিক, ভিডিঅ\' আৰু গেইমকে ধৰি আটাইবোৰৰ ধ্বনি আৰু কম্পন অৱৰোধ কৰে।"</string>
<string name="notification_tap_again" msgid="4477318164947497249">"খুলিবলৈ পুনৰাই টিপক"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। খুলিবলৈ টিপক।"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। খুলিবলৈ টিপক।"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। খুলিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"মুখাৱয়ব চিনাক্ত কৰা হৈছে"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"বাওঁফাললৈ নিয়ক"</item>
<item msgid="5558598599408514296">"তললৈ নিয়ক"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • দ্ৰুতগতিৰে চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • লাহে লাহে চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চাৰ্জিং ডক • সম্পূৰ্ণ হ’বলৈ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগিব"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ব্যৱহাৰকাৰী সলনি কৰক"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"পুল-ডাউনৰ মেনু"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই ছেশ্বনৰ আটাইবোৰ এপ্ আৰু ডেটা মচা হ\'ব।"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"অতিথি, আপোনাক পুনৰ স্বাগতম!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"আপুনি আপোনাৰ ছেশ্বন অব্যাহত ৰাখিব বিচাৰেনে?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"কেপশ্বন অভাৰলে’"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"সক্ষম কৰক"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"অক্ষম কৰক"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"এপ্টো পিন কৰা আছে"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"এই কাৰ্যই আপুনি আনপিন নকৰালৈকে ইয়াক দেখা পোৱা অৱস্থাত ৰাখে। আনপিন কৰিবলৈ \'পিছলৈ যাওক\' আৰু \'অৱলোকন\'-ত স্পৰ্শ কৰি থাকক।"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"এই কাৰ্যই আপুনি আনপিন নকৰালৈকে ইয়াক দেখা পোৱা অৱস্থাত ৰাখে। আনপিন কৰিবলৈ পিছলৈ যাওক আৰু হ\'মত স্পৰ্শ কৰি সেঁচি ধৰক।"</string>
@@ -527,7 +536,7 @@
<string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ জাননী নিয়ন্ত্ৰণসমূহ খোলা অৱস্থাত আছে"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="1561909368876911701">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ জাননী নিয়ন্ত্ৰণসমূহ বন্ধ অৱস্থাত আছে"</string>
<string name="notification_more_settings" msgid="4936228656989201793">"অধিক ছেটিং"</string>
- <string name="notification_app_settings" msgid="8963648463858039377">"নিজৰ উপযোগিতা অনুসৰি"</string>
+ <string name="notification_app_settings" msgid="8963648463858039377">"কাষ্টমাইজ কৰক"</string>
<string name="notification_conversation_bubble" msgid="2242180995373949022">"বাবল হিচাপে দেখুৱাওক"</string>
<string name="notification_conversation_unbubble" msgid="6908427185031099868">"Bubbles আঁতৰাওক"</string>
<string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 6dfb616..15aff51 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tanımaq olmur. Barmaq izini işlədin."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth qoşulub."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batareyanın faizi naməlumdur."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> üzərindən qoşuldu."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Üz ilə kiliddən çıxarılıb. Açmaq üçün basın."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Üz tanınıb. Açmaq üçün basın."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Üz tanınıb. \"Kiliddən çıxar\" ikonasına basıb açın."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Üz ilə kiliddən çıxarılıb"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Üz tanınıb"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Sola köçürün"</item>
<item msgid="5558598599408514296">"Aşağı köçürün"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sürətlə şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Asta şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj Doku • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aşağı çəkilən menyu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu sessiyada bütün tətbiqlər və data silinəcək."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Xoş gəlmisiniz!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Sessiya davam etsin?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Subtitr başlığı"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktiv edin"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiv edin"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Tətbiq bərkidilib"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Geri və İcmal düymələrinə basıb saxlayın."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"\"Geri\" və \"Əsas ekran\" düymələrinin davamlı basılması ilə çıxarılana qədər tətbiq göz önündə qalır."</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index f26cb36..fad5f18 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Lice nije prepoznato. Koristite otisak prsta."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth je priključen."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procenat napunjenosti baterije nije poznat."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Povezani ste sa <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Otključano je licem. Pritisnite da biste otvorili."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Lice je prepoznato. Pritisnite da biste otvorili."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Lice prepoznato. Pritisnite ikonu otključavanja da biste otvorili."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Otključano je licem"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Lice je prepoznato"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Pomerite nalevo"</item>
<item msgid="5558598599408514296">"Pomerite nadole"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Puni se • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brzo se puni • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo se puni • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Bazna stanica za punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Puni se • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Zameni korisnika"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući meni"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci u ovoj sesiji će biti izbrisani."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Dobro došli nazad, goste!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li da nastavite sesiju?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Preklapanje titlova"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"omogućite"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"onemogućite"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacija je zakačena"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Na ovaj način se ovo stalno prikazuje dok ga ne otkačite. Dodirnite i zadržite Nazad i Pregled da biste ga otkačili."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Na ovaj način se ovo stalno prikazuje dok ga ne otkačite. Dodirnite i zadržite Nazad i Početna da biste ga otkačili."</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 4257e3f..bcf4e05 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Твар не распазнаны. Скарыстайце адбітак пальца."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-сувязь."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Працэнт зараду акумулятара невядомы."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Падлучаны да <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Разблакіравана распазнаваннем твару. Націсніце, каб адкрыць."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Твар распазнаны. Націсніце, каб адкрыць."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Твар распазнаны. Для адкрыцця націсніце значок разблакіроўкі."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Разблакіравана распазнаваннем твару"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Твар распазнаны"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Перамясціце палец улева"</item>
<item msgid="5558598599408514296">"Перамясціце палец ніжэй"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе хуткая зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе павольная зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе зарадка праз док-станцыю • Поўнасцю зарадзіцца праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Перайсці да іншага карыстальніка"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"высоўнае меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усе праграмы і даныя гэтага сеанса будуць выдалены."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"З вяртаннем, госць!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Хочаце працягнуць сеанс?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Накладанне субцітраў"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"уключыць"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"адключыць"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Праграма замацавана"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Будзе паказвацца, пакуль не адмацуеце. Каб адмацаваць, краніце і ўтрымлівайце кнопкі \"Назад\" і \"Агляд\"."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Будзе паказвацца, пакуль не адмацуеце. Каб адмацаваць, націсніце і ўтрымлівайце кнопкі \"Назад\" і \"Галоўны экран\"."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index e2f83f6..8515d92 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Лицето не е разпознато. Използвайте отпечатък."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth е включен."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Процентът на батерията е неизвестен."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Има връзка с <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -217,11 +221,11 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Вход"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Слухови апарати"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Включва се..."</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Автоматична ориентация"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Авт. ориентация"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Автоматично завъртане на екрана"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Местоположение"</string>
<string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Скрийнсейвър"</string>
- <string name="quick_settings_camera_label" msgid="5612076679385269339">"Достъп до камерата"</string>
+ <string name="quick_settings_camera_label" msgid="5612076679385269339">"Камера: достъп"</string>
<string name="quick_settings_mic_label" msgid="8392773746295266375">"Достъп до микрофона"</string>
<string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Налице"</string>
<string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Блокирано"</string>
@@ -239,7 +243,7 @@
<string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Няма налични устройства"</string>
<string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"не е установена връзка с Wi-Fi"</string>
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яркост"</string>
- <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Инвертиране на цветовете"</string>
+ <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Цветове: инверт."</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекция на цветове"</string>
<string name="quick_settings_more_user_settings" msgid="1064187451100861954">"Потребителски настройки"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Готово"</string>
@@ -261,7 +265,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Ограничение от <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Служебни приложения"</string>
- <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Нощно осветление"</string>
+ <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Нощно осветл."</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Ще се вкл. по залез"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"До изгрев"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Ще се включи в <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Отключено с лице. Натиснете за отваряне."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Лицето бе разпознато. Натиснете за отваряне."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лицето бе разпознато. Отворете чрез иконата за отключване."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Отключено с лице"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Лицето бе разпознато"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Преместване наляво"</item>
<item msgid="5558598599408514296">"Преместване надолу"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бързо • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бавно • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Докинг станция за зареждане • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Превключване между потребителите"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"падащо меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Всички приложения и данни в тази сесия ще бъдат изтрити."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Добре дошли отново в сесията като гост!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Искате ли да продължите сесията си?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Наслагване на надписите"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"активиране"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"деактивиране"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Приложението е фиксирано"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Екранът ще се показва, докато не го освободите с докосване и задържане на бутона за връщане назад и този за общ преглед."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Екранът ще се показва, докато не го освободите с докосване и задържане на бутона за връщане назад и „Начало“."</string>
@@ -471,7 +480,7 @@
<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>
- <string name="qr_code_scanner_title" msgid="5290201053875420785">"Сканиране на QR код"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR код: сканиране"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Потребителски профил в Work"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Самолетен режим"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Няма да чуете следващия си будилник в <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -538,7 +547,7 @@
<string name="snoozed_for_time" msgid="7586689374860469469">"Отложено за <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# час}=2{# часа}other{# часа}}"</string>
<string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# минута}other{# минути}}"</string>
- <string name="battery_detail_switch_title" msgid="6940976502957380405">"Режим за запазване на батерията"</string>
+ <string name="battery_detail_switch_title" msgid="6940976502957380405">"Запазване на батерията"</string>
<string name="keyboard_key_button_template" msgid="8005673627272051429">"Бутон „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
<string name="keyboard_key_home" msgid="3734400625170020657">"Начало"</string>
<string name="keyboard_key_back" msgid="4185420465469481999">"Назад"</string>
@@ -588,7 +597,7 @@
<string name="accessibility_long_click_tile" msgid="210472753156768705">"Отваряне на настройките"</string>
<string name="accessibility_status_bar_headphones" msgid="1304082414912647414">"Слушалките (без микрофон) са свързани"</string>
<string name="accessibility_status_bar_headset" msgid="2699275863720926104">"Слушалките са свързани"</string>
- <string name="data_saver" msgid="3484013368530820763">"Икономия на данни"</string>
+ <string name="data_saver" msgid="3484013368530820763">"Данни: икономия"</string>
<string name="accessibility_data_saver_on" msgid="5394743820189757731">"Функцията „Икономия на данни“ е включена"</string>
<string name="switch_bar_on" msgid="1770868129120096114">"Вкл."</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Изкл."</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 277eeb7..9e257cd 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"মুখ শনাক্ত করতে পারছি না। পরিবর্তে আঙ্গুলের ছাপ ব্যবহার করুন।"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ব্লুটুথ সংযুক্ত হয়েছে৷"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ব্যাটারি কত শতাংশ আছে তা জানা যায়নি।"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>এ সংযুক্ত হয়ে আছে।"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"ফেসের সাহায্যে আনলক করা হয়েছে। খোলার জন্য প্রেস করুন।"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"ফেস শনাক্ত করা হয়েছে। খোলার জন্য প্রেস করুন।"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ফেস শনাক্ত করা হয়েছে। খোলার জন্য আনলক আইকন প্রেস করুন।"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ফেস দেখিয়ে আনলক করা হয়েছে"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ফেস চিনে নেওয়া হয়েছে"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"বাঁদিকে সরান"</item>
<item msgid="5558598599408514296">"নিচে নামান"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চার্জিং • পুরো চার্জ হতে <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগবে"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • দ্রুত চার্জ হচ্ছে • পুরো চার্জ হতে <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগবে"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ধীরে চার্জ হচ্ছে • পুরো চার্জ হতে <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগবে"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চার্জিং ডক • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-এর মধ্যে সম্পূর্ণ হয়ে যাবে"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চার্জ হচ্ছে • পুরো চার্জ হতে আরও <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> সময় লাগবে"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ব্যবহারকারী পাল্টে দিন"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"পুলডাউন মেনু"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই সেশনের সব অ্যাপ ও ডেটা মুছে ফেলা হবে।"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"অতিথি, আপনি ফিরে আসায় আপনাকে স্বাগত!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"আপনি কি আপনার সেশনটি চালিয়ে যেতে চান?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"ক্যাপশন ওভারলে"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"চালু হবে"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"বন্ধ হবে"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"সাউন্ড ও ভাইব্রেশন"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"সেটিংস"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"অ্যাপ পিন করা হয়েছে"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"এটি আপনি আনপিন না করা পর্যন্ত এটিকে প্রদর্শিত করবে৷ আনপিন করতে ফিরুন এবং ওভারভিউ স্পর্শ করে ধরে থাকুন।"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"এর ফলে আপনি এটি আনপিন না করা পর্যন্ত এটি দেখানো হতে থাকবে। আনপিন করতে \"ফিরে যান\" এবং \"হোম\" বোতামদুটি ট্যাপ করে ধরে রাখুন।"</string>
@@ -548,7 +555,7 @@
<string name="keyboard_key_dpad_right" msgid="6282105433822321767">"ডান"</string>
<string name="keyboard_key_dpad_center" msgid="4079412840715672825">"কেন্দ্র"</string>
<string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
- <string name="keyboard_key_space" msgid="6980847564173394012">"স্পেস"</string>
+ <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
<string name="keyboard_key_enter" msgid="8633362970109751646">"এন্টার"</string>
<string name="keyboard_key_backspace" msgid="4095278312039628074">"ব্যাকস্পেস"</string>
<string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"প্লে/বিরতি"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 0fe6121..d3c8ef6 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nije moguće prepoznati lice. Koristite otisak prsta."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth je povezan."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Postotak napunjenosti baterije nije poznat"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Povezan na <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Otključano licem. Pritisnite da otvorite."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Lice prepoznato. Pritisnite da otvorite."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Lice prepoznato. Pritisnite ikonu za otklj. da otvorite."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Otključano je licem"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Lice je prepoznato"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Pomjeranje ulijevo"</item>
<item msgid="5558598599408514296">"Pomjeranje nadolje"</item>
@@ -337,9 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brzo punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Priključna stanica za punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Zamijeni korisnika"</string>
- <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući izbornik"</string>
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući meni"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci iz ove sesije će se izbrisati."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Zdravo! Lijepo je opet vidjeti goste."</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li nastaviti sesiju?"</string>
@@ -417,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Preklapanje titlova"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"omogući"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"onemogući"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacija je zakačena"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Ekran ostaje prikazan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Nazad."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Na ovaj način ekran ostaje prikazan dok ga ne otkačite. Da otkačite ekran, dodirnite i držite dugme Nazad i Početna."</string>
@@ -547,7 +557,7 @@
<string name="keyboard_key_dpad_right" msgid="6282105433822321767">"Desno"</string>
<string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Sredina"</string>
<string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
- <string name="keyboard_key_space" msgid="6980847564173394012">"Razmaknica"</string>
+ <string name="keyboard_key_space" msgid="6980847564173394012">"Tipka za razmak"</string>
<string name="keyboard_key_enter" msgid="8633362970109751646">"Tipka za novi red"</string>
<string name="keyboard_key_backspace" msgid="4095278312039628074">"Tipka za brisanje"</string>
<string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"Pokreni/pauziraj"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 15127b8..20e2574 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No podem detectar la cara. Usa l\'empremta digital."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connectat."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Es desconeix el percentatge de bateria."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"S\'ha connectat a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"S\'ha desbloquejat amb la cara. Prem per obrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"S\'ha reconegut la cara. Prem per obrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"S\'ha reconegut la cara. Prem la icona per obrir."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"S\'ha desbloquejat amb la cara"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"S\'ha reconegut la cara"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Mou cap a l\'esquerra"</item>
<item msgid="5558598599408514296">"Mou cap avall"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • S\'està carregant • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant ràpidament • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant lentament • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Base de càrrega • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • S\'està carregant • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Canvia d\'usuari"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú desplegable"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Totes les aplicacions i les dades d\'aquesta sessió se suprimiran."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Benvingut de nou, convidat."</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vols continuar amb la sessió?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Superposició de subtítols"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"activar"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desactivar"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"L\'aplicació està fixada"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Aquest element es continuarà mostrant fins que deixis de fixar-lo. Per fer-ho, toca i mantén premudes els botons Enrere i Aplicacions recents."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Aquest element es continuarà mostrant fins que deixis de fixar-lo. Per fer-ho, mantén premuts els botons Enrere i Inici."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 4da7e6f..f7e116f 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Obličej se nepodařilo rozpoznat. Použijte místo něj otisk prstu."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Rozhraní Bluetooth je připojeno."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procento baterie není známé."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Připojeno k zařízení <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Odemknuto obličejem. Stisknutím otevřete."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Obličej rozpoznán. Stisknutím otevřete."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Obličej rozpoznán. Klepněte na ikonu odemknutí."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Odemknuto obličejem"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Obličej rozpoznán"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Přesunout doleva"</item>
<item msgid="5558598599408514296">"Přesunout dolů"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rychlé nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Pomalé nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíjecí dok • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Přepnout uživatele"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rozbalovací nabídka"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Veškeré aplikace a data v této relaci budou vymazána."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Vítejte zpět v relaci hosta!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Chcete v relaci pokračovat?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Překryvná vrstva titulků"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktivovat"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktivovat"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Aplikace je připnutá"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Obsah bude připnut v zobrazení, dokud jej neuvolníte. Uvolníte jej stisknutím a podržením tlačítek Zpět a Přehled."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Obsah bude připnut v zobrazení, dokud ho neuvolníte. Uvolníte ho podržením tlačítek Zpět a Plocha."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 59732ef..23e00fc 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansigtet kan ikke genkendes. Brug fingeraftryk i stedet."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth tilsluttet."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batteriniveauet er ukendt."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Tilsluttet <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Låst op ved hjælp af ansigt. Tryk for at åbne."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Ansigt genkendt. Tryk for at åbne."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ansigt genkendt. Tryk på oplåsningsikonet for at åbne."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Låst op via ansigtsgenkendelse"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ansigtet er genkendt"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Flyt til venstre"</item>
<item msgid="5558598599408514296">"Flyt ned"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader hurtigt • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader langsomt • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader i dockingstation • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Skift bruger"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullemenu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps og data i denne session slettes."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Velkommen tilbage, gæst!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vil du fortsætte din session?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Overlejrede undertekster"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktivér"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiver"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Appen er fastgjort"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Dette fastholder skærmen i visningen, indtil du frigør den. Tryk på Tilbage og Overblik, og hold fingeren nede for at frigøre skærmen."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Dette fastholder skærmen i visningen, indtil du frigør den. Hold Tilbage og Startskærm nede for at frigøre skærmen."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index bbac4f0..08fa40e 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Gesicht wurde nicht erkannt. Verwende stattdessen den Fingerabdruck."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Mit Bluetooth verbunden"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akkustand unbekannt."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Mit <xliff:g id="BLUETOOTH">%s</xliff:g> verbunden"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Gerät mit dem Gesicht entsperrt. Tippe zum Öffnen."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Gesicht erkannt. Tippe zum Öffnen."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Gesicht erkannt. Tippe zum Öffnen auf das Symbol „Entsperren“."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Gerät mit Gesicht entsperrt"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Gesicht erkannt"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Nach links bewegen"</item>
<item msgid="5558598599408514296">"Nach unten bewegen"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird schnell geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird langsam geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ladestation • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Nutzer wechseln"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Pull-down-Menü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle Apps und Daten in dieser Sitzung werden gelöscht."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Willkommen zurück im Gastmodus"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Möchtest du deine Sitzung fortsetzen?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Untertitel-Overlay"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktivieren"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktivieren"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Ton & Vibration"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Einstellungen"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"App ist auf dem Bildschirm fixiert"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Die App bleibt so lange auf dem Bildschirm fixiert, bis du die Fixierung aufhebst. Berühre und halte dazu \"Zurück\" und \"Übersicht\"."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Die App bleibt so lange auf dem Bildschirm fixiert, bis du die Fixierung aufhebst. Berühre und halte dazu \"Zurück\" und \"Startbildschirm\"."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index ed44366..7237488 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Το πρόσωπο δεν αναγνωρίζεται. Χρησιμ. δακτ. αποτ."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Το Bluetooth είναι συνδεδεμένο."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Άγνωστο ποσοστό μπαταρίας."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Συνδέθηκε στο <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ξεκλείδωμα με αναγνώριση προσώπου. Πατήστε για άνοιγμα."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Το πρόσωπο αναγνωρίστηκε. Πατήστε για άνοιγμα."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Το πρόσωπο αναγνωρ. Πατήστ. το εικον. ξεκλειδ. για άνοιγμα."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ξεκλείδωμα με αναγνώριση προσώπου"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Το πρόσωπο αναγνωρίστηκε"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Μετακίνηση αριστερά"</item>
<item msgid="5558598599408514296">"Μετακίνηση κάτω"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Γρήγορη φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Αργή φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Βάση φόρτισης • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Εναλλαγή χρήστη"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"αναπτυσσόμενο μενού"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Όλες οι εφαρμογές και τα δεδομένα αυτής της περιόδου σύνδεσης θα διαγραφούν."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Kαλώς ορίσατε ξανά!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Θέλετε να συνεχίσετε την περίοδο σύνδεσής σας;"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Επικάλυψη υπότιτλων"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ενεργοποίηση"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"απενεργοποίηση"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Ήχος και δόνηση"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ρυθμίσεις"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Η εφαρμογή είναι καρφιτσωμένη."</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Με αυτόν τον τρόπο παραμένει σε προβολή μέχρι να το ξεκαρφιτσώσετε. Αγγίξτε παρατεταμένα τα στοιχεία \"Επιστροφή\" και \"Επισκόπηση\" για ξεκαρφίτσωμα."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Με αυτόν τον τρόπο, παραμένει σε προβολή μέχρι να το ξεκαρφιτσώσετε. Αγγίξτε παρατεταμένα τα στοιχεία \"Πίσω\" και \"Αρχική οθόνη\" για ξεκαρφίτσωμα."</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index c8ccb36..47bf1b4 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -161,6 +161,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <string name="keyguard_face_failed" msgid="9044619102286917151">"Can’t recognise face"</string>
+ <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use fingerprint instead"</string>
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connected."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +314,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognised"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Move left"</item>
<item msgid="5558598599408514296">"Move down"</item>
@@ -337,7 +341,7 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging dock • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -417,6 +421,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Captions overlay"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"enable"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 186679e..867deb4 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -161,6 +161,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <string name="keyguard_face_failed" msgid="9044619102286917151">"Can’t recognise face"</string>
+ <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use fingerprint instead"</string>
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connected."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +314,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognised"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Move left"</item>
<item msgid="5558598599408514296">"Move down"</item>
@@ -337,7 +341,7 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging dock • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -417,6 +421,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Captions overlay"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"enable"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index c8ccb36..47bf1b4 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -161,6 +161,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <string name="keyguard_face_failed" msgid="9044619102286917151">"Can’t recognise face"</string>
+ <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use fingerprint instead"</string>
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connected."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +314,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognised"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Move left"</item>
<item msgid="5558598599408514296">"Move down"</item>
@@ -337,7 +341,7 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging dock • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -417,6 +421,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Captions overlay"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"enable"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index c8ccb36..47bf1b4 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -161,6 +161,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <string name="keyguard_face_failed" msgid="9044619102286917151">"Can’t recognise face"</string>
+ <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use fingerprint instead"</string>
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connected."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +314,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognised"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Move left"</item>
<item msgid="5558598599408514296">"Move down"</item>
@@ -337,7 +341,7 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging dock • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -417,6 +421,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Captions overlay"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"enable"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 754a7f6..f903c96 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -161,6 +161,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognize face. Use fingerprint instead."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <string name="keyguard_face_failed" msgid="9044619102286917151">"Can’t recognize face"</string>
+ <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use fingerprint instead"</string>
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connected."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +314,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognized. Press to open."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognized. Press the unlock icon to open."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognized"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Move left"</item>
<item msgid="5558598599408514296">"Move down"</item>
@@ -337,7 +341,7 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging Dock • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -417,6 +421,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Captions overlay"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"enable"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Sound & vibration"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 8a1f4ad..ce489d2 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No se reconoce el rostro. Usa la huella dactilar."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Se desconoce el porcentaje de la batería."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>"</string>
@@ -221,7 +225,7 @@
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Girar la pantalla automáticamente"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Ubicación"</string>
<string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Protector de pantalla"</string>
- <string name="quick_settings_camera_label" msgid="5612076679385269339">"Acceso a la cámara"</string>
+ <string name="quick_settings_camera_label" msgid="5612076679385269339">"Acceso a cámara"</string>
<string name="quick_settings_mic_label" msgid="8392773746295266375">"Acceso al mic."</string>
<string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Disponible"</string>
<string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Bloqueado"</string>
@@ -239,8 +243,8 @@
<string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"No hay dispositivos disponibles"</string>
<string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Red Wi-Fi no conectada"</string>
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillo"</string>
- <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversión de color"</string>
- <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corrección de colores"</string>
+ <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Invertir colores"</string>
+ <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corregir colores"</string>
<string name="quick_settings_more_user_settings" msgid="1064187451100861954">"Configuración del usuario"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Listo"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Cerrar"</string>
@@ -280,7 +284,7 @@
<string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Grabación de pantalla"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Detener"</string>
- <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo de una mano"</string>
+ <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo una mano"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"¿Quieres desbloquear el micrófono del dispositivo?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"¿Quieres desbloquear la cámara del dispositivo?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"¿Quieres desbloquear la cámara y el micrófono del dispositivo?"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Desbloqueo con rostro. Presiona para abrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Rostro reconocido. Presiona para abrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rostro reconocido. Presiona el desbloqueo para abrir."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Se desbloqueó con el rostro"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Se reconoció el rostro"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Mover hacia la izquierda"</item>
<item msgid="5558598599408514296">"Mover hacia abajo"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lento • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Conectado y cargando • Carga completa en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar usuario"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú expandible"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán las aplicaciones y los datos de esta sesión."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"¡Hola de nuevo, invitado!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"¿Quieres retomar la sesión?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Superposición de subtítulos"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"habilitar"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"inhabilitar"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Sonido y vibración"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configuración"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"La app está fijada"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Esta función mantiene la pantalla visible hasta que dejes de fijarla. Para ello, mantén presionados los botones Atrás y Recientes."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Esta función mantiene la pantalla visible hasta que dejes de fijarla. Para ello, mantén presionados los botones de inicio y Atrás."</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 44e9cf2..89ee62d 100644
--- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
@@ -78,8 +78,8 @@
</string-array>
<string-array name="tile_states_location">
<item msgid="3316542218706374405">"No disponible"</item>
- <item msgid="4813655083852587017">"Desactivado"</item>
- <item msgid="6744077414775180687">"Activado"</item>
+ <item msgid="4813655083852587017">"Desactivada"</item>
+ <item msgid="6744077414775180687">"Activada"</item>
</string-array>
<string-array name="tile_states_hotspot">
<item msgid="3145597331197351214">"No disponible"</item>
@@ -133,8 +133,8 @@
</string-array>
<string-array name="tile_states_reduce_brightness">
<item msgid="1839836132729571766">"No disponible"</item>
- <item msgid="4572245614982283078">"Desactivado"</item>
- <item msgid="6536448410252185664">"Activado"</item>
+ <item msgid="4572245614982283078">"Desactivada"</item>
+ <item msgid="6536448410252185664">"Activada"</item>
</string-array>
<string-array name="tile_states_cameratoggle">
<item msgid="6680671247180519913">"No disponible"</item>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 997cba7..df7c083 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No se reconoce la cara. Usa la huella digital."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentaje de batería desconocido."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Desbloqueado con la cara. Pulsa para abrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Cara reconocida. Pulsa para abrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Cara reconocida. Pulsa el icono de desbloquear para abrir."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Desbloqueado con la cara"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Cara reconocida"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Mover hacia la izquierda"</item>
<item msgid="5558598599408514296">"Mover hacia abajo"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • En <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> terminará de cargarse"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida • En <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> terminará de cargarse"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • En <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> terminará de cargarse"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Base de carga • En <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> terminará de cargar"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Carga completa en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar de usuario"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú desplegable"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán todas las aplicaciones y datos de esta sesión."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"¡Hola de nuevo, invitado!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"¿Quieres continuar con tu sesión?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Superposición de subtítulos"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"activar"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desactivar"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Aplicación fijada"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"La aplicación se mantendrá visible hasta que dejes de fijarla. Para dejar de fijarla, mantén pulsados los botones Atrás y Aplicaciones recientes."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"La aplicación se mantendrá visible hasta que dejes de fijarla. Para dejar de fijarla, mantén pulsados los botones Atrás e Inicio."</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 3210181..d85c818 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nägu ei õnnestu tuvastada. Kasutage sõrmejälge."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth on ühendatud."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Aku laetuse protsent on teadmata."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ühendatud: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Avati näoga. Avamiseks vajutage."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Nägu tuvastati. Avamiseks vajutage."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Nägu tuvastati. Avamiseks vajutage avamise ikooni."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Avati näoga"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Nägu tuvastati"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Teisalda vasakule"</item>
<item msgid="5558598599408514296">"Teisalda alla"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kiirlaadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Aeglane laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimisdokk • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kasutaja vahetamine"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rippmenüü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Seansi kõik rakendused ja andmed kustutatakse."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Tere tulemast tagasi, külaline!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Kas soovite seansiga jätkata?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Subtiitrite ülekate"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"luba"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"keela"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Rakendus on kinnitatud"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"See hoitakse kuval, kuni selle vabastate. Vabastamiseks puudutage pikalt nuppe Tagasi ja Ülevaade."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"See hoitakse kuval, kuni selle vabastate. Vabastamiseks puudutage pikalt nuppe Tagasi ja Avakuva."</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 3a8f9af..a36f923 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ezin da hauteman aurpegia. Erabili hatz-marka."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-a konektatuta."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Bateriaren ehunekoa ezezaguna da."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> gailura konektatuta."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Aurpegiaren bidez desblokeatu da. Sakatu irekitzeko."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Ezagutu da aurpegia. Sakatu irekitzeko."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ezagutu da aurpegia. Irekitzeko, sakatu desblokeatzeko ikonoa."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Aurpegiaren bidez desblokeatu da"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ezagutu da aurpegia"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Eraman ezkerrera"</item>
<item msgid="5558598599408514296">"Eraman behera"</item>
@@ -337,7 +343,7 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Bizkor kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mantso kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oinarrian kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Aldatu erabiltzailea"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"zabaldu menua"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Saioko aplikazio eta datu guztiak ezabatuko dira."</string>
@@ -417,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Azpititulu gainjarriak"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"gaitu"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desgaitu"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Aplikazioa ainguratuta dago"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta \"Atzera\" eta \"Ikuspegi orokorra\" botoiak."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta Atzera eta Hasiera botoiak."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 33a1b87..4ba5ede 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"چهره شناسایی نشد. درعوض از اثر انگشت استفاده کنید."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"بلوتوث متصل است."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"درصد شارژ باتری مشخص نیست."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"به <xliff:g id="BLUETOOTH">%s</xliff:g> متصل شد."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"قفلْ با چهره باز شد. برای باز کردن، فشار دهید."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"چهره شناسایی شد. برای باز کردن، فشار دهید."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"چهره شناسایی شد. برای باز کردن، نماد قفلگشایی را فشار دهید."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"قفل با چهره باز شد"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"چهره شناسایی شد"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"انتقال بهچپ"</item>
<item msgid="5558598599408514296">"انتقال بهپایین"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ کردن • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ کردن سریع • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ کردن آهسته • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • پایه شارژ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ شدن • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تغییر کاربر"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"منوی پایینپر"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"همه برنامهها و دادههای این جلسه حذف خواهد شد."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"مهمان گرامی، بازگشتتان را خوش آمد میگوییم!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"آیا میخواهید جلسهتان را ادامه دهید؟"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"همپوشانی زیرنویس ناشنوایان"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"فعال کردن"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"غیرفعال کردن"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"برنامه سنجاق شده است"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"تا زمانی که سنجاق را برندارید، در نما نگهداشته میشود. برای برداشتن سنجاق، «برگشت» و «نمای کلی» را لمس کنید و نگهدارید."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"تا برداشتن سنجاق، در نما نگهداشته میشود. برای برداشتن سنجاق، «برگشت» و «صفحه اصلی» را لمس کنید و نگهدارید."</string>
@@ -549,8 +558,8 @@
<string name="keyboard_key_dpad_center" msgid="4079412840715672825">"مرکز"</string>
<string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
<string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
- <string name="keyboard_key_enter" msgid="8633362970109751646">"ورود"</string>
- <string name="keyboard_key_backspace" msgid="4095278312039628074">"پسبر"</string>
+ <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string>
+ <string name="keyboard_key_backspace" msgid="4095278312039628074">"Backspace"</string>
<string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"پخش/مکث"</string>
<string name="keyboard_key_media_stop" msgid="1509943745250377699">"متوقف کردن"</string>
<string name="keyboard_key_media_next" msgid="8502476691227914952">"بعدی"</string>
@@ -561,9 +570,9 @@
<string name="keyboard_key_page_down" msgid="9035902490071829731">"صفحه قبل"</string>
<string name="keyboard_key_forward_del" msgid="5325501825762733459">"حذف"</string>
<string name="keyboard_key_move_home" msgid="3496502501803911971">"ابتدا"</string>
- <string name="keyboard_key_move_end" msgid="99190401463834854">"انتها"</string>
- <string name="keyboard_key_insert" msgid="4621692715704410493">"درج"</string>
- <string name="keyboard_key_num_lock" msgid="7209960042043090548">"قفل اعداد"</string>
+ <string name="keyboard_key_move_end" msgid="99190401463834854">"End"</string>
+ <string name="keyboard_key_insert" msgid="4621692715704410493">"Insert"</string>
+ <string name="keyboard_key_num_lock" msgid="7209960042043090548">"Num Lock"</string>
<string name="keyboard_key_numpad_template" msgid="7316338238459991821">"صفحهکلید عددی <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="notif_inline_reply_remove_attachment_description" msgid="7954075334095405429">"برداشتن پیوست"</string>
<string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"سیستم"</string>
@@ -738,10 +747,10 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ضبط صفحهنمایش"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"بدون عنوان"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"آمادهبهکار"</string>
- <string name="magnification_window_title" msgid="4863914360847258333">"پنجره بزرگنمایی"</string>
- <string name="magnification_controls_title" msgid="8421106606708891519">"کنترلهای پنجره بزرگنمایی"</string>
- <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"بزرگ کردن"</string>
- <string name="accessibility_control_zoom_out" msgid="69578832020304084">"کوچک کردن"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"پنجره درشتنمایی"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"کنترلهای پنجره درشتنمایی"</string>
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"زومپیش کردن"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"زومپس کردن"</string>
<string name="accessibility_control_move_up" msgid="6622825494014720136">"انتقال به بالا"</string>
<string name="accessibility_control_move_down" msgid="5390922476900974512">"انتقال به پایین"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"انتقال به راست"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 9b9082d..58eb829 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Kasvoja ei voi tunnistaa. Käytä sormenjälkeä."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth yhdistetty."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akun varaustaso ei tiedossa."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Yhteys: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Avattu kasvojen avulla. Avaa painamalla."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Kasvot tunnistettu. Avaa painamalla."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Kasvot tunnistettu. Jatka lukituksen avauskuvakkeella."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Avattu kasvojen avulla"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Kasvot tunnistettu"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Siirrä vasemmalle"</item>
<item msgid="5558598599408514296">"Siirrä alas"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu nopeasti • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu hitaasti • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ladataan telineellä • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kunnes täynnä"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Vaihda käyttäjää"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"alasvetovalikko"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Kaikki sovellukset ja tämän istunnon tiedot poistetaan."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Tervetuloa takaisin!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Haluatko jatkaa istuntoa?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Tekstitysten peitto"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ota käyttöön"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"poista käytöstä"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Sovellus on kiinnitetty"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Pysyy näkyvissä, kunnes irrotat sen. Irrota painamalla pitkään Edellinen ja Viimeisimmät."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Pysyy näkyvissä, kunnes irrotat sen. Irrota painamalla pitkään Edellinen ja Aloitusnäyttö."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 47e961b..815cf40 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Visage non reconnu. Utilisez plutôt l\'empreinte digitale."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connecté"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pourcentage de la pile inconnu."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connecté à : <xliff:g id="BLUETOOTH">%s</xliff:g>"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Déverr. par reconnaissance faciale. Appuyez pour ouvrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Visage reconnu. Appuyez pour ouvrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Visage reconnu. Appuyez sur Déverrouiller pour ouvrir."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Déverrouillé avec le visage"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Visage reconnu"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Déplacer vers la gauche"</item>
<item msgid="5558598599408514296">"Déplacer vers le bas"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"En recharge : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"En recharge rapide : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"En recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Station de recharge • Recharge terminée dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge en cours… • Se terminera dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Changer d\'utilisateur"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu déroulant"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Bienvenue à nouveau dans la session Invité"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Voulez-vous poursuivre la session?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Superposition de sous-titres"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"activer"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"désactiver"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Son et vibration"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Paramètres"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"L\'application est épinglée"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur « Retour » et « Aperçu »."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur les touches Retour et Accueil."</string>
@@ -572,13 +579,13 @@
<string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"Précédent"</string>
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Raccourcis clavier"</string>
- <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Changer la dispos. du clavier"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Changer la disposition du clavier"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applications"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistance"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Navigateur"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacts"</string>
<string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Courriel"</string>
- <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Message texte"</string>
+ <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Messages texte"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musique"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne pas déranger"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
index 4ec0084..c408865 100644
--- a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
@@ -47,7 +47,7 @@
<item msgid="287997784730044767">"Activées"</item>
</string-array>
<string-array name="tile_states_battery">
- <item msgid="6311253873330062961">"Non disponible"</item>
+ <item msgid="6311253873330062961">"Non accessible"</item>
<item msgid="7838121007534579872">"Désactivé"</item>
<item msgid="1578872232501319194">"Activé"</item>
</string-array>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 46897b0..3dd8650 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Visage non reconnu. Utilisez votre empreinte."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connecté"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pourcentage de la batterie inconnu."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connecté à : <xliff:g id="BLUETOOTH">%s</xliff:g>"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Déverrouillé par visage. Appuyez pour ouvrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Visage reconnu. Appuyez pour ouvrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Visage reconnu. Appuyez sur l\'icône de déverrouillage pour ouvrir."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Déverrouillé par le visage"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Visage reconnu"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Déplacer vers la gauche"</item>
<item msgid="5558598599408514296">"Déplacer vers le bas"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • En charge • Chargé dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge rapide • Chargé dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge lente • Chargé dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Station de charge • Chargé dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge • Chargé dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Changer d\'utilisateur"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu déroulant"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Heureux de vous revoir, Invité"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Voulez-vous poursuivre la dernière session ?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Sous-titres en superposition"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"activer"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"désactiver"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"L\'application est épinglée"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Elle restera visible jusqu\'à ce que vous la retiriez. Pour la retirer, appuyez de manière prolongée sur les boutons Retour et Aperçu."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Elle restera visible jusqu\'à ce que vous la retiriez. Pour la retirer, appuyez de manière prolongée sur les boutons Retour et Accueil."</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 4c070ff..ffc8eb1 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Non se recoñeceu a cara. Usa a impresión dixital."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Descoñécese a porcentaxe da batería."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Usouse o desbloqueo facial. Preme para abrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Recoñeceuse a cara. Preme para abrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Recoñeceuse a cara. Preme a icona de desbloquear para abrir."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Usouse o desbloqueo facial"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Recoñeceuse a cara"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Mover cara á esquerda"</item>
<item msgid="5558598599408514296">"Mover cara abaixo"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando rapidamente • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lentamente • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Base de carga • Carga completa dentro de <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar usuario"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú despregable"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Eliminaranse todas as aplicacións e datos desta sesión."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Benvido de novo, convidado"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Queres continuar coa túa sesión?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Superposición de subtítulos"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"activa"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desactiva"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"A aplicación está fixada"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"A pantalla manterase visible ata que deixes de fixala. Para facelo, mantén premido Atrás e Visión xeral."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"A pantalla manterase visible ata que deixes de fixala. Para facelo, mantén premido Atrás e Inicio."</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index ae642a7..5731df3 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ચહેરો ઓળખી શકતા નથી. તેને બદલે ફિંગરપ્રિન્ટ વાપરો."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"બ્લૂટૂથ કનેક્ટ થયું."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"બૅટરીની ટકાવારી અજાણ છે."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> થી કનેક્ટ થયાં."</string>
@@ -281,7 +285,7 @@
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"શરૂ કરો"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"રોકો"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"એક-હાથે વાપરો મોડ"</string>
- <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ડિવાઇસના માઇક્રોફોનને કરીએ?"</string>
+ <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ડિવાઇસના માઇક્રોફોનને અનબ્લૉક કરીએ?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ડિવાઇસના કૅમેરાને અનબ્લૉક કરીએ?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ડિવાઇસના કૅમેરા અને માઇક્રોફોનને અનબ્લૉક કરીએ?"</string>
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"આ તમારા માઇક્રોફોનનો ઉપયોગ કરવાની મંજૂરી ધરાવતી તમામ ઍપ અને સેવાઓ માટે ઍક્સેસને અનબ્લૉક કરે છે."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"ચહેરા દ્વારા અનલૉક કર્યું. ખોલવા માટે દબાવો."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"ચહેરો ઓળખ્યો. ખોલવા માટે દબાવો."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ચહેરો ઓળખ્યો. ખોલવા માટે \'અનલૉક કરો\' આઇકન દબાવો."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ચહેરા દ્વારા અનલૉક કર્યું"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ચહેરો ઓળખ્યો"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"ડાબે ખસેડો"</item>
<item msgid="5558598599408514296">"નીચે ખસેડો"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ઝડપથી ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ધીમેથી ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ડૉકથી ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં સંપૂર્ણ ચાર્જ થઈ જશે"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં પૂરું ચાર્જ થઈ જશે"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"વપરાશકર્તા સ્વિચ કરો"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"પુલડાઉન મેનૂ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"આ સત્રમાંની તમામ ઍપ અને ડેટા કાઢી નાખવામાં આવશે."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ફરી સ્વાગત છે, અતિથિ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"શું તમે તમારું સત્ર ચાલુ રાખવા માંગો છો?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"કૅપ્શન ઓવરલે"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ચાલુ કરો"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"બંધ કરો"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"સાઉન્ડ અને વાઇબ્રેશન"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"સેટિંગ"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"ઍપને પિન કરેલી છે"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને વ્યૂમાં રાખે છે. અનપિન કરવા માટે પાછળ અને ઓવરવ્યૂને સ્પર્શ કરી રાખો."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને વ્યૂમાં રાખે છે. અનપિન કરવા માટે પાછળ અને હોમને સ્પર્શ કરી રાખો."</string>
@@ -576,10 +583,10 @@
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ઍપ્લિકેશનો"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"સહાય"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"બ્રાઉઝર"</string>
- <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacts"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"સંપર્કો"</string>
<string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ઇમેઇલ"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
- <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"સંગીત"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"મ્યુઝિક"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ખલેલ પાડશો નહીં"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"વૉલ્યૂમ બટન્સ શૉર્ટકટ"</string>
diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
index 73b3720..cc062a77 100644
--- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
@@ -87,7 +87,7 @@
<item msgid="2075645297847971154">"ચાલુ છે"</item>
</string-array>
<string-array name="tile_states_color_correction">
- <item msgid="2840507878437297682">"અનુપલબ્ધ"</item>
+ <item msgid="2840507878437297682">"ઉપલબ્ધ નથી"</item>
<item msgid="1909756493418256167">"બંધ છે"</item>
<item msgid="4531508423703413340">"ચાલુ છે"</item>
</string-array>
@@ -157,7 +157,7 @@
<item msgid="6866424167599381915">"ચાલુ છે"</item>
</string-array>
<string-array name="tile_states_qr_code_scanner">
- <item msgid="7435143266149257618">"અનુપલબ્ધ"</item>
+ <item msgid="7435143266149257618">"ઉપલબ્ધ નથી"</item>
<item msgid="3301403109049256043">"બંધ છે"</item>
<item msgid="8878684975184010135">"ચાલુ છે"</item>
</string-array>
@@ -167,12 +167,12 @@
<item msgid="7809470840976856149">"ચાલુ છે"</item>
</string-array>
<string-array name="tile_states_onehanded">
- <item msgid="8189342855739930015">"અનુપલબ્ધ"</item>
+ <item msgid="8189342855739930015">"ઉપલબ્ધ નથી"</item>
<item msgid="146088982397753810">"બંધ છે"</item>
<item msgid="460891964396502657">"ચાલુ છે"</item>
</string-array>
<string-array name="tile_states_dream">
- <item msgid="6184819793571079513">"અનુપલબ્ધ"</item>
+ <item msgid="6184819793571079513">"ઉપલબ્ધ નથી"</item>
<item msgid="8014986104355098744">"બંધ છે"</item>
<item msgid="5966994759929723339">"ચાલુ છે"</item>
</string-array>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 08e3b80..43bc112 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"चेहरे की पहचान नहीं हुई. फ़िंगरप्रिंट इस्तेमाल करें."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लूटूथ कनेक्ट किया गया."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"इस बारे में जानकारी नहीं है कि अभी बैटरी कितने प्रतिशत चार्ज है."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> से कनेक्ट किया गया."</string>
@@ -281,8 +285,8 @@
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"शुरू करें"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"रोकें"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"वन-हैंडेड मोड"</string>
- <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"क्या आप डिवाइस के माइक्रोफ़ोन को अनब्लॉक करना चाहते हैं?"</string>
- <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"क्या आप डिवाइस के कैमरे को अनब्लॉक करना चाहते हैं?"</string>
+ <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"क्या आपको डिवाइस का माइक्रोफ़ोन अनब्लॉक करना है?"</string>
+ <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"क्या आपको डिवाइस का कैमरा अनब्लॉक करना है?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"क्या आप डिवाइस का कैमरा और माइक्रोफ़ोन अनब्लॉक करना चाहते हैं?"</string>
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ऐसा करने से, माइक्रोफ़ोन का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें माइक्रोफ़ोन का इस्तेमाल करने की अनुमति दी गई है."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ऐसा करने से, कैमरे का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें कैमरे का इस्तेमाल करने की अनुमति दी गई है."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"चेहरे से अनलॉक किया गया. डिवाइस खोलने के लिए टैप करें."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"चेहरे की पहचान हो गई. डिवाइस खोलने के लिए टैप करें."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"चेहरे की पहचान हो गई. डिवाइस खोलने के लिए अनलॉक आइकॉन को टैप करें."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"चेहरे से अनलॉक किया गया"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"चेहरे की पहचान हो गई"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"बाईं ओर ले जाएं"</item>
<item msgid="5558598599408514296">"नीचे ले जाएं"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • तेज़ चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • धीरे चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • डॉक पर चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"उपयोगकर्ता बदलें"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेन्यू"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"इस सेशन के सभी ऐप्लिकेशन और डेटा को हटा दिया जाएगा."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"मेहमान, आपका फिर से स्वागत है!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"क्या आपको अपना सेशन जारी रखना है?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"कैप्शन ऊपर लगाएं"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"चालू करें"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"बंद करें"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"ऐप्लिकेशन पिन किया गया है"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"इससे वह तब तक दिखता रहता है, जब तक कि आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए, \'वापस जाएं\' और \'खास जानकारी\' को दबाकर रखें."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"इससे वह तब तक दिखाई देती है जब तक आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए, होम और वापस जाएं वाले बटन को दबाकर रखें."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index c3f1b96..19298f4 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Prepoznavanje lica nije uspjelo. Upotrijebite otisak prsta."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth povezan."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Postotak baterije nije poznat."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Spojen na <xliff:g id="BLUETOOTH">%s</xliff:g> ."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Otključano pomoću lica. Pritisnite da biste otvorili."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Lice je prepoznato. Pritisnite da biste otvorili."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Lice je prepoznato. Pritisnite ikonu otključavanja da biste otvorili."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Otključano licem"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Lice je prepoznato"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Pomicanje ulijevo"</item>
<item msgid="5558598599408514296">"Pomicanje prema dolje"</item>
@@ -337,7 +343,7 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • brzo punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • sporo punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Priključna stanica za punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Promjena korisnika"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući izbornik"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Izbrisat će se sve aplikacije i podaci u ovoj sesiji."</string>
@@ -417,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Sloj titlova"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"omogući"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"onemogući"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacija je prikvačena"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Dodirnite i zadržite Natrag i Pregled da biste ga otkvačili."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Dodirnite gumbe Natrag i Početna i zadržite pritisak da biste ga otkvačili."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 4e40dc5..fb8d5c7 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Az arc nem felismerhető. Használjon ujjlenyomatot."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth csatlakoztatva."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Az akkumulátor töltöttségi szintje ismeretlen."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Csatlakoztatva a következőhöz: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Zárolás arccal feloldva. Koppintson az eszköz használatához."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Arc felismerve. Koppintson az eszköz használatához."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Arc felismerve. Eszköz használata: Feloldás ikon."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Zárolás arccal feloldva"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Arc felismerve"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Mozgatás balra"</item>
<item msgid="5558598599408514296">"Mozgatás lefelé"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Gyors töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lassú töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Töltődokk • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Felhasználóváltás"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"lehúzható menü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"A munkamenetben található összes alkalmazás és adat törlődni fog."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Örülünk, hogy visszatért, vendég!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Folytatja a munkamenetet?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Feliratok fedvény"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"engedélyezés"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"letiltás"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Az alkalmazás ki van tűzve"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz tartsa lenyomva a Vissza és az Áttekintés lehetőséget."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz tartsa lenyomva a Vissza és a Kezdőképernyő elemet."</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 4f080eb..3501f52 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Դեմքը չի հաջողվում ճանաչել։ Օգտագործեք մատնահետքը։"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-ը միացված է:"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Մարտկոցի լիցքի մակարդակն անհայտ է։"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Միացված է <xliff:g id="BLUETOOTH">%s</xliff:g>-ին:"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ապակողպվել է դեմքով։ Սեղմեք բացելու համար։"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Դեմքը ճանաչվեց։ Սեղմեք բացելու համար։"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Դեմքը ճանաչվեց։ Բացելու համար սեղմեք ապակողպման պատկերակը։"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ապակողպվեց դեմքով"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Դեմքը ճանաչվեց"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Տեղափոխել ձախ"</item>
<item msgid="5558598599408514296">"Տեղափոխել ներքև"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Արագ լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Դանդաղ լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Լիցքավորում դոկ-կայանի միջոցով • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Անջատել օգտվողին"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"իջնող ընտրացանկ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Այս աշխատաշրջանի բոլոր հավելվածներն ու տվյալները կջնջվեն:"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Բարի վերադարձ, հյուր"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Շարունակե՞լ աշխատաշրջանը։"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Ենթագրերի վրադրում"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"միացնել"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"անջատել"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Ձայն և թրթռոց"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Կարգավորումներ"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Հավելվածն ամրացված է"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Էկրանը կմնա տեսադաշտում, մինչև այն ապամրացնեք: Ապամրացնելու համար հպեք և պահեք Հետ և Համատեսք կոճակները:"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Էկրանը կցուցադրվի այնքան ժամանակ, մինչև չեղարկեք ամրացումը: Չեղարկելու համար հպեք և պահեք «Հետ» և «Գլխավոր էկրան» կոճակները"</string>
@@ -833,7 +840,7 @@
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Ընտրված է <xliff:g id="COUNT">%1$d</xliff:g> սարք"</string>
<string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(անջատված է)"</string>
<string name="media_output_dialog_connect_failed" msgid="3080972621975339387">"Սխալ առաջացավ։ Հպեք՝ կրկնելու համար։"</string>
- <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"Միացրեք սարքը"</string>
+ <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"Միացնել սարք"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Այս աշխատաշրջանը հեռարձակելու համար բացեք հավելվածը"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Անհայտ հավելված"</string>
<string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Կանգնեցնել հեռարձակումը"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 726c366..26e7f3e 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tidak dapat mengenali wajah. Gunakan sidik jari."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth terhubung."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Persentase baterai tidak diketahui."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Terhubung ke <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Kunci dibuka dengan wajah. Tekan untuk membuka."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Wajah dikenali. Tekan untuk membuka."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Wajah dikenali. Tekan ikon buka kunci untuk membuka."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Kunci dibuka dengan wajah"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Wajah dikenali"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Pindah ke kiri"</item>
<item msgid="5558598599408514296">"Pindah ke bawah"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan cepat • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan lambat • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi Daya dengan Dok • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Beralih pengguna"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pulldown"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data dalam sesi ini akan dihapus."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Selamat datang kembali, tamu!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Lanjutkan sesi Anda?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Overlay teks"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktifkan"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"nonaktifkan"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Aplikasi disematkan"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Ini akan terus ditampilkan sampai Anda melepas sematan. Sentuh lama tombol Kembali dan Ringkasan untuk melepas sematan."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ini akan terus ditampilkan sampai Anda melepas sematan. Sentuh lama tombol Kembali dan Beranda untuk melepas sematan."</string>
@@ -567,7 +576,7 @@
<string name="keyboard_key_numpad_template" msgid="7316338238459991821">"Numpad <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="notif_inline_reply_remove_attachment_description" msgid="7954075334095405429">"Hapus lampiran"</string>
<string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"Sistem"</string>
- <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"Layar Utama"</string>
+ <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"Layar utama"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"Terbaru"</string>
<string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"Kembali"</string>
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifikasi"</string>
@@ -912,7 +921,7 @@
<string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi tidak akan otomatis terhubung untuk saat ini"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Lihat semua"</string>
<string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Untuk beralih jaringan, lepaskan kabel ethernet"</string>
- <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Agar pengalaman perangkat menjadi lebih baik, aplikasi dan layanan tetap dapat memindai jaringan Wi-Fi kapan saja, bahkan saat Wi-Fi nonaktif. Anda dapat mengubahnya di setelan pemindaian Wi-Fi. "<annotation id="link">"Ubah"</annotation></string>
+ <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Untuk meningkatkan fungsi perangkat, aplikasi dan layanan tetap dapat memindai jaringan Wi-Fi kapan saja, bahkan saat Wi-Fi nonaktif. Anda dapat mengubahnya di setelan pemindaian Wi-Fi. "<annotation id="link">"Ubah"</annotation></string>
<string name="turn_off_airplane_mode" msgid="8425587763226548579">"Nonaktifkan mode pesawat"</string>
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ingin menambahkan kartu berikut ke Setelan Cepat"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Tambahkan kartu"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 7a90de3..b699135 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Andlit þekkist ekki. Notaðu fingrafar í staðinn."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth tengt."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Staða rafhlöðu óþekkt."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Tengt við <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Opnað með andliti. Ýttu til að opna."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Andlitið var greint. Ýttu til að opna."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Andlitið var greint. Ýttu á opnunartáknið til að opna."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Opnað með andliti"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Andlitið var greint"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Færa til vinstri"</item>
<item msgid="5558598599408514296">"Færa niður"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Í hleðslu • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hraðhleðsla • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hæg hleðsla • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hleður í dokku • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Í hleðslu • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Skipta um notanda"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Fellivalmynd"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Öllum forritum og gögnum í þessari lotu verður eytt."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Velkominn aftur, gestur!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Viltu halda áfram með lotuna?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Yfirlögn myndatexta"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"virkja"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"slökkva"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Forrit er fest"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Þetta heldur þessu opnu þangað til þú losar það. Haltu fingri á „Til baka“ og „Yfirlit“ til að losa."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Þetta heldur þessu opnu þangað til það er losað. Haltu inni bakkhnappinum og heimahnappinum til að losa."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 2b2b32a..e1bf662 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Impossibile riconoscere il volto. Usa l\'impronta."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth collegato."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percentuale della batteria sconosciuta."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connesso a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Sbloccato con il volto. Premi per aprire."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Volto riconosciuto. Premi per aprire."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Volto riconosciuto. Premi l\'icona Sblocca per aprire."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Sbloccato con il volto"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Volto riconosciuto"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Sposta a sinistra"</item>
<item msgid="5558598599408514296">"Sposta giù"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • In carica • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica veloce • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica lenta • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • In carica nel dock • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • In carica • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambio utente"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu a discesa"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tutte le app e i dati di questa sessione verranno eliminati."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Ti ridiamo il benvenuto nella sessione Ospite."</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vuoi continuare la sessione?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Overlay sottotitoli"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"attiva"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disattiva"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Suoni e vibrazione"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Impostazioni"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"L\'app è bloccata sullo schermo"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"La schermata rimane visibile finché non viene sganciata. Per sganciarla, tieni premuto Indietro e Panoramica."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"La schermata rimane visibile finché non viene disattivato il blocco su schermo. Per disattivarlo, tocca e tieni premuto Indietro e Home."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 4b39928..9014544 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"לא ניתן לזהות את הפנים. יש להשתמש בטביעת אצבע במקום."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth מחובר."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"אחוז טעינת הסוללה לא ידוע."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"התבצע חיבור אל <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"הנעילה בוטלה באמצעות זיהוי הפנים. יש ללחוץ כדי לפתוח."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"הפנים זוהו. יש ללחוץ כדי לפתוח."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"הפנים זוהו. יש ללחוץ על סמל ביטול הנעילה כדי לפתוח."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"הנעילה בוטלה באמצעות זיהוי הפנים"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"הפנים זוהו"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"הזזה שמאלה"</item>
<item msgid="5558598599408514296">"הזזה למטה"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה מהירה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה איטית • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • אביזר העגינה בטעינה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"החלפת משתמש"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"תפריט במשיכה למטה"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"כל האפליקציות והנתונים בסשן הזה יימחקו."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"שמחים לראותך שוב!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"האם ברצונך להמשיך בפעילות באתר?"</string>
@@ -362,7 +367,7 @@
<string name="manage_notifications_text" msgid="6885645344647733116">"ניהול"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"היסטוריה"</string>
<string name="notification_section_header_incoming" msgid="850925217908095197">"התראות חדשות"</string>
- <string name="notification_section_header_gentle" msgid="6804099527336337197">"שקט"</string>
+ <string name="notification_section_header_gentle" msgid="6804099527336337197">"שקטות"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"התראות"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"שיחות"</string>
<string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"ניקוי כל ההתראות השקטות"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"שכבת-על לכיתוב"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"הפעלה"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"השבתה"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"צליל ורטט"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"הגדרות"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"האפליקציה מוצמדת"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"נשאר בתצוגה עד לביטול ההצמדה. יש ללחוץ לחיצה ארוכה על הלחצנים \'הקודם\' ו\'סקירה\' כדי לבטל את ההצמדה."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"נשאר בתצוגה עד לביטול ההצמדה. יש ללחוץ לחיצה ארוכה על הלחצנים \'הקודם\' ו\'דף הבית\' כדי לבטל את ההצמדה."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index a7fdf40..c7b636a 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"顔を認識できません。指紋認証を使用してください。"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetoothに接続済み。"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"バッテリー残量は不明です。"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>に接続しました。"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"顔でロック解除しました。押すと開きます。"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"顔を認識しました。押すと開きます。"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"顔を認識しました。ロック解除アイコンを押して開きます。"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"顔でロック解除しました"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"顔を認識しました"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"左に移動"</item>
<item msgid="5558598599408514296">"下に移動"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • 完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 急速充電中 • 完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 低速充電中 • 完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ホルダーで充電中 • 完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • フル充電まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ユーザーを切り替える"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"プルダウン メニュー"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"このセッションでのアプリとデータはすべて削除されます。"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"おかえりなさい、ゲストさん"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"セッションを続行しますか?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"字幕のオーバーレイ"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"有効にする"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"無効にする"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"着信音とバイブレーション"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"設定"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"アプリは固定されています"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"固定を解除するまで画面が常に表示されるようになります。[戻る] と [最近] を同時に押し続けると固定が解除されます。"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"固定を解除するまで画面が常に表示されるようになります。[戻る] と [ホーム] を同時に押し続けると固定が解除されます。"</string>
@@ -833,7 +840,7 @@
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"選択したデバイス: <xliff:g id="COUNT">%1$d</xliff:g> 台"</string>
<string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(接続解除済み)"</string>
<string name="media_output_dialog_connect_failed" msgid="3080972621975339387">"切り替えられません。タップしてやり直してください。"</string>
- <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"デバイスの接続"</string>
+ <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"デバイスを接続"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"このセッションをキャストするには、アプリを開いてください。"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"不明なアプリ"</string>
<string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"キャストを停止"</string>
@@ -917,11 +924,11 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> が以下のタイルをクイック設定に追加しようとしています"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"タイルを追加"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"タイルを追加しない"</string>
- <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ユーザーの選択"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ユーザーを選択"</string>
<string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# 個のアプリがアクティブです}other{# 個のアプリがアクティブです}}"</string>
<string name="fgs_dot_content_description" msgid="2865071539464777240">"最新情報"</string>
<string name="fgs_manager_dialog_title" msgid="5879184257257718677">"実行中のアプリ"</string>
- <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"ユーザーが使用していない状態でもアクティブで実行中のアプリの一覧です。機能面は向上しますが、バッテリー駆動時間に影響する可能性があります。"</string>
+ <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"ユーザーが使用していない状態でもアクティブで実行されているアプリの一覧です。機能性は向上しますが、バッテリー駆動時間に影響する可能性があります。"</string>
<string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"停止"</string>
<string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"停止中"</string>
<string name="clipboard_edit_text_done" msgid="4551887727694022409">"完了"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 7c4df7b..ed1eebb 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"სახის ამოცნობა ვერ ხერხდება. სანაცვლოდ თითის ანაბეჭდი გამოიყენეთ."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth დაკავშირებულია."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ბატარეის პროცენტული მაჩვენებელი უცნობია."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"დაკავშირებულია <xliff:g id="BLUETOOTH">%s</xliff:g>-თან."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"განიბლოკა სახით. დააჭირეთ გასახსნელად."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"ამოცნობილია სახით. დააჭირეთ გასახსნელად."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ამოცნობილია სახით. გასახსნელად დააჭირეთ განბლოკვის ხატულას."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"განიბლოკა სახით"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"სახე ამოცნობილია"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"მარცხნივ გადატანა"</item>
<item msgid="5558598599408514296">"ქვემოთ გადატანა"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • სწრაფად იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ნელა იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • დამტენი სამაგრი • დატენამდე დარჩა <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"მომხმარებლის გადართვა"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ჩამოშლადი მენიუ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ამ სესიის ყველა აპი და მონაცემი წაიშლება."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"სტუმარო, გვიხარია, რომ დაბრუნდით!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"გსურთ, თქვენი სესიის გაგრძელება?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"სუბტიტრების გადაფარვა"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ჩართვა"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"გამორთვა"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"ხმა და ვიბრაცია"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"პარამეტრები"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"აპი ჩამაგრებულია"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"ამით ის დარჩება ხედში ჩამაგრების მოხსნამდე. ჩამაგრების მოსახსნელად, ხანგრძლივად შეეხეთ „უკან და მიმოხილვა“-ს."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ამით ის დარჩება ხედში ჩამაგრების მოხსნამდე. ჩამაგრების მოსახსნელად, ხანგრძლივად შეეხეთ „უკან მთავარ გვერდზე“-ს."</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 06cb83c..44149ab 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -84,7 +84,7 @@
<string name="screenshot_share_description" msgid="2861628935812656612">"Скриншотты бөлісу"</string>
<string name="screenshot_scroll_label" msgid="2930198809899329367">"Тағы суретке түсіру"</string>
<string name="screenshot_dismiss_description" msgid="4702341245899508786">"Скриншотты жабу"</string>
- <string name="screenshot_preview_description" msgid="7606510140714080474">"Скриншотты алдын ала қарау"</string>
+ <string name="screenshot_preview_description" msgid="7606510140714080474">"Скриншотты алдын ала көру"</string>
<string name="screenshot_top_boundary_pct" msgid="2520148599096479332">"Жоғарғы шектік сызық: <xliff:g id="PERCENT">%1$d</xliff:g> пайыз"</string>
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Төменгі шектік сызық: <xliff:g id="PERCENT">%1$d</xliff:g> пайыз"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Сол жақ шектік сызық: <xliff:g id="PERCENT">%1$d</xliff:g> пайыз"</string>
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Бет танылмады. Орнына саусақ ізін пайдаланыңыз."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth қосылған."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарея зарядының мөлшері белгісіз."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> қосылған."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Бетпен ашылды. Ашу үшін басыңыз."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Бет танылды. Ашу үшін басыңыз."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Бет танылды. Ашу үшін құлыпты ашу белгішесін басыңыз."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Бетпен ашылды."</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Бет танылды."</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Солға жылжыту"</item>
<item msgid="5558598599408514296">"Төмен жылжыту"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядталуда • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жылдам зарядталуда • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Баяу зарядталуда • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Қондыру станциясында зарядталуда • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядталып жатыр. • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Пайдаланушыны ауыстыру"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ашылмалы мәзір"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Осы сеанстағы барлық қолданбалар мен деректер жойылады."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Қош келдіңіз, қонақ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Сеансты жалғастыру керек пе?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Субтитр қою"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"қосу"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"өшіру"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Қолданба бекітілді"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Өзіңіз босатқаша ашық тұрады. Босату үшін \"Артқа\" және \"Шолу\" түймелерін басып тұрыңыз."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Өзіңіз босатқаша ашық тұрады. Босату үшін \"Артқа\" және \"Негізгі бет\" түймелерін басып тұрыңыз"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 338d05d..1d3a1d4 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"មិនអាចសម្គាល់មុខបានទេ។ សូមប្រើស្នាមម្រាមដៃជំនួសវិញ។"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"បានតភ្ជាប់ប៊្លូធូស។"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"មិនដឹងអំពីភាគរយថ្មទេ។"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"បានភ្ជាប់ទៅ <xliff:g id="BLUETOOTH">%s</xliff:g> ។"</string>
@@ -266,7 +270,7 @@
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"រហូតដល់ពេលថ្ងៃរះ"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"បើកនៅម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"រហូតដល់ម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
- <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"រចនាប័ទ្មងងឹត"</string>
+ <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ទម្រង់រចនាងងឹត"</string>
<string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"មុខងារសន្សំថ្ម"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"បើកនៅពេលថ្ងៃលិច"</string>
<string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"រហូតដល់ពេលថ្ងៃរះ"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"បានដោះសោដោយប្រើមុខ។ សូមចុច ដើម្បីបើក។"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"បានស្គាល់មុខ។ សូមចុច ដើម្បីបើក។"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"បានស្គាល់មុខ។ សូមចុចរូបដោះសោ ដើម្បីបើក។"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"បានដោះសោដោយប្រើមុខ"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"បានស្គាល់មុខ"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"ផ្លាស់ទីទៅឆ្វេង"</item>
<item msgid="5558598599408514296">"ផ្លាស់ទីចុះក្រោម"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្ម • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្មយឺត • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ឧបករណ៍ភ្ជាប់សាកថ្ម • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ទៀត"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្ម • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ប្ដូរអ្នកប្រើ"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ម៉ឺនុយទាញចុះ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"កម្មវិធី និងទិន្នន័យទាំងអស់ក្នុងវគ្គនេះនឹងត្រូវលុប។"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"សូមស្វាគមន៍ការត្រឡប់មកវិញ, ភ្ញៀវ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"តើអ្នកចង់បន្តវគ្គរបស់អ្នកទេ?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"ការដាក់ត្រួតគ្នាលើអក្សររត់"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"បើក"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"បិទ"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"កម្មវិធីត្រូវបានខ្ទាស់"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"វានឹងនៅតែបង្ហាញ រហូតទាល់តែអ្នកដកការដៅ។ សូមសង្កត់ប៊ូតុងថយក្រោយ និងប៊ូតុងទិដ្ឋភាពរួមឲ្យជាប់ ដើម្បីដកការដៅ។"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"វានឹងនៅតែបង្ហាញ រហូតទាល់តែអ្នកដកការដៅ។ សូមចុចប៊ូតុងថយក្រោយ និងប៊ូតុងទំព័រដើមឱ្យជាប់ ដើម្បីដកការដៅ។"</string>
@@ -592,7 +601,7 @@
<string name="accessibility_data_saver_on" msgid="5394743820189757731">"កម្មវិធីសន្សំសំចៃទិន្នន័យបានបើក"</string>
<string name="switch_bar_on" msgid="1770868129120096114">"បើក"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"បិទ"</string>
- <string name="tile_unavailable" msgid="3095879009136616920">"មិនមាន"</string>
+ <string name="tile_unavailable" msgid="3095879009136616920">"មិនអាចប្រើបាន"</string>
<string name="tile_disabled" msgid="373212051546573069">"បានបិទ"</string>
<string name="nav_bar" msgid="4642708685386136807">"របាររុករក"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"ប្លង់"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index fd3b703..f02830b 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ಮುಖ ಗುರುತಿಸಲಾಗುತ್ತಿಲ್ಲ ಬದಲಿಗೆ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಬಳಸಿ."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ಬ್ಲೂಟೂತ್ ಸಂಪರ್ಕಗೊಂಡಿದೆ."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ಬ್ಯಾಟರಿ ಶೇಕಡಾವಾರು ತಿಳಿದಿಲ್ಲ."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"ಮುಖವನ್ನು ಬಳಸಿ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗಿದೆ. ತೆರೆಯಲು ಒತ್ತಿ."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ. ತೆರೆಯಲು ಒತ್ತಿ."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ. ತೆರೆಯಲು ಅನ್ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ಮುಖದ ಮೂಲಕ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"ಎಡಕ್ಕೆ ಸರಿಸಿ"</item>
<item msgid="5558598599408514296">"ಕೆಳಗೆ ಸರಿಸಿ"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ಡಾಕ್ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ದಲ್ಲಿ ಚಾರ್ಜ್ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ಪುಲ್ಡೌನ್ ಮೆನು"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ಈ ಸೆಷನ್ನಲ್ಲಿನ ಎಲ್ಲ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ಮತ್ತೆ ಸುಸ್ವಾಗತ, ಅತಿಥಿ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ನಿಮ್ಮ ಸೆಷನ್ ಮುಂದುವರಿಸಲು ಇಚ್ಚಿಸುವಿರಾ?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"ಶೀರ್ಷಿಕೆಗಳ ಓವರ್ಲೇ"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"ಆ್ಯಪ್ ಅನ್ನು ಪಿನ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"ನೀವು ಅನ್ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ ಹಾಗೂ ಅನ್ಪಿನ್ ಮಾಡಲು ಅವಲೋಕಿಸಿ."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ನೀವು ಅನ್ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ ಹಾಗೂ ಅನ್ಪಿನ್ ಮಾಡಲು ಮುಖಪುಟಕ್ಕೆ ಹಿಂತಿರುಗಿ."</string>
@@ -833,7 +842,7 @@
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> ಸಾಧನಗಳನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
<string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ಡಿಸ್ಕನೆಕ್ಟ್ ಆಗಿದೆ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3080972621975339387">"ಬದಲಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
- <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"ಸಾಧನವನ್ನು ಸಂಪರ್ಕಿಸಿ"</string>
+ <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"ಸಾಧನವನ್ನು ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ಈ ಸೆಶನ್ ಕಾಸ್ಟ್ ಮಾಡಲು, ಆ್ಯಪ್ ಅನ್ನು ತೆರೆಯಿರಿ."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"ಅಪರಿಚಿತ ಆ್ಯಪ್"</string>
<string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ಬಿತ್ತರಿಸುವುದನ್ನು ನಿಲ್ಲಿಸಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 4cedd5f..ebf0db2 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"얼굴을 인식할 수 없습니다. 대신 지문을 사용하세요."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"블루투스가 연결되었습니다."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"배터리 잔량을 알 수 없습니다."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>에 연결되었습니다."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"얼굴 인식으로 잠금 해제되었습니다. 열려면 누르세요."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"얼굴이 인식되었습니다. 열려면 누르세요."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"얼굴이 인식되었습니다. 열려면 잠금 해제 아이콘을 누르세요."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"얼굴 인식으로 잠금 해제되었습니다."</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"얼굴이 인식되었습니다."</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"왼쪽으로 이동"</item>
<item msgid="5558598599408514296">"아래로 이동"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 고속 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 저속 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 충전 거치대 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"사용자 전환"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"풀다운 메뉴"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"이 세션에 있는 모든 앱과 데이터가 삭제됩니다."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"게스트 세션 진행"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"세션을 계속 진행하시겠습니까?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"캡션 오버레이"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"사용"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"사용 중지"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"앱 고정됨"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"고정 해제할 때까지 계속 표시됩니다. 고정 해제하려면 뒤로 및 최근 사용을 길게 터치하세요."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"고정 해제할 때까지 계속 표시됩니다. 고정 해제하려면 뒤로 및 홈을 길게 터치하세요."</string>
@@ -576,7 +585,7 @@
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"애플리케이션"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"지원"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"브라우저"</string>
- <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"주소록"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"연락처"</string>
<string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"이메일"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"음악"</string>
@@ -912,7 +921,7 @@
<string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"지금은 Wi-Fi가 자동으로 연결되지 않습니다."</string>
<string name="see_all_networks" msgid="3773666844913168122">"모두 보기"</string>
<string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"네트워크를 전환하려면 이더넷을 연결 해제하세요."</string>
- <string name="wifi_scan_notify_message" msgid="3753839537448621794">"기기 환경을 개선하기 위해 Wi‑Fi가 꺼져 있을 때도 앱과 서비스에서 Wi‑Fi 네트워크를 검색할 수 있습니다. 이 설정은 Wi‑Fi 검색 설정에서 변경할 수 있습니다. "<annotation id="link">"변경"</annotation></string>
+ <string name="wifi_scan_notify_message" msgid="3753839537448621794">"기기 환경을 개선하기 위해 앱과 서비스에서 언제든지 Wi‑Fi 네트워크를 검색할 수 있습니다(Wi‑Fi가 꺼져 있을 때 포함). 이 설정은 Wi‑Fi 검색 설정에서 변경할 수 있습니다. "<annotation id="link">"변경"</annotation></string>
<string name="turn_off_airplane_mode" msgid="8425587763226548579">"비행기 모드 사용 중지"</string>
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g>에서 빠른 설정에 다음 타일을 추가하려고 합니다."</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"타일 추가"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 7266a7b..aa7a67f 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Жүз таанылбай жатат. Манжа изин колдонуңуз."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth байланышта"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарея кубатынын деңгээли белгисиз."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> менен туташкан."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Кулпуну жүзүңүз менен ачтыңыз. Ачуу үчүн басыңыз."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Жүз таанылды. Ачуу үчүн басыңыз."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Жүз таанылды. Эми кулпуну ачуу сүрөтчөсүн басыңыз."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Түзмөгүңүздү жүзүңүз менен ачтыңыз"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Жүз таанылды"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Солго жылдыруу"</item>
<item msgid="5558598599408514296">"Төмөн жылдыруу"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Тез кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жай кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Кубаттоо догу • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Колдонуучуну которуу"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ылдый түшүүчү меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Бул сеанстагы бардык колдонмолор жана аларга байланыштуу нерселер өчүрүлөт."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Кайтып келишиңиз менен!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Сеансыңызды улантасызбы?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Коштомо жазуулардын үстүнө коюу"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"иштетүү"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"өчүрүү"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Колдонмо кадалды"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн \"Артка\" жана \"Назар\" баскычтарын басып, кармап туруңуз."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн, \"Артка\" жана \"Башкы бет\" баскычтарын басып, кармап туруңуз."</string>
@@ -458,7 +467,7 @@
<string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Чалуулар менен эскертмелердин үнү чыгарылат (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Абал тилкеси"</string>
- <string name="demo_mode" msgid="263484519766901593">"Тутум интерфейсинин демо режими"</string>
+ <string name="demo_mode" msgid="263484519766901593">"Системанын интерфейсинин демо режими"</string>
<string name="enable_demo_mode" msgid="3180345364745966431">"Демо режимин иштетүү"</string>
<string name="show_demo_mode" msgid="3677956462273059726">"Демо режимин көрсөтүү"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
@@ -912,7 +921,7 @@
<string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi азырынча автоматтык түрдө туташпайт"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Баарын көрүү"</string>
<string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Башка тармактарга которулуу үчүн Ethernet кабелин ажыратыңыз"</string>
- <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Түзмөктүн колдонулушун жакшыртуу үчүн колдонмолор менен кызматтар Wi‑Fi өчүп турса да зымсыз тармактарды издей беришет. Аны Wi-Fi тармактарын издөө жөндөөлөрүнөн өзгөртө аласыз. "<annotation id="link">"Өзгөртүү"</annotation></string>
+ <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Түзмөктүн иштешин жакшыртуу үчүн колдонмолор менен кызматтар Wi‑Fi өчүп турса да зымсыз тармактарды издей беришет. Издебесин десеңиз, Wi-Fi тармактарын издөө дегенди өчүрүп коюңуз. "<annotation id="link">"Өзгөртүү"</annotation></string>
<string name="turn_off_airplane_mode" msgid="8425587763226548579">"Учак режимин өчүрүү"</string>
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> төмөнкү ыкчам баскычты Ыкчам жөндөөлөргө кошкону жатат"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Ыкчам баскыч кошуу"</string>
@@ -921,7 +930,7 @@
<string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# колдонмо иштеп жатат}other{# колдонмо иштеп жатат}}"</string>
<string name="fgs_dot_content_description" msgid="2865071539464777240">"Жаңы маалымат"</string>
<string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Жигердүү колдонмолор"</string>
- <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Бул колдонмолор жабылып турса да, активдүү болуп, иштеп турушат. Алардын функционалдуулугу жакшырат, бирок батареянын кубатынын мөөнөтүнө кедергиси тийиши мүмкүн."</string>
+ <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Бул колдонмолор жабылып турса да иштей беришет. Ушуну менен көбүрөөк мүмкүнчүлүктөргө ээ болгонуңуз менен, батареяңыз тез отуруп калышы мүмкүн."</string>
<string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"Токтотуу"</string>
<string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"Токтотулду"</string>
<string name="clipboard_edit_text_done" msgid="4551887727694022409">"Бүттү"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 6685ae7..7d09542 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ບໍ່ສາມາດຈຳແນກໜ້າໄດ້. ກະລຸນາໃຊ້ລາຍນິ້ວມືແທນ."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ເຊື່ອມຕໍ່ Bluetooth ແລ້ວ."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ບໍ່ຮູ້ເປີເຊັນແບັດເຕີຣີ."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"ເຊື່ອມຕໍ່ຫາ <xliff:g id="BLUETOOTH">%s</xliff:g> ແລ້ວ."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດເພື່ອເປີດ."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດເພື່ອເປີດ."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອເປີດ."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ປົດລັອກດ້ວຍໃບໜ້າແລ້ວ"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ຈຳແນກໜ້າໄດ້ແລ້ວ"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"ຍ້າຍໄປຊ້າຍ"</item>
<item msgid="5558598599408514296">"ຍ້າຍລົງ"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟແບບໄວ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟແບບຊ້າ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟຜ່ານດັອກ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ສະຫຼັບຜູ້ໃຊ້"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ເມນູແບບດຶງລົງ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ແອັບຯແລະຂໍ້ມູນທັງໝົດໃນເຊດຊັນນີ້ຈະຖືກລຶບອອກ."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ຍິນດີຕ້ອນຮັບກັບມາ, ຜູ້ຢ້ຽມຢາມ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ທ່ານຕ້ອງການສືບຕໍ່ເຊດຊັນຂອງທ່ານບໍ່?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"ຄຳບັນຍາຍແບບວາງທັບ"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ເປີດນຳໃຊ້"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ປິດນຳໃຊ້"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"ແອັບຖືກປັກໝຸດແລ້ວ"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"ນີ້ຈະສະແດງມັນໃນໜ້າຈໍຈົນກວ່າທ່ານຈະເຊົາປັກມຸດ. ໃຫ້ແຕະປຸ່ມກັບຄືນ ແລະ ປຸ່ມພາບຮວມຄ້າງໄວ້ເພື່ອຍົກເລີກການປັກມຸດ."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ນີ້ຈະສະແດງມັນໃນໜ້າຈໍຈົນກວ່າທ່ານຈະເຊົາປັກໝຸດ. ໃຫ້ແຕະປຸ່ມກັບຄືນ ແລະ ປຸ່ມພາບຮວມຄ້າງໄວ້ເພື່ອຍົກເລີກການປັກໝຸດ."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 751e485..34a35b7 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Veidas neatpažintas. Naudokite kontrolinį kodą."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"„Bluetooth“ prijungtas."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akumuliatoriaus energija procentais nežinoma."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Prisijungta prie „<xliff:g id="BLUETOOTH">%s</xliff:g>“."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Atrakinta pagal veidą. Paspauskite, kad atidarytumėte."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Veidas atpažintas. Paspauskite, kad atidarytumėte."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Veidas atpažintas. Atidarykite paspaudę atrakin. piktogramą."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Atrakinta pagal veidą"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Veidas atpažintas"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Perkelti kairėn"</item>
<item msgid="5558598599408514296">"Perkelti žemyn"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sparčiai įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lėtai įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Įkraunama doke • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Perjungti naudotoją"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"išplečiamasis meniu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bus ištrintos visos šios sesijos programos ir duomenys."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Sveiki sugrįžę, svety!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Ar norite tęsti sesiją?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Subtitrų perdanga"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"įgalinti"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"išjungti"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Garsas ir vibravimas"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Nustatymai"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Programa prisegta"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Tai bus rodoma, kol atsegsite. Palieskite ir palaikykite „Atgal“ ir „Apžvalga“, kad atsegtumėte."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Tai bus rodoma, kol atsegsite. Palieskite ir palaikykite „Atgal“ ir „Pagrindinis ekranas“, kad atsegtumėte."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 8a19ef1..51d724c 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nevar atpazīt seju. Lietojiet pirksta nospiedumu."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth savienojums ir izveidots."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akumulatora uzlādes līmenis procentos nav zināms."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ir izveidots savienojum ar <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ierīce atbloķēta ar seju. Nospiediet, lai atvērtu."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Seja atpazīta. Nospiediet, lai atvērtu."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Seja atpazīta. Lai atvērtu, nospiediet atbloķēšanas ikonu."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ierīce atbloķēta pēc sejas"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Seja atpazīta"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Pārvietojiet pirkstu pa kreisi"</item>
<item msgid="5558598599408514296">"Pārvietojiet pirkstu lejup"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Notiek uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ātrā uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lēnā uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Notiek uzlāde dokā • Līdz pilnai uzlādei atlicis: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Notiek uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Mainīt lietotāju"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"novelkamā izvēlne"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tiks dzēstas visas šīs sesijas lietotnes un dati."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Laipni lūdzam atpakaļ, viesi!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vai vēlaties turpināt savu sesiju?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Subtitri pārklājas"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"iespējot"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"atspējot"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Lietotne ir piesprausta"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, pieskarieties pogām Atpakaļ un Pārskats un turiet tās."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, pieskarieties pogām “Atpakaļ” un “Sākums” un turiet tās."</string>
@@ -833,7 +842,7 @@
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Atlasītas vairākas ierīces (kopā <xliff:g id="COUNT">%1$d</xliff:g>)"</string>
<string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(savienojums pārtraukts)"</string>
<string name="media_output_dialog_connect_failed" msgid="3080972621975339387">"Nevar pārslēgt. Pieskarieties, lai mēģinātu vēlreiz."</string>
- <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"Savienošana ar ierīci"</string>
+ <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"Savienot ar ierīci"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Lai apraidītu šo sesiju, lūdzu, atveriet lietotni."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nezināma lietotne"</string>
<string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Apturēt apraidi"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 6f3076f..0032dffa 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Не се препознава ликот. Користете отпечаток."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth е поврзан."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Процентот на батеријата е непознат."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Поврзано со <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Отклучено со лик. Притиснете за да отворите."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Лицето е препознаено. Притиснете за да отворите."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лицето е препознаено. Притиснете ја иконата за отклучување за да отворите."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Отклучено со лице"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Лицето е препознаено"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Премести налево"</item>
<item msgid="5558598599408514296">"Премести надолу"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни брзо • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни бавно • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни на док • Полн за <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Промени го корисникот"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"паѓачко мени"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Сите апликации и податоци во сесијата ќе се избришат."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Добре дојде пак, гостине!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Дали сакате да продолжите со сесијата?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Преклопување титли"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"овозможи"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"оневозможи"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Звук и вибрации"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Поставки"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Апликацијата е закачена"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Ќе се гледа сѐ додека не го откачите. Допрете и држете „Назад“ и „Краток преглед“ за откачување."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ќе се гледа сѐ додека не го откачите. Допрете и задржете „Назад“ и „Почетен екран“ за откачување."</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 623fcbd..325589e 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"മുഖം തിരിച്ചറിയാനായില്ല. പകരം ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കൂ."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ബ്ലൂടൂത്ത് കണക്റ്റുചെയ്തു."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ബാറ്ററി ശതമാനം അജ്ഞാതമാണ്."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> എന്നതിലേക്ക് കണക്റ്റുചെയ്തു."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തു. തുറക്കാൻ അമർത്തുക."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"മുഖം തിരിച്ചറിഞ്ഞു. തുറക്കാൻ അമർത്തുക."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"മുഖം തിരിച്ചറിഞ്ഞു. തുറക്കാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തു"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"മുഖം തിരിച്ചറിഞ്ഞു"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"ഇടത്തേക്ക് നീക്കുക"</item>
<item msgid="5558598599408514296">"താഴേക്ക് നീക്കുക"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ചാർജിംഗ് ഡോക്ക് • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ഉപയോക്താവ് മാറുക"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"പുൾഡൗൺ മെനു"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ഈ സെഷനിലെ എല്ലാ ആപ്പുകളും ഡാറ്റയും ഇല്ലാതാക്കും."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"അതിഥി, വീണ്ടും സ്വാഗതം!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"നിങ്ങളുടെ സെഷൻ തുടരണോ?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"അടിക്കുറിപ്പുകൾ മുകളിൽ വയ്ക്കുക"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"പ്രവർത്തനക്ഷമമാക്കുക"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"പ്രവർത്തനരഹിതമാക്കുക"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"ആപ്പ് പിൻ ചെയ്തു"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ \'തിരികെ\', \'ചുരുക്കവിവരണം\' എന്നിവ സ്പർശിച്ച് പിടിക്കുക."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ \'തിരികെ പോവുക\', \'ഹോം\' ബട്ടണുകൾ സ്പർശിച്ച് പിടിക്കുക."</string>
@@ -921,7 +930,7 @@
<string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# ആപ്പ് സജീവമാണ്}other{# ആപ്പുകൾ സജീവമാണ്}}"</string>
<string name="fgs_dot_content_description" msgid="2865071539464777240">"പുതിയ വിവരങ്ങൾ"</string>
<string name="fgs_manager_dialog_title" msgid="5879184257257718677">"സജീവമായ ആപ്പുകൾ"</string>
- <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"നിങ്ങൾ ഉപയോഗിക്കാത്തപ്പോൾ പോലും ഈ ആപ്പുകൾ സജീവമായിരിക്കും, പ്രവർത്തിച്ചുകൊണ്ടിരിക്കുകയും ചെയ്യും. ഇത് അവയുടെ പ്രവർത്തനക്ഷമത മെച്ചപ്പെടുത്തുന്നു, എന്നാൽ ഇത് ബാറ്ററി ലൈഫിനെ ബാധിച്ചേക്കാനിടയുണ്ട്."</string>
+ <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"നിങ്ങൾ ഉപയോഗിക്കാത്തപ്പോൾ പോലും ഈ ആപ്പുകൾ സജീവമായിരിക്കുകയും പ്രവർത്തിച്ചുകൊണ്ടിരിക്കുകയും ചെയ്യും. ഇത് അവയുടെ പ്രവർത്തനക്ഷമത മെച്ചപ്പെടുത്തുന്നു, എങ്കിലും ഇത് ബാറ്ററി ലൈഫിനെ ബാധിച്ചേക്കാം."</string>
<string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"നിർത്തുക"</string>
<string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"നിർത്തി"</string>
<string name="clipboard_edit_text_done" msgid="4551887727694022409">"പൂർത്തിയായി"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index c340037..5b2dd37 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Царай таних боломжгүй. Оронд нь хурууны хээ ашигла"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth холбогдсон."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарейн хувь тодорхойгүй байна."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>-тай холбогдсон."</string>
@@ -239,8 +243,8 @@
<string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Төхөөрөмж байхгүй"</string>
<string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi-д холбогдоогүй байна"</string>
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Тодрол"</string>
- <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Өнгө урвуулах"</string>
- <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Өнгөний засвар"</string>
+ <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Өнгө хувиргалт"</string>
+ <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Өнгө тохируулга"</string>
<string name="quick_settings_more_user_settings" msgid="1064187451100861954">"Хэрэглэгчийн тохиргоо"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Дууссан"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Хаах"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Царайгаар түгжээг тайлсан. Нээхийн тулд дарна уу."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Царайг таньсан. Нээхийн тулд дарна уу."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Царайг таньсан. Нээх бол түгжээг тайлах дүрсийг дарна уу."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Царайгаар түгжээг тайлсан"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Царайг таньсан"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Зүүн тийш зөөх"</item>
<item msgid="5558598599408514296">"Доош зөөх"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Хурдтай цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Удаан цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Цэнэглэх холбогч • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Хэрэглэгчийг сэлгэх"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"эвхмэл цэс"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Энэ харилцан үйлдлийн бүх апп болон дата устах болно."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Эргэн тавтай морилно уу!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Та үргэлжлүүлэхийг хүсэж байна уу?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Давхарласан хадмал"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"идэвхжүүлэх"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"идэвхгүй болгох"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Дуу, чичиргээ"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Тохиргоо"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Аппыг бэхэлсэн"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Таныг тогтоосныг болиулах хүртэл үүнийг харуулна. Тогтоосныг болиулахын тулд Буцах, Тоймыг дараад хүлээнэ үү."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Таныг тогтоосныг болиулах хүртэл үүнийг харуулсан хэвээр байна. Тогтоосныг болиулахын тулд Буцах, Нүүр хуудас товчлуурыг дараад хүлээнэ үү."</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index d2f35452..b53641b 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"चेहरा ओळखू शकत नाही. त्याऐवजी फिंगरप्रिंट वापरा."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लूटूथ कनेक्ट केले."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"बॅटरीच्या चार्जिंगची टक्केवारी माहित नाही."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> शी कनेक्ट केले."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"चेहऱ्याने अनलॉक केले आहे. उघडण्यासाठी दाबा."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"चेहरा ओळखला आहे. उघडण्यासाठी दाबा."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"चेहरा ओळखला आहे. उघडण्यासाठी अनलॉक करा आयकन दाबा."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"चेहऱ्याने अनलॉक केले आहे"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"चेहरा ओळखला आहे"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"डावीकडे हलवा"</item>
<item msgid="5558598599408514296">"खाली हलवा"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • वेगाने चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • हळू चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्जिंग डॉक • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"वापरकर्ता स्विच करा"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेनू"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"या सत्रातील सर्व अॅप्स आणि डेटा हटवला जाईल."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"अतिथी, तुमचे पुन्हा स्वागत आहे!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"तुम्ही तुमचे सत्र सुरू ठेवू इच्छिता?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"कॅप्शन ओव्हरले करा"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"सुरू करा"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"बंद करा"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"आवाज आणि व्हायब्रेशन"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"सेटिंग्ज"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"ॲप पिन केले आहे"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"तुम्ही अनपिन करेर्यंत हे यास दृश्यामध्ये ठेवते. अनपिन करण्यासाठी परत आणि विहंगावलोकनास स्पर्श करा आणि धरून ठेवा."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"तुम्ही अनपिन करेर्यंत हे त्याला दृश्यामध्ये ठेवते. अनपिन करण्यासाठी मागे आणि होम वर स्पर्श करा आणि धरून ठेवा."</string>
@@ -574,7 +581,7 @@
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"कीबोर्ड शॉर्टकट"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"कीबोर्ड लेआउट स्विच करा"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ॲप्लिकेशन"</string>
- <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"सहाय्य"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assist"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ब्राउझर"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"संपर्क"</string>
<string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ईमेल"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index d569385..db73d54 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tidak mengenali wajah. Gunakan cap jari."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth disambungkan."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Peratusan kuasa bateri tidak diketahui."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Disambungkan kepada <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Dibuka kunci dengan wajah. Tekan untuk membuka."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Wajah dicam. Tekan untuk membuka."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Wajah dicam. Tekan ikon buka kunci untuk membuka."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Dibuka kunci dengan wajah"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Wajah dicam"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Alih ke kiri"</item>
<item msgid="5558598599408514296">"Alih ke bawah"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan cepat • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan perlahan • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan Dok • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Tukar pengguna"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu tarik turun"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua apl dan data dalam sesi ini akan dipadam."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Selamat kembali, tetamu!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Adakah anda ingin meneruskan sesi anda?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Tindanan kapsyen"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"dayakan"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"lumpuhkan"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Apl telah disemat"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Tindakan ini memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh & tahan Kembali dan Ikhtisar untuk menyahsemat."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Tindakan ini memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh & tahan Kembali dan Skrin Utama untuk menyahsemat."</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 24dc589..7b4bbaf 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -22,7 +22,7 @@
<string name="app_label" msgid="4811759950673118541">"စနစ်၏ UI"</string>
<string name="battery_low_title" msgid="5319680173344341779">"‘ဘက်ထရီ အားထိန်း’ ဖွင့်မလား။"</string>
<string name="battery_low_description" msgid="3282977755476423966">"သင့်တွင် ဘက်ထရီ <xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်သည်။ ‘ဘက်ထရီ အားထိန်း’ က ‘မှောင်သည့် အပြင်အဆင်’ ဖွင့်ပြီး နောက်ခံလုပ်ဆောင်ချက်ကို ကန့်သတ်ကာ အကြောင်းကြားချက်များကို နှောင့်နှေးစေသည်။"</string>
- <string name="battery_low_intro" msgid="5148725009653088790">"‘ဘက်ထရီ အားထိန်း’ က ‘မှောင်သည့် အပြင်အဆင်’ ဖွင့်ပြီး နောက်ခံလုပ်ဆောင်ချက်ကို ကန့်သတ်ကာ အကြောင်းကြားချက်များကို နှောင့်နှေးစေသည်။"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"‘ဘက်ထရီ အားထိန်း’ က ‘အမှောင်နောက်ခံ’ ကို ဖွင့်ပြီး နောက်ခံလုပ်ဆောင်ချက်ကို ကန့်သတ်ကာ အကြောင်းကြားချက်များကို နှောင့်နှေးစေသည်။"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်ရှိနေ"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB ဖြင့် အားသွင်း၍မရပါ"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"သင့်စက်ပစ္စည်းနှင့် အတူပါလာသည့် အားသွင်းကိရိယာကို အသုံးပြုပါ"</string>
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"မျက်နှာကို မမှတ်မိပါ။ လက်ဗွေကို အစားထိုးသုံးပါ။"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ဘလူးတုသ်ချိတ်ဆက်ထားမှု"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ဘက်ထရီရာခိုင်နှုန်းကို မသိပါ။"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>သို့ ချိတ်ဆက်ထား"</string>
@@ -266,7 +270,7 @@
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"နေထွက်ချိန် အထိ"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> တွင် ဖွင့်ရန်"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> အထိ"</string>
- <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"မှောင်သည့် အပြင်အဆင်"</string>
+ <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"အမှောင်နောက်ခံ"</string>
<string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ဘက်ထရီ အားထိန်း"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"နေဝင်ချိန်၌ ဖွင့်ရန်"</string>
<string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"နေထွက်ချိန် အထိ"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"မျက်နှာဖြင့် ဖွင့်ထားသည်။ ဖွင့်ရန် နှိပ်ပါ။"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"မျက်နှာ မှတ်မိသည်။ ဖွင့်ရန် နှိပ်ပါ။"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"မျက်နှာ မှတ်မိသည်။ ဖွင့်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"မျက်နှာဖြင့် ဖွင့်လိုက်သည်"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"မျက်နှာ မှတ်မိသည်"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"ဘယ်ဘက်သို့ရွှေ့ရန်"</item>
<item msgid="5558598599408514296">"အောက်သို့ရွှေ့ရန်"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အမြန်အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အားသွင်းအထိုင် • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> တွင် ပြည့်မည်"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"အသုံးပြုသူကို ပြောင်းလဲရန်"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ဆွဲချမီနူး"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ဒီချိတ်ဆက်မှု ထဲက အက်ပ်များ အားလုံး နှင့် ဒေတာကို ဖျက်ပစ်မည်။"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ဧည့်သည်ကို ပြန်လည် ကြိုဆိုပါသည်။"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"သင်၏ စက်ရှင်ကို ဆက်လုပ်လိုပါသလား။"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"စာတန်းများ ထပ်ပိုးရန်"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ဖွင့်ရန်"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ပိတ်ရန်"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"အသံနှင့် တုန်ခါမှု"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ဆက်တင်များ"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"အက်ပ်ကို ပင်ထိုးထားသည်"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"သင်ပင်မဖြုတ်မခြင်း ၎င်းကို ပြသထားပါမည်။ ပင်ဖြုတ်ရန် Back နှင့် Overview ကို ထိ၍ဖိထားပါ။"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"သင်က ပင်မဖြုတ်မခြင်း ၎င်းကို ပြသထားပါမည်။ ပင်ဖြုတ်ရန် \'နောက်သို့\' နှင့် \'ပင်မ\' ခလုတ်တို့ကို တို့၍ဖိထားပါ။"</string>
@@ -568,7 +575,7 @@
<string name="notif_inline_reply_remove_attachment_description" msgid="7954075334095405429">"ပူးတွဲပါဖိုင်ကို ဖယ်ရှားရန်"</string>
<string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"စနစ်"</string>
<string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"ပင်မ"</string>
- <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"လတ်တလော"</string>
+ <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"မကြာသေးမီက"</string>
<string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"နောက်သို့"</string>
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"အကြောင်းကြားချက်များ"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"ကီးဘုတ် ဖြတ်လမ်းများ"</string>
@@ -833,7 +840,7 @@
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"စက်ပစ္စည်း <xliff:g id="COUNT">%1$d</xliff:g> ခုကို ရွေးချယ်ထားသည်"</string>
<string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(ချိတ်ဆက်မှု မရှိပါ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3080972621975339387">"ပြောင်း၍ မရပါ။ ပြန်စမ်းကြည့်ရန် တို့ပါ။"</string>
- <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"ကိရိယာနှင့်ချိတ်ဆက်ရန်"</string>
+ <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"စက်တစ်ခုနှင့် ချိတ်ဆက်ရန်"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"အက်ပ်ဖွင့်ပြီး ဤစက်ရှင်ကို ကာစ်လုပ်နိုင်သည်။"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"အမည်မသိ အက်ပ်"</string>
<string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ကာစ် ရပ်ရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 090d64b..3d03ebf 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansiktet gjenkjennes ikke. Bruk fingeravtrykk."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth er tilkoblet."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batteriprosenten er ukjent."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Koblet til <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -227,7 +231,7 @@
<string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Blokkert"</string>
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Medieenhet"</string>
<string name="quick_settings_user_title" msgid="8673045967216204537">"Bruker"</string>
- <string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
+ <string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wifi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internett"</string>
<string name="quick_settings_networks_available" msgid="1875138606855420438">"Tilgjengelige nettverk"</string>
<string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Nettverk er utilgjengelige"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Låst opp med ansiktet. Trykk for å åpne."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Ansiktet er gjenkjent. Trykk for å åpne."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ansiktet er gjenkjent. Trykk på lås opp-ikon for å fortsette"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Låst opp med ansiktet"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ansiktet er gjenkjent"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Flytt til venstre"</item>
<item msgid="5558598599408514296">"Flytt ned"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader raskt • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader sakte • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ladedokk • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Bytt bruker"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullegardinmeny"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apper og data i denne økten blir slettet."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Velkommen tilbake, gjest!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vil du fortsette økten?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Overlegg med teksting"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktivér"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiver"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Appen er festet"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Gjør at den vises til du løsner den. Trykk og hold inne Tilbake og Oversikt for å løsne den."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Gjør at den vises til du løsner den. Trykk og hold inne Tilbake og Startside for å løsne den."</string>
@@ -904,7 +913,7 @@
<string name="mobile_data_no_connection" msgid="1713872434869947377">"Ingen tilkobling"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ingen andre nettverk er tilgjengelige"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"Ingen nettverk er tilgjengelige"</string>
- <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
+ <string name="turn_on_wifi" msgid="1308379840799281023">"Wifi"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Trykk på et nettverk for å koble til"</string>
<string name="unlock_to_view_networks" msgid="5072880496312015676">"Lås opp for å se nettverk"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Søker etter nettverk …"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 415137c..6e298df 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"अनुहार पहिचान गर्न सकिएन। बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्।"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लुटुथ जडान भयो।"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ब्याट्रीमा कति प्रतिशत चार्ज छ भन्ने कुराको जानाकरी छैन।"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> मा जडित।"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"अनुहार प्रयोग गरी अनलक गरियो। डिभाइस खोल्न थिच्नुहोस्।"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"अनुहार पहिचान गरियो। डिभाइस खोल्न थिच्नुहोस्।"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"अनुहार पहिचान गरियो। डिभाइस खोल्न अनलक आइकनमा थिच्नुहोस्।"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"अनुहार प्रयोग गरी अनलक गरियो"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"अनुहार पहिचान गरियो"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"बायाँ सार्नुहोस्"</item>
<item msgid="5558598599408514296">"तल सार्नुहोस्"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • छिटो चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • बिस्तारै चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • डक चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा फुल चार्ज हुने छ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"प्रयोगकर्ता फेर्नुहोस्"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेनु"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"यो सत्रमा भएका सबै एपहरू र डेटा मेटाइने छ।"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"तपाईंलाई फेरि स्वागत छ, अतिथि"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"तपाईं आफ्नो सत्र जारी गर्न चाहनुहुन्छ?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"क्याप्सनको ओभरले"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"सक्षम पार्नुहोस्"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"असक्षम पार्नुहोस्"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"साउन्ड तथा भाइब्रेसन"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"सेटिङ"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"एप पिन गरिएको छ"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न पछाडि र परिदृश्य बटनलाई टच एण्ड होल्ड गर्नुहोस्।"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न पछाडि र गृह नामक बटनहरूलाई टच एण्ड होल्ड गर्नुहोस्।"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index d631990..3a50909 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Gezicht niet herkend. Gebruik je vingerafdruk."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-verbinding ingesteld."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batterijpercentage onbekend."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Verbonden met <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ontgrendeld via gezicht. Druk om te openen."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Gezicht herkend. Druk om te openen."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Gezicht herkend. Druk op het ontgrendelicoon."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ontgrendeld via gezicht"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Gezicht herkend"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Naar links verplaatsen"</item>
<item msgid="5558598599408514296">"Omlaag verplaatsen"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Snel opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Langzaam opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplaaddock • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Gebruiker wijzigen"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pull-downmenu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps en gegevens in deze sessie worden verwijderd."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Welkom terug, gast!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Wil je doorgaan met je sessie?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Ondertitelingsoverlay"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aanzetten"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"uitzetten"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Geluid en trillen"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Instellingen"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"App is vastgezet"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Het scherm blijft zichtbaar totdat je het losmaakt. Tik op Terug en Overzicht en houd deze vast om het scherm los te maken."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Het scherm blijft zichtbaar totdat je het losmaakt. Tik op Terug en Home en houd deze vast om het scherm los te maken."</string>
@@ -921,7 +928,7 @@
<string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app is actief}other{# apps zijn actief}}"</string>
<string name="fgs_dot_content_description" msgid="2865071539464777240">"Nieuwe informatie"</string>
<string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Actieve apps"</string>
- <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Deze apps zijn actief, ook als je ze niet gebruikt. Dit verbetert de functionaliteit, maar kan ook van invloed zijn op de batterijduur."</string>
+ <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Deze apps zijn actief, ook als je ze niet gebruikt. Dit verbetert de functionaliteit, maar kan de batterijduur ook beïnvloeden."</string>
<string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"Stoppen"</string>
<string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"Gestopt"</string>
<string name="clipboard_edit_text_done" msgid="4551887727694022409">"Klaar"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 81c4580..671e60f 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -31,7 +31,7 @@
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ଚାଲୁ କରନ୍ତୁ"</string>
<string name="battery_saver_start_action" msgid="8353766979886287140">"ଚାଲୁ କରନ୍ତୁ"</string>
<string name="battery_saver_dismiss_action" msgid="7199342621040014738">"ନା, ଧନ୍ୟବାଦ"</string>
- <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ଅଟୋ-ରୋଟେଟ୍ ସ୍କ୍ରିନ୍"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ଅଟୋ-ରୋଟେଟ ସ୍କ୍ରିନ"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ଆକ୍ସେସ୍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ଆକ୍ସେସ୍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ କି?\nଏହି ଆପ୍କୁ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ କିନ୍ତୁ ଏହି USB ଡିଭାଇସ୍ ଜରିଆରେ ଅଡିଓ କ୍ୟାପ୍ଟର୍ କରିପାରିବ।"</string>
<string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>କୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
@@ -97,7 +97,7 @@
<string name="screenrecord_audio_label" msgid="6183558856175159629">"ଅଡିଓ ରେକର୍ଡ କରନ୍ତୁ"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ଡିଭାଇସ୍ ଅଡିଓ"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"ଆପଣଙ୍କ ଡିଭାଇସରୁ ସାଉଣ୍ଡ, ଯେପରିକି ସଙ୍ଗୀତ, କଲ୍ ଏବଂ ରିଂଟୋନଗୁଡ଼ିକ"</string>
- <string name="screenrecord_mic_label" msgid="2111264835791332350">"ମାଇକ୍ରୋଫୋନ୍"</string>
+ <string name="screenrecord_mic_label" msgid="2111264835791332350">"ମାଇକ୍ରୋଫୋନ"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"ଡିଭାଇସ୍ ଅଡିଓ ଏବଂ ମାଇକ୍ରୋଫୋନ୍"</string>
<string name="screenrecord_start" msgid="330991441575775004">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"ସ୍କ୍ରିନ୍ ରେକର୍ଡ କରାଯାଉଛି"</string>
@@ -116,7 +116,7 @@
<string name="accessibility_rotate_button" msgid="1238584767612362586">"ସ୍କ୍ରୀନ୍କୁ ଘୁରାନ୍ତୁ"</string>
<string name="accessibility_recent" msgid="901641734769533575">"ଓଭରଭିଉ"</string>
<string name="accessibility_camera_button" msgid="2938898391716647247">"କ୍ୟାମେରା"</string>
- <string name="accessibility_phone_button" msgid="4256353121703100427">"ଫୋନ୍"</string>
+ <string name="accessibility_phone_button" msgid="4256353121703100427">"ଫୋନ"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ଭଏସ୍ ସହାୟକ"</string>
<string name="accessibility_wallet_button" msgid="1458258783460555507">"ୱାଲେଟ୍"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR କୋଡ ସ୍କାନର"</string>
@@ -161,13 +161,17 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ଫେସ୍ ଚିହ୍ନଟ କରିହେବ ନାହିଁ। ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ବ୍ଲୁଟୂଥ୍ ସଂଯୋଗ କରାଯାଇଛି।"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ବ୍ୟାଟେରୀ ଶତକଡ଼ା ଅଜଣା ଅଟେ।"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ସହ ସଂଯୁକ୍ତ"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> ସହିତ ସଂଯୁକ୍ତ।"</string>
- <string name="accessibility_not_connected" msgid="4061305616351042142">"ସଂଯୁକ୍ତ ହୋଇନାହିଁ।"</string>
+ <string name="accessibility_not_connected" msgid="4061305616351042142">"କନେକ୍ଟ ହୋଇନାହିଁ।"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"ରୋମିଙ୍ଗ"</string>
- <string name="cell_data_off" msgid="4886198950247099526">"ବନ୍ଦ"</string>
+ <string name="cell_data_off" msgid="4886198950247099526">"ବନ୍ଦ ଅଛି"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"ଏରୋପ୍ଲେନ୍ ମୋଡ୍।"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ଅନ୍।"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"ବ୍ୟାଟେରୀ <xliff:g id="NUMBER">%d</xliff:g> ଶତକଡ଼ା।"</string>
@@ -218,11 +222,11 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"ଶ୍ରବଣ ଯନ୍ତ୍ର"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ଅନ୍ ହେଉଛି…"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ଅଟୋ-ରୋଟେଟ୍"</string>
- <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ଅଟୋ-ରୋଟେଟ୍ ସ୍କ୍ରିନ୍"</string>
- <string name="quick_settings_location_label" msgid="2621868789013389163">"ଲୋକେସନ୍"</string>
+ <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ଅଟୋ-ରୋଟେଟ ସ୍କ୍ରିନ"</string>
+ <string name="quick_settings_location_label" msgid="2621868789013389163">"ଲୋକେସନ"</string>
<string name="quick_settings_screensaver_label" msgid="1495003469366524120">"ସ୍କ୍ରିନ ସେଭର"</string>
- <string name="quick_settings_camera_label" msgid="5612076679385269339">"କ୍ୟାମେରା ଆକ୍ସେସ୍"</string>
- <string name="quick_settings_mic_label" msgid="8392773746295266375">"ମାଇକ୍ ଆକ୍ସେସ୍"</string>
+ <string name="quick_settings_camera_label" msgid="5612076679385269339">"କ୍ୟାମେରା ଆକ୍ସେସ"</string>
+ <string name="quick_settings_mic_label" msgid="8392773746295266375">"ମାଇକ ଆକ୍ସେସ"</string>
<string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"ଉପଲବ୍ଧ"</string>
<string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"ବ୍ଲକ୍ କରାଯାଇଛି"</string>
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"ମିଡିଆ ଡିଭାଇସ୍"</string>
@@ -233,7 +237,7 @@
<string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"ନେଟୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"କୌଣସି ୱାଇ-ଫାଇ ନେଟ୍ୱର୍କ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"ଅନ୍ ହେଉଛି…"</string>
- <string name="quick_settings_cast_title" msgid="2279220930629235211">"ସ୍କ୍ରିନ୍ କାଷ୍ଟ"</string>
+ <string name="quick_settings_cast_title" msgid="2279220930629235211">"ସ୍କ୍ରିନ କାଷ୍ଟ"</string>
<string name="quick_settings_casting" msgid="1435880708719268055">"କାଷ୍ଟିଙ୍ଗ"</string>
<string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"ନାମହୀନ ଡିଭାଇସ୍"</string>
<string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"କୌଣସି ଡିଭାଇସ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
@@ -241,7 +245,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ଉଜ୍ଜ୍ୱଳତା"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ରଙ୍ଗ ଇନଭାର୍ସନ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ରଙ୍ଗ ସଂଶୋଧନ"</string>
- <string name="quick_settings_more_user_settings" msgid="1064187451100861954">"ଉପଯୋଗକର୍ତ୍ତା ସେଟିଂସ୍"</string>
+ <string name="quick_settings_more_user_settings" msgid="1064187451100861954">"ଉପଯୋଗକର୍ତ୍ତା ସେଟିଂସ"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ହୋଇଗଲା"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="quick_settings_connected" msgid="3873605509184830379">"ସଂଯୁକ୍ତ"</string>
@@ -277,15 +281,15 @@
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ସକ୍ଷମ କରାଯାଇଛି"</string>
- <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ସ୍କ୍ରିନ୍ ରେକର୍ଡ"</string>
+ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ସ୍କ୍ରିନ ରେକର୍ଡ"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ଏକ-ହାତ ମୋଡ"</string>
- <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ଡିଭାଇସର ମାଇକ୍ରୋଫୋନକୁ ଅନବ୍ଲକ୍ କରିବେ?"</string>
- <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ଡିଭାଇସର କ୍ୟାମେରାକୁ ଅନବ୍ଲକ୍ କରିବେ?"</string>
+ <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ଡିଭାଇସର ମାଇକ୍ରୋଫୋନକୁ ଅନବ୍ଲକ କରିବେ?"</string>
+ <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ଡିଭାଇସର କ୍ୟାମେରାକୁ ଅନବ୍ଲକ କରିବେ?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ଡିଭାଇସର କ୍ୟାମେରା ଏବଂ ମାଇକ୍ରୋଫୋନକୁ ଅନବ୍ଲକ୍ କରିବେ?"</string>
- <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ଆପଣଙ୍କ ମାଇକ୍ରୋଫୋନକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string>
- <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ଆପଣଙ୍କ କ୍ୟାମେରାକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string>
+ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ଆପଣଙ୍କ ମାଇକ୍ରୋଫୋନକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ସ ଓ ସେବାଗୁଡ଼ିକ ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ କରେ।"</string>
+ <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ଆପଣଙ୍କ କ୍ୟାମେରାକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ସ ଓ ସେବାଗୁଡ଼ିକ ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ କରେ।"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ଆପଣଙ୍କ କ୍ୟାମେରା କିମ୍ବା ମାଇକ୍ରୋଫୋନକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string>
<string name="sensor_privacy_start_use_mic_blocked_dialog_title" msgid="2640140287496469689">"ମାଇକ୍ରୋଫୋନକୁ ବ୍ଲକ କରାଯାଇଛି"</string>
<string name="sensor_privacy_start_use_camera_blocked_dialog_title" msgid="7398084286822440384">"କ୍ୟାମେରାକୁ ବ୍ଲକ କରାଯାଇଛି"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି। ଖୋଲିବାକୁ ଦବାନ୍ତୁ।"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି। ଖୋଲିବାକୁ ଦବାନ୍ତୁ।"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି। ଖୋଲିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ।"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"ବାମକୁ ମୁଭ କରନ୍ତୁ"</item>
<item msgid="5558598599408514296">"ତଳକୁ ମୁଭ କରନ୍ତୁ"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଡକରୁ ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ୟୁଜର୍ ବଦଳାନ୍ତୁ"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ପୁଲଡାଉନ ମେନୁ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ଏହି ସେସନର ସମସ୍ତ ଆପ୍ ଓ ଡାଟା ଡିଲିଟ୍ ହୋଇଯିବ।"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ପୁଣି ସ୍ୱାଗତ, ଅତିଥି!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ଆପଣ ନିଜର ସେସନ୍ ଜାରି ରଖିବାକୁ ଚାହାଁନ୍ତି କି?"</string>
@@ -394,9 +399,9 @@
<string name="monitoring_subtitle_ca_certificate" msgid="8588092029755175800">"CA ସର୍ଟିଫିକେଟ୍"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"ପଲିସୀ ଦେଖନ୍ତୁ"</string>
<string name="monitoring_button_view_controls" msgid="8316440345340701117">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ"</string>
- <string name="monitoring_description_named_management" msgid="505833016545056036">"ଏହି ଡିଭାଇସଟି <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>ର ଅଟେ।\n\nଆପଣଙ୍କ IT ଆଡମିନ୍ ସେଟିଂସ୍, କର୍ପୋରେଟ୍ ଆକ୍ସେସ୍, ଆପ୍ସ, ଆପଣଙ୍କ ଡିଭାଇସ୍ ସହ ସମ୍ବନ୍ଧିତ ଡାଟା ଏବଂ ଆପଣଙ୍କ ଡିଭାଇସର ଲୋକେସନ୍ ସୂଚନାକୁ ନିରୀକ୍ଷଣ ଏବଂ ପରିଚାଳନା କରିପାରିବେ।\n\nଅଧିକ ସୂଚନା ପାଇଁ, ଆପଣଙ୍କ IT ଆଡମିନଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
- <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> ଏହି ଡିଭାଇସ ସହ ସମ୍ବନ୍ଧିତ ଡାଟା ଆକ୍ସେସ୍ କରିବା, ଆପଗୁଡ଼ିକୁ ପରିଚାଳନା କରିବା ଏବଂ ଏହି ଡିଭାଇସର ସେଟିଂସ୍ ବଦଳାଇବାକୁ ସକ୍ଷମ ହୋଇପାରେ।\n\nଯଦି ଆପଣଙ୍କର କିଛି ପ୍ରଶ୍ନ ଅଛି, ତେବେ <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g> ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
- <string name="monitoring_description_management" msgid="4308879039175729014">"ଏହି ଡିଭାଇସଟି ଆପଣଙ୍କ ସଂସ୍ଥାର ଅଟେ।\n\nଆପଣଙ୍କ IT ଆଡମିନ୍ ସେଟିଂସ୍, କର୍ପୋରେଟ୍ ଆକ୍ସେସ୍, ଆପ୍ସ, ଆପଣଙ୍କ ଡିଭାଇସ୍ ସହ ସମ୍ବନ୍ଧିତ ଡାଟା ଏବଂ ଆପଣଙ୍କ ଡିଭାଇସର ଲୋକେସନ୍ ସୂଚନାକୁ ନିରୀକ୍ଷଣ ଏବଂ ପରିଚାଳନା କରିପାରିବେ।\n\nଅଧିକ ସୂଚନା ପାଇଁ, ଆପଣଙ୍କ IT ଆଡମିନଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"ଏହି ଡିଭାଇସଟି <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>ର ଅଟେ।\n\nଆପଣଙ୍କ IT ଆଡମିନ ସେଟିଂସ, କର୍ପୋରେଟ ଆକ୍ସେସ, ଆପ୍ସ, ଆପଣଙ୍କ ଡିଭାଇସ ସହ ସମ୍ବନ୍ଧିତ ଡାଟା ଏବଂ ଆପଣଙ୍କ ଡିଭାଇସର ଲୋକେସନ ସୂଚନାକୁ ନିରୀକ୍ଷଣ ଏବଂ ପରିଚାଳନା କରିପାରିବେ।\n\nଅଧିକ ସୂଚନା ପାଇଁ, ଆପଣଙ୍କ IT ଆଡମିନଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
+ <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> ଏହି ଡିଭାଇସ ସହ ସମ୍ବନ୍ଧିତ ଡାଟା ଆକ୍ସେସ କରିବା, ଆପଗୁଡ଼ିକୁ ପରିଚାଳନା କରିବା ଏବଂ ଏହି ଡିଭାଇସର ସେଟିଂସ ବଦଳାଇବାକୁ ସକ୍ଷମ ହୋଇପାରେ।\n\nଯଦି ଆପଣଙ୍କର କିଛି ପ୍ରଶ୍ନ ଅଛି, ତେବେ <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g> ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"ଏହି ଡିଭାଇସଟି ଆପଣଙ୍କ ସଂସ୍ଥାର ଅଟେ।\n\nଆପଣଙ୍କ IT ଆଡମିନ ସେଟିଂସ, କର୍ପୋରେଟ ଆକ୍ସେସ, ଆପ୍ସ, ଆପଣଙ୍କ ଡିଭାଇସ ସହ ସମ୍ବନ୍ଧିତ ଡାଟା ଏବଂ ଆପଣଙ୍କ ଡିଭାଇସର ଲୋକେସନ ସୂଚନାକୁ ନିରୀକ୍ଷଣ ଏବଂ ପରିଚାଳନା କରିପାରିବେ।\n\nଅଧିକ ସୂଚନା ପାଇଁ, ଆପଣଙ୍କ IT ଆଡମିନଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ଏହି ଡିଭାଇସରେ ଆପଣଙ୍କ ସଂସ୍ଥା ଏକ ସର୍ଟିଫିକେଟ୍ ଅଥରିଟି ଇନଷ୍ଟଲ୍ କରିଛନ୍ତି। ଆପଣଙ୍କ ସୁରକ୍ଷିତ ନେଟୱର୍କ ଟ୍ରାଫିକ୍ ନୀରିକ୍ଷଣ କିମ୍ବା ସଂଶୋଧନ କରାଯାଇ ପାରେ।"</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ଆପଣଙ୍କ ୱର୍କ ପ୍ରୋଫାଇଲରେ ଆପଣଙ୍କ ସଂସ୍ଥା ଏକ ସର୍ଟିଫିକେଟ୍ ଅଥରିଟି ଇନଷ୍ଟଲ୍ କରିଛନ୍ତି। ଆପଣଙ୍କ ସୁରକ୍ଷିତ ନେଟୱର୍କ ଟ୍ରାଫିକ୍ ନୀରିକ୍ଷଣ କିମ୍ବା ସଂଶୋଧନ କରାଯାଇ ପାରେ।"</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ଏହି ଡିଭାଇସରେ ଏକ ସର୍ଟିଫିକେଟ୍ ଅଥରିଟି ଇନଷ୍ଟଲ୍ କରାଯାଇଛି। ଆପଣଙ୍କ ସୁରକ୍ଷିତ ନେଟୱର୍କ ଟ୍ରାଫିକ୍ ନୀରିକ୍ଷଣ କିମ୍ବା ସଂଶୋଧନ କରାଯାଇ ପାରେ।"</string>
@@ -418,23 +423,25 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"କ୍ୟାପ୍ସନ୍ର ଓଭର୍ଲେ"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ସକ୍ଷମ କରନ୍ତୁ"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ଅକ୍ଷମ କରନ୍ତୁ"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"ସାଉଣ୍ଡ ଓ ଭାଇବ୍ରେସନ"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ସେଟିଂସ"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"ଆପକୁ ପିନ୍ କରାଯାଇଛି"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"ଆପଣ ଅନପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଉଥିବ। ଅନପିନ୍ କରିବାକୁ ସ୍ପର୍ଶ କରି ଧରିରଖନ୍ତୁ ଓ ଦେଖନ୍ତୁ।"</string>
- <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ଆପଣ ଅନପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଉଥିବ। ଅନପିନ୍ କରିବା ପାଇଁ ହୋମ୍ ଓ ବ୍ୟାକ୍ ବଟନ୍କୁ ଧରିରଖନ୍ତୁ।"</string>
+ <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ଆପଣ ଅନପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଉଥିବ। ଅନପିନ୍ କରିବା ପାଇଁ ହୋମ ଓ ବ୍ୟାକ ବଟନକୁ ଦବାଇ ଧରନ୍ତୁ।"</string>
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"ଆପଣ ଅନ୍ପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଯାଉଥିବ। ଅନ୍ପିନ୍ କରିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରି ଧରି ରଖନ୍ତୁ।"</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"ଆପଣ ଅନପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଉଥିବ। ଅନପିନ୍ କରିବାକୁ ସ୍ପର୍ଶ କରନ୍ତୁ ଏବଂ ଓଭରଭ୍ୟୁକୁ ଧରିରଖନ୍ତୁ।"</string>
- <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"ଆପଣ ଅନପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଉଥିବ। ଅନପିନ୍ କରିବା ପର୍ଯ୍ୟନ୍ତ ହୋମ୍କୁ ଦାବିଧରନ୍ତୁ।"</string>
+ <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"ଆପଣ ଅନପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଉଥିବ। ଅନପିନ୍ କରିବା ପର୍ଯ୍ୟନ୍ତ ହୋମକୁ ଦବାଇ ଧରନ୍ତୁ।"</string>
<string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"ବ୍ୟକ୍ତିଗତ ଡାଟାକୁ ଆକ୍ସେସ୍ କରାଯାଇପାରେ (ଯେପରିକି ଯୋଗାଯୋଗଗୁଡ଼ିକ ଏବଂ ଇମେଲ୍ ବିଷୟବସ୍ତୁ)।"</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"ପିନ୍ କରାଯାଇଥିବା ଆପଟି ଅନ୍ୟ ଆପଗୁଡ଼ିକୁ ଖୋଲିପାରେ।"</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"ଏହି ଆପକୁ ଅନପିନ୍ କରିବା ପାଇଁ, \"ବ୍ୟାକ୍\" ଏବଂ \"ଓଭରଭିଉ\" ବଟନକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
- <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"ଏହି ଆପକୁ ଅନପିନ୍ କରିବାକୁ, \"ବ୍ୟାକ୍\" ଏବଂ \"ହୋମ୍\" ବଟନକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
+ <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"ଏହି ଆପକୁ ଅନପିନ କରିବାକୁ, \"ବ୍ୟାକ\" ଏବଂ \"ହୋମ\" ବଟନକୁ ସ୍ପର୍ଶ କରି ଦବାଇ ଧରନ୍ତୁ"</string>
<string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"ଏହି ଆପକୁ ଅନପିନ୍ କରିବାକୁ, ଉପରକୁ ସ୍ୱାଇପ୍ କରି ଧରି ରଖନ୍ତୁ"</string>
<string name="screen_pinning_positive" msgid="3285785989665266984">"ବୁଝିଗଲି"</string>
<string name="screen_pinning_negative" msgid="6882816864569211666">"ନାହିଁ, ଥାଉ"</string>
<string name="screen_pinning_start" msgid="7483998671383371313">"ଆପ୍ ପିନ୍ କରାଯାଇଛି"</string>
<string name="screen_pinning_exit" msgid="4553787518387346893">"ଆପ୍ ଅନପିନ୍ କରାଯାଇଛି"</string>
<string name="stream_voice_call" msgid="7468348170702375660">"କଲ୍ କରନ୍ତୁ"</string>
- <string name="stream_system" msgid="7663148785370565134">"ସିଷ୍ଟମ୍"</string>
+ <string name="stream_system" msgid="7663148785370565134">"ସିଷ୍ଟମ"</string>
<string name="stream_ring" msgid="7550670036738697526">"ରିଙ୍ଗ"</string>
<string name="stream_music" msgid="2188224742361847580">"ମିଡିଆ"</string>
<string name="stream_alarm" msgid="16058075093011694">"ଆଲାରାମ୍"</string>
@@ -566,9 +573,9 @@
<string name="keyboard_key_num_lock" msgid="7209960042043090548">"ନମ୍ବର ଲକ୍"</string>
<string name="keyboard_key_numpad_template" msgid="7316338238459991821">"ନମ୍ବରପ୍ୟାଡ୍ <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="notif_inline_reply_remove_attachment_description" msgid="7954075334095405429">"ଆଟାଚମେଣ୍ଟ୍ କାଢ଼ି ଦିଅନ୍ତୁ"</string>
- <string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"ସିଷ୍ଟମ୍"</string>
+ <string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"ସିଷ୍ଟମ"</string>
<string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"ହୋମ"</string>
- <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"ସମ୍ପ୍ରତି"</string>
+ <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"ବର୍ତ୍ତମାନର"</string>
<string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"ଫେରନ୍ତୁ"</string>
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ବିଜ୍ଞପ୍ତି"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"କୀ\'ବୋର୍ଡ ସର୍ଟକଟ୍"</string>
@@ -576,11 +583,11 @@
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ଆପ୍ଲିକେସନ୍"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"ସହାୟତା"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ବ୍ରାଉଜର୍"</string>
- <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"ଯୋଗାଯୋଗ"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"କଣ୍ଟାକ୍ଟ"</string>
<string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ଇମେଲ୍"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"ମ୍ୟୁଜିକ୍"</string>
- <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"କ୍ୟାଲେଣ୍ଡର୍"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"କ୍ୟାଲେଣ୍ଡର"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ଭଲ୍ୟୁମ ବଟନ୍ ଶର୍ଟକଟ୍"</string>
<string name="battery" msgid="769686279459897127">"ବ୍ୟାଟେରୀ"</string>
@@ -588,10 +595,10 @@
<string name="accessibility_long_click_tile" msgid="210472753156768705">"ସେଟିଂସ୍ ଖୋଲନ୍ତୁ"</string>
<string name="accessibility_status_bar_headphones" msgid="1304082414912647414">"ହେଡଫୋନ୍ ସଂଯୁକ୍ତ"</string>
<string name="accessibility_status_bar_headset" msgid="2699275863720926104">"ହେଡସେଟ୍ ସଂଯୁକ୍ତ"</string>
- <string name="data_saver" msgid="3484013368530820763">"ଡାଟା ସେଭର୍"</string>
+ <string name="data_saver" msgid="3484013368530820763">"ଡାଟା ସେଭର"</string>
<string name="accessibility_data_saver_on" msgid="5394743820189757731">"ଡାଟା ସେଭର୍ ଅନ୍ ଅଛି"</string>
- <string name="switch_bar_on" msgid="1770868129120096114">"ଚାଲୁ"</string>
- <string name="switch_bar_off" msgid="5669805115416379556">"ବନ୍ଦ"</string>
+ <string name="switch_bar_on" msgid="1770868129120096114">"ଚାଲୁ ଅଛି"</string>
+ <string name="switch_bar_off" msgid="5669805115416379556">"ବନ୍ଦ ଅଛି"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"ଅନୁପଲବ୍ଧ"</string>
<string name="tile_disabled" msgid="373212051546573069">"ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="nav_bar" msgid="4642708685386136807">"ନାଭିଗେଶନ୍ ବାର୍"</string>
@@ -618,7 +625,7 @@
<string name="right_keycode" msgid="2480715509844798438">"ଡାହାଣ କୀ\'କୋଡ୍"</string>
<string name="left_icon" msgid="5036278531966897006">"ବାମ ଆଇକନ୍"</string>
<string name="right_icon" msgid="1103955040645237425">"ଡାହାଣ ଆଇକନ୍"</string>
- <string name="drag_to_add_tiles" msgid="8933270127508303672">"ଟାଇଲ୍ ଯୋଗ କରିବା ପାଇଁ ଦାବିଧରି ଟାଣନ୍ତୁ"</string>
+ <string name="drag_to_add_tiles" msgid="8933270127508303672">"ଟାଇଲ୍ ଯୋଗ କରିବା ପାଇଁ ଦାବିଧରି ଡ୍ରାଗ କରନ୍ତୁ"</string>
<string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"ଟାଇଲ୍ ପୁଣି ସଜାଇବାକୁ ଦାବିଧରି ଟାଣନ୍ତୁ"</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"ବାହାର କରିବାକୁ ଏଠାକୁ ଡ୍ରାଗ୍ କରନ୍ତୁ"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"ଆପଣଙ୍କର ଅତିକମ୍ରେ <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g>ଟି ଟାଇଲ୍ ଆବଶ୍ୟକ"</string>
@@ -688,7 +695,7 @@
<string name="notification_channel_screenshot" msgid="7665814998932211997">"ସ୍କ୍ରୀନଶଟ୍"</string>
<string name="notification_channel_instant" msgid="7556135423486752680">"Instant Apps"</string>
<string name="notification_channel_setup" msgid="7660580986090760350">"ସେଟଅପ"</string>
- <string name="notification_channel_storage" msgid="2720725707628094977">"ଷ୍ଟୋରେଜ୍"</string>
+ <string name="notification_channel_storage" msgid="2720725707628094977">"ଷ୍ଟୋରେଜ"</string>
<string name="notification_channel_hints" msgid="7703783206000346876">"ହିଣ୍ଟ"</string>
<string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ଚାଲୁଛି"</string>
@@ -733,8 +740,8 @@
<string name="ongoing_privacy_dialog_attribution_label" msgid="3385241594101496292">"(<xliff:g id="ATTRIBUTION_LABEL">%s</xliff:g>)"</string>
<string name="ongoing_privacy_dialog_attribution_proxy_label" msgid="1111829599659403249">"(<xliff:g id="ATTRIBUTION_LABEL">%1$s</xliff:g> • <xliff:g id="PROXY_LABEL">%2$s</xliff:g>)"</string>
<string name="privacy_type_camera" msgid="7974051382167078332">"କ୍ୟାମେରା"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ଲୋକେସନ୍"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"ମାଇକ୍ରୋଫୋନ୍"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ଲୋକେସନ"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"ମାଇକ୍ରୋଫୋନ"</string>
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ସ୍କ୍ରିନ ରେକର୍ଡିଂ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"କୌଣସି ଶୀର୍ଷକ ନାହିଁ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ଷ୍ଟାଣ୍ଡବାଏ"</string>
@@ -854,7 +861,7 @@
<string name="build_number_copy_toast" msgid="877720921605503046">"କ୍ଲିପବୋର୍ଡକୁ କପି କରାଯାଇଥିବା ବିଲ୍ଡ ନମ୍ୱର।"</string>
<string name="basic_status" msgid="2315371112182658176">"ବାର୍ତ୍ତାଳାପ ଖୋଲନ୍ତୁ"</string>
<string name="select_conversation_title" msgid="6716364118095089519">"ବାର୍ତ୍ତାଳାପ ୱିଜେଟଗୁଡ଼ିକ"</string>
- <string name="select_conversation_text" msgid="3376048251434956013">"ଏକ ବାର୍ତ୍ତାଳାପକୁ ଆପଣଙ୍କ ମୂଳସ୍କ୍ରିନରେ ଯୋଗ କରିବା ପାଇଁ ସେଥିରେ ଟାପ୍ କରନ୍ତୁ"</string>
+ <string name="select_conversation_text" msgid="3376048251434956013">"ଏକ ବାର୍ତ୍ତାଳାପକୁ ଆପଣଙ୍କ ହୋମ ସ୍କ୍ରିନରେ ଯୋଗ କରିବା ପାଇଁ ସେଥିରେ ଟାପ କରନ୍ତୁ"</string>
<string name="no_conversations_text" msgid="5354115541282395015">"ଆପଣଙ୍କ ବର୍ତ୍ତମାନର ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ ଏଠାରେ ଦେଖାଯିବ"</string>
<string name="priority_conversations" msgid="3967482288896653039">"ପ୍ରାଥମିକତା ଦିଆଯାଇଥିବା ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ"</string>
<string name="recent_conversations" msgid="8531874684782574622">"ବର୍ତ୍ତମାନର ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ"</string>
@@ -920,7 +927,7 @@
<string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ଉପଯୋଗକର୍ତ୍ତା ଚୟନ କର"</string>
<string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{#ଟି ଆପ ସକ୍ରିୟ ଅଛି}other{#ଟି ଆପ ସକ୍ରିୟ ଅଛି}}"</string>
<string name="fgs_dot_content_description" msgid="2865071539464777240">"ନୂଆ ସୂଚନା"</string>
- <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"ସକ୍ରିୟ ଆପଗୁଡ଼ିକ"</string>
+ <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"ସକ୍ରିୟ ଆପ୍ସ"</string>
<string name="fgs_manager_dialog_message" msgid="2670045017200730076">"ଆପଣ ଏହି ଆପ୍ସକୁ ବ୍ୟବହାର କରୁନଥିଲେ ମଧ୍ୟ ସେଗୁଡ଼ିକ ସକ୍ରିୟ ରହିଥାଏ ଏବଂ ଚାଲୁଥାଏ। ଏହା ସେଗୁଡ଼ିକର କାର୍ଯ୍ୟକ୍ଷମତାକୁ ଉନ୍ନତ କରେ, କିନ୍ତୁ ଏହା ମଧ୍ୟ ବ୍ୟାଟେରୀ ଲାଇଫକୁ ପ୍ରଭାବିତ କରିପାରେ।"</string>
<string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"ବନ୍ଦ ହୋଇଛି"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index a4b9262..003c548 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ਚਿਹਰਾ ਨਹੀਂ ਪਛਾਣ ਸਕਦੇ। ਇਸਦੀ ਬਜਾਏ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ।"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ਕਨੈਕਟ ਕੀਤੀ।"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ਬੈਟਰੀ ਪ੍ਰਤੀਸ਼ਤ ਅਗਿਆਤ ਹੈ।"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ।"</string>
@@ -284,8 +288,8 @@
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਕੈਮਰੇ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਕੈਮਰੇ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string>
- <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
- <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
+ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ਇਹ ਉਨ੍ਹਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
+ <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ਇਹ ਉਨ੍ਹਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਜਾਂ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
<string name="sensor_privacy_start_use_mic_blocked_dialog_title" msgid="2640140287496469689">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
<string name="sensor_privacy_start_use_camera_blocked_dialog_title" msgid="7398084286822440384">"ਕੈਮਰਾ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ। ਖੋਲ੍ਹਣ ਲਈ ਦਬਾਓ।"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ। ਖੋਲ੍ਹਣ ਲਈ ਦਬਾਓ।"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ। ਖੋਲ੍ਹਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ।"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"ਖੱਬੇ ਲਿਜਾਓ"</item>
<item msgid="5558598599408514296">"ਹੇਠਾਂ ਲਿਜਾਓ"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਡੌਕ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ਵਰਤੋਂਕਾਰ ਸਵਿੱਚ ਕਰੋ"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ਪੁੱਲਡਾਊਨ ਮੀਨੂ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ਇਸ ਸੈਸ਼ਨ ਵਿਚਲੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟਾ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਏਗਾ।"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ਮਹਿਮਾਨ, ਫਿਰ ਤੁਹਾਡਾ ਸੁਆਗਤ ਹੈ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ਕੀ ਤੁਸੀਂ ਆਪਣਾ ਸੈਸ਼ਨ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"ਸੁਰਖੀਆਂ ਓਵਰਲੇ"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ਚਾਲੂ ਕਰੋ"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ਬੰਦ ਕਰੋ"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"ਐਪ ਨੂੰ ਪਿੰਨ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"ਇਹ ਇਸ ਨੂੰ ਤਦ ਤੱਕ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਰੱਖਦਾ ਹੈ ਜਦ ਤੱਕ ਤੁਸੀਂ ਅਨਪਿੰਨ ਨਹੀਂ ਕਰਦੇ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ \'ਪਿੱਛੇ\' ਅਤੇ \'ਰੂਪ-ਰੇਖਾ\' ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਅਨਪਿੰਨ ਕੀਤੇ ਜਾਣ ਤੱਕ ਇਸਨੂੰ ਦਿਖਾਇਆ ਜਾਂਦਾ ਹੈ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ \'ਪਿੱਛੇ\' ਅਤੇ \'ਹੋਮ\' ਨੂੰ ਸਪਰਸ਼ ਕਰਕੇ ਰੱਖੋ।"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 2265018..7082ff8 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nie rozpoznaję twarzy. Użyj odcisku palca."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth połączony."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Poziom naładowania baterii jest nieznany."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Połączono z <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Odblokowano rozpoznawaniem twarzy. Naciśnij, by otworzyć."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Twarz rozpoznana. Naciśnij, by otworzyć."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Twarz rozpoznana. Aby otworzyć, kliknij ikonę odblokowywania."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Odblokowano skanem twarzy"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Twarz rozpoznana"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Przenieś w lewo"</item>
<item msgid="5558598599408514296">"Przenieś w dół"</item>
@@ -337,7 +343,7 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Szybkie ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wolne ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ładowanie na stacji dokującej • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Przełącz użytkownika"</string>
<!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
<skip />
@@ -418,6 +424,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Nakładka z napisami"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"włącz"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"wyłącz"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacja jest przypięta"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, kliknij i przytrzymaj Wstecz oraz Przegląd."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, naciśnij i przytrzymaj Wstecz oraz Ekran główny."</string>
@@ -921,7 +931,7 @@
<string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# aplikacja jest aktywna}few{# aplikacje są aktywne}many{# aplikacji jest aktywnych}other{# aplikacji jest aktywne}}"</string>
<string name="fgs_dot_content_description" msgid="2865071539464777240">"Nowa informacja"</string>
<string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Aktywne aplikacje"</string>
- <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Te aplikacje są aktywne i działają, nawet gdy ich nie używasz. Zwiększa to ich funkcjonalność, ale może również pogarszać żywotność baterii."</string>
+ <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Te aplikacje są aktywne i działają, nawet gdy ich nie używasz. Zwiększa to ich funkcjonalność, ale może też wpływać na czas pracy na baterii."</string>
<string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"Zatrzymaj"</string>
<string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"Zatrzymano"</string>
<string name="clipboard_edit_text_done" msgid="4551887727694022409">"Gotowe"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 395b1f7..9a8ff66 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Não foi possível reconhecer o rosto Use a impressão digital."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentagem da bateria desconhecida."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Desbloqueado pelo rosto. Pressione para abrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Rosto reconhecido. Pressione para abrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rosto reconhecido. Pressione o ícone de desbloq. para abrir."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Desbloqueado pelo rosto"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Rosto reconhecido"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Mais para a esquerda"</item>
<item msgid="5558598599408514296">"Mais para baixo"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando na base • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Trocar usuário"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu suspenso"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Você voltou, visitante!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Quer continuar a sessão?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Sobreposição de legendas"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ativar"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desativar"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Som e vibração"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configurações"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"O app está fixado"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Visão geral e mantenha essas opções pressionadas para liberar."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Início e mantenha essas opções pressionadas para liberar."</string>
@@ -500,7 +507,7 @@
<string name="notification_automatic_title" msgid="3745465364578762652">"Automática"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Som e vibração desativados"</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"O som e a vibração estão desativados, e o balão aparece na parte inferior da seção de conversa"</string>
- <string name="notification_channel_summary_default" msgid="3282930979307248890">"Podem vibrar ou tocar com base nas configurações do smartphone"</string>
+ <string name="notification_channel_summary_default" msgid="3282930979307248890">"Pode vibrar ou tocar com base nas configurações do smartphone"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode vibrar ou tocar com base nas configurações do smartphone. As conversas do app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem em balões por padrão."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se a notificação resultará em som ou vibração"</string>
<string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"<b>Status:</b> promovida a Padrão"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index a8ace85..c2436e1 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Impos. reconh. rosto. Utilize a impressão digital."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ligado."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percentagem da bateria desconhecida."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ligado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -281,8 +285,8 @@
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Parar"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo para uma mão"</string>
- <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Pretende desbloquear o microfone do dispositivo?"</string>
- <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Pretende desbloquear a câmara do dispositivo?"</string>
+ <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string>
+ <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmara do dispositivo?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Pretende desbloquear a câmara e o microfone?"</string>
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Isto desbloqueia o acesso a todas as apps e serviços com autorização para utilizar o seu microfone."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Isto desbloqueia o acesso a todas as apps e serviços com autorização para utilizar a sua câmara."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Desbloqueado com o rosto. Prima para abrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Rosto reconhecido. Prima para abrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rosto reconhecido. Prima o ícone de desbloqueio para abrir."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Desbloqueado com o rosto"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Rosto reconhecido"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Mover para a esquerda"</item>
<item msgid="5558598599408514296">"Mover para baixo"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar rapidamente • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar lentamente • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar na estação de ancoragem • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Mudar utilizador"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pendente"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todas as apps e dados desta sessão serão eliminados."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Bem-vindo de volta, convidado!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Pretende continuar a sessão?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Sobreposição de legendas"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ativar"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desativar"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Som e vibração"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Definições"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"A app está fixada"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Esta opção mantém o item visível até o soltar. Toque sem soltar em Anterior e em Vista geral para soltar."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Esta opção mantém o item visível até o soltar. Toque sem soltar em Anterior e em Página inicial para soltar."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 395b1f7..9a8ff66 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Não foi possível reconhecer o rosto Use a impressão digital."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentagem da bateria desconhecida."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Desbloqueado pelo rosto. Pressione para abrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Rosto reconhecido. Pressione para abrir."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rosto reconhecido. Pressione o ícone de desbloq. para abrir."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Desbloqueado pelo rosto"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Rosto reconhecido"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Mais para a esquerda"</item>
<item msgid="5558598599408514296">"Mais para baixo"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando na base • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Trocar usuário"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu suspenso"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Você voltou, visitante!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Quer continuar a sessão?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Sobreposição de legendas"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ativar"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desativar"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Som e vibração"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configurações"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"O app está fixado"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Visão geral e mantenha essas opções pressionadas para liberar."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Início e mantenha essas opções pressionadas para liberar."</string>
@@ -500,7 +507,7 @@
<string name="notification_automatic_title" msgid="3745465364578762652">"Automática"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Som e vibração desativados"</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"O som e a vibração estão desativados, e o balão aparece na parte inferior da seção de conversa"</string>
- <string name="notification_channel_summary_default" msgid="3282930979307248890">"Podem vibrar ou tocar com base nas configurações do smartphone"</string>
+ <string name="notification_channel_summary_default" msgid="3282930979307248890">"Pode vibrar ou tocar com base nas configurações do smartphone"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode vibrar ou tocar com base nas configurações do smartphone. As conversas do app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem em balões por padrão."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se a notificação resultará em som ou vibração"</string>
<string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"<b>Status:</b> promovida a Padrão"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 451ff5b..f62ff13 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Chipul nu a fost recunoscut. Folosiți amprenta."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Conectat prin Bluetooth."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procentajul bateriei este necunoscut."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectat la <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"S-a deblocat cu ajutorul feței. Apăsați pentru a deschide."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Chipul a fost recunoscut. Apăsați pentru a deschide."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Chip recunoscut. Apăsați pictograma de deblocare pentru a deschide"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"S-a deblocat folosind fața"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Chipul a fost recunoscut"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Deplasați spre stânga"</item>
<item msgid="5558598599408514296">"Deplasați în jos"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă rapid • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă lent • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Suport de încărcare • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Comutați între utilizatori"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"meniu vertical"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toate aplicațiile și datele din această sesiune vor fi șterse."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Bine ați revenit în sesiunea pentru invitați!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vreți să continuați sesiunea?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Suprapunere pe subtitrări"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"activați"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"dezactivați"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Sunete și vibrații"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Setări"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Aplicația este fixată"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Astfel rămâne afișat până anulați fixarea. Atingeți lung opțiunile Înapoi și Recente pentru a anula fixarea."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Astfel rămâne afișat până anulați fixarea. Atingeți lung opțiunile Înapoi și Acasă pentru a anula fixarea."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index ecaf8d4..6a8ee31 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Не удалось распознать лицо. Используйте отпечаток."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-соединение установлено."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Уровень заряда батареи в процентах неизвестен."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>: подключено."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Разблокировано сканированием лица. Нажмите, чтобы открыть."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Лицо распознано. Нажмите, чтобы открыть."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лицо распознано. Нажмите на значок разблокировки."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Разблокировано сканированием лица"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Лицо распознано"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Переместите палец влево"</item>
<item msgid="5558598599408514296">"Переместите палец вниз"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Быстрая зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Медленная зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядка от док-станции • Ещё <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Сменить пользователя."</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"раскрывающееся меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Все приложения и данные этого профиля будут удалены."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Рады видеть вас снова!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Продолжить сеанс?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Наложение субтитров"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"включить"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"отключить"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Приложение закреплено"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Приложение останется активным, пока вы не отмените блокировку, нажав и удерживая кнопки \"Назад\" и \"Обзор\"."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Приложение останется активным, пока вы не отмените блокировку, нажав и удерживая кнопки \"Назад\" и \"Главный экран\"."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 9bc1000..bbf1619 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"මුහුණ හැඳිනිය නොහැක. ඒ වෙනුවට ඇඟිලි සලකුණ භාවිත ක."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"බ්ලූටූත් සම්බන්ධිතයි."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"බැටරි ප්රතිශතය නොදනී."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> වෙත සම්බන්ධ කරන ලදි."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"මුහුණ මගින් අගුලු හරින ලදි. විවෘත කිරීමට ඔබන්න."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"මුහුණ හඳුනා ගන්නා ලදි. විවෘත කිරීමට ඔබන්න."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"මුහුණ හඳුනා ගන්නා ලදි. විවෘත කිරීමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"මුහුණ මගින් අගුලු හරින ලදි"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"මුහුණ හඳුනා ගන්නා ලදි"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"වමට ගෙන යන්න"</item>
<item msgid="5558598599408514296">"පහළට ගෙන යන්න"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • සෙමින් ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ආරෝපණ ඩොකය • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"පරිශීලක මාරුව"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"නිපතන මෙනුව"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"මෙම සැසියේ සියළුම යෙදුම් සහ දත්ත මකාවී."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"නැවත සාදරයෙන් පිළිගනිමු, අමුත්තා!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ඔබගේ සැසිය දිගටම කරගෙන යෑමට ඔබට අවශ්යද?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"සිරස්තල උඩැතිරිය"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"සබල කරන්න"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"අබල කරන්න"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"යෙදුම අමුණා ඇත"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට දළ විශ්ලේෂණය ස්පර්ශ කර ආපසු අල්ලාගෙන සිටින්න."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට මුල් පිටුව ස්පර්ශ කර අල්ලාගෙන සිටින්න."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 7fdfcc8..9688091 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tvár sa nedá rozpoznať. Použite odtlačok prsta."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth pripojené."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percento batérie nie je známe."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Pripojené k zariadeniu <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -282,11 +286,11 @@
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ukončiť"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Režim jednej ruky"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Chcete odblokovať mikrofón zariadenia?"</string>
- <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Chcete odblokovať fotoaparát zariadenia?"</string>
+ <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Chcete odblokovať kameru zariadenia?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Chcete odblokovať fotoaparát a mikrofón zariadenia?"</string>
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať mikrofón."</string>
- <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať fotoaparát."</string>
- <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať fotoaparát alebo mikrofón."</string>
+ <string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať kameru."</string>
+ <string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať kameru alebo mikrofón."</string>
<string name="sensor_privacy_start_use_mic_blocked_dialog_title" msgid="2640140287496469689">"Mikrofón je blokovaný"</string>
<string name="sensor_privacy_start_use_camera_blocked_dialog_title" msgid="7398084286822440384">"Kamera je blokovaná"</string>
<string name="sensor_privacy_start_use_mic_camera_blocked_dialog_title" msgid="195236134743281973">"Mikrofón a kamera sú blokované"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Odomknuté tvárou. Otvorte stlačením."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Tvár bola rozpoznaná. Otvorte stlačením."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Tvár bola rozpoznaná. Otvorte stlačením ikony odomknutia."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Odomknuté tvárou"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Tvár bola rozpoznaná"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Posunúť doľava"</item>
<item msgid="5558598599408514296">"Posunúť nadol"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa rýchlo • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa pomaly • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíjací dok • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Prepnutie používateľa"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rozbaľovacia ponuka"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Všetky aplikácie a údaje v tejto relácii budú odstránené."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Hosť, vitajte späť!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Chcete v relácii pokračovať?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Prekrytie titulkov"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"povoliť"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"zakázať"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Zvuk a vibrácie"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Nastavenia"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Aplikácia je pripnutá"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Obsah bude pripnutý v zobrazení, dokým ho neuvoľníte. Uvoľníte ho stlačením a podržaním tlačidiel Späť a Prehľad."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Obsah bude pripnutý v zobrazení, dokým ho neuvoľníte. Uvoľníte ho pridržaním tlačidiel Späť a Domov."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 8752f8e..f9ab048 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Obraza ni mogoče prepoznati. Uporabite prstni odtis."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Povezava Bluetooth vzpostavljena."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Neznan odstotek napolnjenosti baterije."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Povezava vzpostavljena z: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Odklenjeno z obrazom. Pritisnite za odpiranje."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Obraz je prepoznan. Pritisnite za odpiranje."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Obraz je prepoznan. Za odpiranje pritisnite ikono za odklepanje."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Odklenjeno z obrazom"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Obraz je prepoznan"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Premik levo"</item>
<item msgid="5558598599408514296">"Premik navzdol"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hitro polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Počasno polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Polnjenje na nosilcu • Polno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Preklop med uporabniki"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"spustni meni"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Vse aplikacije in podatki v tej seji bodo izbrisani."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Znova pozdravljeni, gost!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite nadaljevati sejo?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Prekrivni podnapisi"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"omogoči"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"onemogoči"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Zvok in vibriranje"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Nastavitve"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacija je pripeta"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"S tem ostane vidna, dokler je ne odpnete. Če jo želite odpeti, hkrati pridržite gumba za nazaj in pregled."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"S tem ostane vidna, dokler je ne odpnete. Če jo želite odpeti, hkrati pridržite gumba za nazaj in za začetni zaslon."</string>
@@ -833,7 +840,7 @@
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Izbranih je toliko naprav: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
<string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(povezava je prekinjena)"</string>
<string name="media_output_dialog_connect_failed" msgid="3080972621975339387">"Preklop ni mogoč. Če želite poskusiti znova, se dotaknite."</string>
- <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"Povezovanje naprave"</string>
+ <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"Povežite napravo"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Če želite predvajati to sejo, odprite aplikacijo."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Neznana aplikacija"</string>
<string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Ustavi predvajanje"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index b1d07a4..c8a0f24 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nuk mund ta dallojë fytyrën. Përdor më mirë gjurmën e gishtit."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Pajisja është lidhur me \"bluetooth\"."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Përqindja e baterisë e panjohur."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Lidhur me <xliff:g id="BLUETOOTH">%s</xliff:g>"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"U shkyç me fytyrë. Shtyp për ta hapur."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Fytyra u njoh. Shtyp për ta hapur."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Fytyra u njoh. Shtyp ikonën e shkyçjes për ta hapur."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"U shkyç me fytyrë"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Fytyra u njoh"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Lëvize majtas"</item>
<item msgid="5558598599408514296">"Lëvize poshtë"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet shpejt • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet ngadalë • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet në stacion • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Ndërro përdorues"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menyja me tërheqje poshtë"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Të gjitha aplikacionet dhe të dhënat në këtë sesion do të fshihen."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Mirë se erdhe, i ftuar!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Dëshiron ta vazhdosh sesionin tënd?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Mbivendosja e titrave"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktivizo"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"çaktivizo"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacioni është i gozhduar"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Prapa\" dhe \"Përmbledhje\" për ta hequr nga gozhdimi."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Prapa\" dhe \"Kreu\" për ta hequr nga gozhdimi."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 8b2e5a4..80f4d20 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Лице није препознато. Користите отисак прста."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth је прикључен."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Проценат напуњености батерије није познат."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Повезани сте са <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Откључано је лицем. Притисните да бисте отворили."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Лице је препознато. Притисните да бисте отворили."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лице препознато. Притисните икону откључавања да бисте отворили."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Откључано је лицем"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Лице је препознато"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Померите налево"</item>
<item msgid="5558598599408514296">"Померите надоле"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Пуни се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Брзо се пуни • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Споро се пуни • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Базна станица за пуњење • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Пуни се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Замени корисника"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"падајући мени"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Све апликације и подаци у овој сесији ће бити избрисани."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Добро дошли назад, госте!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Желите ли да наставите сесију?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Преклапање титлова"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"омогућите"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"онемогућите"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Апликација је закачена"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"На овај начин се ово стално приказује док га не откачите. Додирните и задржите Назад и Преглед да бисте га откачили."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"На овај начин се ово стално приказује док га не откачите. Додирните и задржите Назад и Почетна да бисте га откачили."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 7994324..912fbf7 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansiktet kändes inte igen. Använd fingeravtryck."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ansluten."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Okänd batterinivå."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ansluten till <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Upplåst med ansiktslås. Tryck för att öppna."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Ansiktet har identifierats. Tryck för att öppna."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ansiktet har identifierats. Tryck på ikonen lås upp."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Upplåst med ansiktslås"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ansiktet har identifierats"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Flytta åt vänster"</item>
<item msgid="5558598599408514296">"Flytta nedåt"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas snabbt • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas långsamt • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Dockningsstation • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Byt användare"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullgardinsmeny"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alla appar och data i denna session kommer att raderas."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Välkommen tillbaka som gäst!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vill du fortsätta sessionen?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Överlagring av textning"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktivera"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"inaktivera"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Ljud och vibration"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Inställningar"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Appen har fästs"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Skärmen visas tills du lossar den. Tryck länge på Tillbaka och Översikt om du vill lossa skärmen."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Skärmen visas tills du lossar den. Tryck länge på Tillbaka och Startsida om du vill lossa skärmen."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 0e6694d3..9b7de62 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Imeshindwa kutambua uso. Tumia alama ya kidole."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth imeunganishwa."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Asilimia ya betri haijulikani."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Imeunganishwa kwenye <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Imefunguliwa kwa kutumia uso wako. Bonyeza ili ufungue."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Uso umetambuliwa. Bonyeza ili ufungue."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Uso umetambuliwa. Bonyeza aikoni ya kufungua ili ufungue."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Imefunguliwa kwa kutumia uso"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Uso umetambuliwa"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Sogeza kushoto"</item>
<item msgid="5558598599408514296">"Sogeza chini"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji kwa kasi • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji polepole • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kituo cha Kuchaji • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Badili mtumiaji"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menyu ya kuvuta chini"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Data na programu zote katika kipindi hiki zitafutwa."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Karibu tena mgeni!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Je, unataka kuendelea na kipindi chako?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Kuwekelea manukuu"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"washa"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"zima"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Sauti na mtetemo"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Mipangilio"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Programu imebandikwa"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Hali hii huifanya ionekane hadi utakapoibandua. Gusa na ushikilie kipengele cha Nyuma na Muhtasari ili ubandue."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Hali hii huifanya ionekane hadi utakapoibandua. Gusa na ushikilie kitufe cha kurudisha Nyuma na cha Mwanzo kwa pamoja ili ubandue."</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 085832f..496acca 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"முகத்தை அடையாளம் காண முடியவில்லை. கைரேகையைப் பயன்படுத்தவும்."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"புளூடூத் இணைக்கப்பட்டது."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"பேட்டரி சதவீதம் தெரியவில்லை."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>க்கு இணைக்கப்பட்டது."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"முகம் மூலம் அன்லாக் செய்யப்பட்டது. திறக்க அழுத்தவும்."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"முகம் அங்கீகரிக்கப்பட்டது. திறக்க அழுத்தவும்."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"முகம் அங்கீகரிக்கப்பட்டது. திறக்க அன்லாக் ஐகானை அழுத்தவும்."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"முகத்தால் அன்லாக் செய்யப்பட்டது"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"முகம் அங்கீகரிக்கப்பட்டது"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"இடதுபுறம் நகர்த்துங்கள்"</item>
<item msgid="5558598599408514296">"கீழே நகர்த்துங்கள்"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • வேகமாகச் சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • மெதுவாக சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • டாக் மூலம் சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுமையாகச் சார்ஜாகிவிடும்"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுவதும் சார்ஜாகும்"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"பயனரை மாற்று"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"கீழ் இழுக்கும் மெனு"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"இந்த அமர்வின் எல்லா ஆப்ஸும் தரவும் நீக்கப்படும்."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"நல்வரவு!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"உங்கள் அமர்வைத் தொடர விருப்பமா?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"மேலடுக்கப்பட்ட வசனங்கள்"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"இயக்கும்"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"முடக்கும்"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"ஒலி & அதிர்வு"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"அமைப்புகள்"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"ஆப்ஸ் பின் செய்யப்பட்டது"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"பொருத்தியதை அகற்றும் வரை இதைக் காட்சியில் வைக்கும். அகற்ற, முந்தையது மற்றும் மேலோட்டப் பார்வையைத் தொட்டுப் பிடிக்கவும்."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"இதற்கான பின்னை அகற்றும் வரை, இந்தப் பயன்முறை செயல்பாட்டிலேயே இருக்கும். அகற்றுவதற்கு, முந்தையது மற்றும் முகப்பு பட்டன்களைத் தொட்டுப் பிடிக்கவும்."</string>
@@ -921,7 +928,7 @@
<string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# ஆப்ஸ் செயலிலுள்ளது}other{# ஆப்ஸ் செயலிலுள்ளன}}"</string>
<string name="fgs_dot_content_description" msgid="2865071539464777240">"புதிய தகவல்கள்"</string>
<string name="fgs_manager_dialog_title" msgid="5879184257257718677">"செயலிலுள்ள ஆப்ஸ்"</string>
- <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"இந்த ஆப்ஸை நீங்கள் பயன்படுத்தாதபோதும் அவை செயலில் இருப்பதோடு இயங்கிக் கொண்டிருக்கும். இது அவற்றின் செயல்பாட்டை மேம்படுத்தும். ஆனால், அதே சமயம் பேட்டரி ஆயுளைக் குறைக்கக்கூடும்."</string>
+ <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"இந்த ஆப்ஸை நீங்கள் பயன்படுத்தாதபோதும் அவை செயலில் இருப்பதோடு இயங்கிக் கொண்டிருக்கும். இது அவற்றின் செயல்பாட்டை மேம்படுத்தும். ஆனால், அதே சமயம் பேட்டரி அளவைக் குறைக்கக்கூடும்."</string>
<string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"நிறுத்து"</string>
<string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"இயங்கவில்லை"</string>
<string name="clipboard_edit_text_done" msgid="4551887727694022409">"முடிந்தது"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 96c09cb..27a9fa3 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ముఖం గుర్తించలేము. బదులుగా వేలిముద్ర ఉపయోగించండి."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"బ్లూటూత్ కనెక్ట్ చేయబడింది."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"బ్యాటరీ శాతం తెలియదు."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>కి కనెక్ట్ చేయబడింది."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"ముఖం ద్వారా అన్లాక్ చేయబడింది. తెరవడానికి నొక్కండి."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"ముఖం గుర్తించబడింది. తెరవడానికి నొక్కండి."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ముఖం గుర్తించబడింది. తెరవడానికి అన్లాక్ చిహ్నం నొక్కండి."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ముఖం ద్వారా అన్లాక్ చేయబడింది"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ముఖం గుర్తించబడింది"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"ఎడమవైపుగా జరపండి"</item>
<item msgid="5558598599408514296">"కిందికి జరపండి"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తి ఛార్జ్"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తి ఛార్జ్"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ఛార్జింగ్ డాక్ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"వినియోగదారుని మార్చు"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"పుల్డౌన్ మెనూ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ఈ సెషన్లోని అన్ని యాప్లు మరియు డేటా తొలగించబడతాయి."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"గెస్ట్కు తిరిగి స్వాగతం!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"మీరు మీ సెషన్ని కొనసాగించాలనుకుంటున్నారా?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"క్యాప్షన్లు ఓవర్లే"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ప్రారంభించు"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"నిలిపివేయండి"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"సౌండ్ & వైబ్రేషన్"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"సెట్టింగ్లు"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"యాప్ పిన్ చేయబడి ఉంది"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"దీని వలన మీరు అన్పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్పిన్ చేయడానికి వెనుకకు మరియు స్థూలదృష్టి తాకి & అలాగే పట్టుకోండి."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"దీని వలన మీరు అన్పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్పిన్ చేయడానికి వెనుకకు మరియు హోమ్ని తాకి & అలాగే పట్టుకోండి."</string>
@@ -556,7 +563,7 @@
<string name="keyboard_key_media_next" msgid="8502476691227914952">"తర్వాత"</string>
<string name="keyboard_key_media_previous" msgid="5637875709190955351">"మునుపటి"</string>
<string name="keyboard_key_media_rewind" msgid="3450387734224327577">"రివైండ్ చేయి"</string>
- <string name="keyboard_key_media_fast_forward" msgid="3572444327046911822">"వేగంగా ఫార్వార్డ్ చేయి"</string>
+ <string name="keyboard_key_media_fast_forward" msgid="3572444327046911822">"వేగంగా ఫార్వర్డ్ చేయి"</string>
<string name="keyboard_key_page_up" msgid="173914303254199845">"Page Up"</string>
<string name="keyboard_key_page_down" msgid="9035902490071829731">"Page Down"</string>
<string name="keyboard_key_forward_del" msgid="5325501825762733459">"Delete"</string>
@@ -619,7 +626,7 @@
<string name="left_icon" msgid="5036278531966897006">"ఎడమ వైపు చిహ్నం"</string>
<string name="right_icon" msgid="1103955040645237425">"కుడివైపు ఉన్న చిహ్నం"</string>
<string name="drag_to_add_tiles" msgid="8933270127508303672">"టైల్స్ను జోడించడానికి పట్టుకుని, లాగండి"</string>
- <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"టైల్ల క్రమం మార్చడానికి వాటిని పట్టుకుని, లాగండి"</string>
+ <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"టైల్స్ను వేరే క్రమంలో అమర్చడానికి వాటిని పట్టుకుని, లాగండి"</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"తీసివేయడానికి ఇక్కడికి లాగండి"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"మీ వద్ద కనీసం <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> టైల్లు ఉండాలి"</string>
<string name="qs_edit" msgid="5583565172803472437">"ఎడిట్ చేయండి"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index c00c09a..2575939 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ไม่รู้จักใบหน้า ใช้ลายนิ้วมือแทน"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"เชื่อมต่อบลูทูธแล้ว"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ไม่ทราบเปอร์เซ็นต์แบตเตอรี่"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"เชื่อมต่อกับ <xliff:g id="BLUETOOTH">%s</xliff:g> แล้ว"</string>
@@ -241,7 +245,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ความสว่าง"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"การกลับสี"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"การแก้สี"</string>
- <string name="quick_settings_more_user_settings" msgid="1064187451100861954">"การตั้งค่าของผู้ใช้"</string>
+ <string name="quick_settings_more_user_settings" msgid="1064187451100861954">"การตั้งค่าผู้ใช้"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"เสร็จสิ้น"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ปิด"</string>
<string name="quick_settings_connected" msgid="3873605509184830379">"เชื่อมต่อ"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"ปลดล็อกด้วยใบหน้าแล้ว กดเพื่อเปิด"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"จดจำใบหน้าได้ กดเพื่อเปิด"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"จดจำใบหน้าได้ กดไอคอนปลดล็อกเพื่อเปิด"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ปลดล็อกด้วยใบหน้าแล้ว"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"จดจำใบหน้าได้"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"เลื่อนนิ้วไปทางซ้าย"</item>
<item msgid="5558598599408514296">"เลื่อนนิ้วลง"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างเร็ว • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างช้าๆ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จบนแท่นชาร์จ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"สลับผู้ใช้"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"เมนูแบบเลื่อนลง"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ระบบจะลบแอปและข้อมูลทั้งหมดในเซสชันนี้"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ยินดีต้อนรับผู้ใช้ชั่วคราวกลับมาอีกครั้ง"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"คุณต้องการอยู่ในเซสชันต่อไปไหม"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"การวางซ้อนคำบรรยายภาพ"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"เปิดใช้"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ปิดใช้"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"เสียงและการสั่น"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"การตั้งค่า"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"ปักหมุดแอปอยู่"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกปักหมุด แตะ \"กลับ\" และ \"ภาพรวม\" ค้างไว้เพื่อเลิกปักหมุด"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกปักหมุด แตะ \"กลับ\" และ \"หน้าแรก\" ค้างไว้เพื่อเลิกปักหมุด"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 9d1bc41..a45c673 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Hindi makilala ang mukha. Gumamit ng fingerprint."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Nakakonekta ang Bluetooth."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Hindi alam ang porsyento ng baterya."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Nakakonekta sa <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Na-unlock gamit ang mukha. Pindutin para buksan."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Nakilala ang mukha. Pindutin para buksan."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Nakilala ang mukha. Pindutin ang icon ng unlock para buksan."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Na-unlock gamit ang mukha"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Nakilala ang mukha"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Ilipat pakaliwa"</item>
<item msgid="5558598599408514296">"Ibaba"</item>
@@ -337,7 +343,7 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabilis na nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabagal na nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging Dock • Mapupuno sa loob ng <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Magpalit ng user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ide-delete ang lahat ng app at data sa session na ito."</string>
@@ -417,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Overlay ng mga caption"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"i-enable"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"i-disable"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Naka-pin ang app"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Pinapanatili nitong nakikita ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Bumalik at Overview upang mag-unpin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Pinapanatili nitong nakikita ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Bumalik at Home upang mag-unpin."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index a18c425..6d9d0f2 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Yüz tanınamadı. Bunun yerine parmak izi kullanın."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth bağlandı."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pil yüzdesi bilinmiyor."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ile bağlı."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Cihazın kilidini yüzünüzle açtınız. Açmak için basın."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Yüzünüz tanındı. Açmak için basın."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Yüzünüz tanındı. Kilit açma simgesine basın."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Cihazın kilidini yüzünüzle açtınız"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Yüzünüz tanındı"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Sola taşı"</item>
<item msgid="5558598599408514296">"Aşağı taşı"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hızlı şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Yavaş şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Yuvada Şarj Oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kullanıcı değiştirme"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"açılır menü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu oturumdaki tüm uygulamalar ve veriler silinecek."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Misafir kullanıcı, tekrar hoşgeldiniz"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Oturumunuza devam etmek istiyor musunuz?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Altyazı yer paylaşımı"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"etkinleştir"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"devre dışı bırak"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Uygulama sabitlendi"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Bu işlem, siz sabitlemeyi kaldırana kadar ekranı görünür durumda tutar. Sabitlemeyi kaldırmak için Geri\'ye ve Genel Bakış\'a dokunup basılı tutun."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Bu işlem, siz sabitlemeyi kaldırana kadar ekranı görünür durumda tutar. Sabitlemeyi kaldırmak için Geri\'ye ve Ana sayfaya dokunup basılı tutun."</string>
@@ -574,7 +583,7 @@
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Klavye Kısayolları"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klavye düzenini değiştir"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Uygulamalar"</string>
- <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Asist"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Asistan"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Tarayıcı"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kişiler"</string>
<string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-posta"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index c8e667b..6e796b4 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Обличчя не розпізнано. Скористайтеся відбитком пальця."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth під’єднано."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Відсоток заряду акумулятора невідомий."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Підключено до <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Розблоковано (фейсконтроль). Натисніть, щоб відкрити."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Обличчя розпізнано. Натисніть, щоб відкрити."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Обличчя розпізнано. Натисніть значок розблокування."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Розблоковано (фейсконтроль)"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Обличчя розпізнано"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Перемістіть палець ліворуч"</item>
<item msgid="5558598599408514296">"Перемістіть палець униз"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Швидке заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Повільне заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Док-станція для заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Змінити користувача"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"спадне меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усі додатки й дані з цього сеансу буде видалено."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"З поверненням!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Продовжити сеанс?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Накласти субтитри"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"увімкнути"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"вимкнути"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"Додаток закріплено"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Ви постійно бачитимете екран, доки не відкріпите його. Щоб відкріпити екран, натисніть і втримуйте кнопки \"Назад\" та \"Огляд\"."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ви бачитимете цей екран, доки не відкріпите його. Для цього натисніть і утримуйте кнопки \"Назад\" та \"Головний екран\"."</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 1a2c123..c722f69 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"چہرے کی شناخت نہیں ہو سکی۔ اس کے بجائے فنگر پرنٹ استعمال کریں۔"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"بلوٹوتھ مربوط ہے۔"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"بیٹری کی فیصد نامعلوم ہے۔"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> سے منسلک ہیں۔"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"چہرے سے انلاک کیا گیا۔ کھولنے کے لیے دبائیں۔"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"چہرے کی شناخت ہو گئی۔ کھولنے کے لیے دبائیں۔"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"چہرے کی شناخت ہو گئی۔ کھولنے کیلئے انلاک آئیکن دبائیں۔"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"چہرے سے غیر مقفل کیا گیا"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"چہرے کی شناخت ہو گئی"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"دائیں منتقل کریں"</item>
<item msgid="5558598599408514296">"نیچے منتقل کریں"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • تیزی سے چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • آہستہ چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ڈاک چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"صارف سوئچ کریں"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"پل ڈاؤن مینو"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"اس سیشن میں موجود سبھی ایپس اور ڈیٹا کو حذف کر دیا جائے گا۔"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"مہمان، پھر سے خوش آمدید!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"کیا آپ اپنا سیشن جاری رکھنا چاہتے ہیں؟"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"کیپشنز کا اوورلے"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"فعال کریں"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"غیر فعال کریں"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"ایپ کو پن کر دیا گیا ہے"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"اس سے یہ اس وقت تک منظر میں رہتی ہے جب تک آپ اس سے پن ہٹا نہیں دیتے۔ پن ہٹانے کیلئے پیچھے اور مجموعی جائزہ کے بٹنز کو ٹچ کریں اور دبائے رکھیں۔"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"اس سے یہ اس وقت تک منظر میں رہتی ہے جب تک آپ اس سے پن نہیں ہٹا دیتے۔ پن ہٹانے کیلئے \"پیچھے\" اور \"ہوم\" بٹنز کو ٹچ کریں اور دبائے رکھیں۔"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index c84394a..19f9a66 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Bu yuz notanish. Barmoq izi orqali urining."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ulandi."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batareya quvvati foizi nomaʼlum."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ulangan: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Yuz orqali ochildi. Ochish uchun bosing."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Yuz aniqlandi. Ochish uchun bosing."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Yuz aniqlandi. Ochish uchun ochish belgisini bosing."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Yuz bilan ochildi"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Yuz aniqlandi"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Chapga siljitish"</item>
<item msgid="5558598599408514296">"Pastga siljitish"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Tez quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sekin quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Dok-stansiya • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Foydalanuvchini almashtirish"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"tortib tushiriladigan menyu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ushbu seansdagi barcha ilovalar va ma’lumotlar o‘chirib tashlanadi."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Xush kelibsiz, mehmon!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Seansni davom ettirmoqchimisiz?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Taglavhalarni chiqarish"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"faollashtirish"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"faolsizlantirish"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Tovush va tebranish"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Sozlamalar"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Ilova mahkamlandi"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Ekran yechilmaguncha u o‘zgarmas holatda qoladi. Uni yechish uchun “Orqaga” va “Umumiy ma’lumot” tugmalarini bosib turing."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ekran yechib olinmagunicha u mahkamlangan holatda qoladi. Uni yechish uchun Orqaga va Asosiy tugmalarni birga bosib turing."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index ce82c96..288831e 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Không thể nhận dạng khuôn mặt. Hãy dùng vân tay."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Đã kết nối bluetooth."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Tỷ lệ phần trăm pin không xác định."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Đã kết nối với <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Đã mở khoá bằng khuôn mặt. Nhấn để mở."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Đã nhận diện khuôn mặt. Nhấn để mở."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Đã nhận diện khuôn mặt. Nhấn biểu tượng mở khoá để mở."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Đã mở khoá bằng khuôn mặt."</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Đã nhận diện khuôn mặt."</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Di chuyển sang trái"</item>
<item msgid="5558598599408514296">"Di chuyển xuống"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc nhanh • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc chậm • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đế sạc • Sạc đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Chuyển đổi người dùng"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"trình đơn kéo xuống"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tất cả ứng dụng và dữ liệu trong phiên này sẽ bị xóa."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Chào mừng bạn trở lại!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Bạn có muốn tiếp tục phiên của mình không?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Lớp phủ phụ đề"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"bật"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"tắt"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Âm thanh và chế độ rung"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Cài đặt"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"Đã ghim ứng dụng"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Ứng dụng này sẽ ở cố định trên màn hình cho đến khi bạn bỏ ghim. Hãy chạm và giữ Quay lại và Tổng quan để bỏ ghim."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ứng dụng này sẽ ở cố định trên màn hình cho đến khi bạn bỏ ghim. Hãy chạm và giữ nút Quay lại và nút Màn hình chính để bỏ ghim."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index bedd76b..27fb0bd 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -22,7 +22,7 @@
<string name="app_label" msgid="4811759950673118541">"系统界面"</string>
<string name="battery_low_title" msgid="5319680173344341779">"要开启省电模式吗?"</string>
<string name="battery_low_description" msgid="3282977755476423966">"您的电池还剩 <xliff:g id="PERCENTAGE">%s</xliff:g> 的电量。省电模式会开启深色主题、限制后台活动,并将通知延迟。"</string>
- <string name="battery_low_intro" msgid="5148725009653088790">"省电模式会开启深色主题、限制后台活动,并将通知延迟。"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"省电模式会开启深色主题、限制后台活动,并延迟通知发送时间。"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"无法通过 USB 充电"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"使用设备随附的充电器"</string>
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"无法识别人脸。请改用指纹。"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"蓝牙已连接。"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"电池电量百分比未知。"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"已连接到<xliff:g id="BLUETOOTH">%s</xliff:g>。"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"已通过面孔识别解锁。点按即可打开。"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"识别出面孔。点按即可打开。"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"识别出面孔。按下解锁图标即可打开。"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"已用面孔解锁"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"已识别出面孔"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"左移"</item>
<item msgid="5558598599408514296">"下移"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在快速充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在慢速充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在基座上充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切换用户"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉菜单"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"此会话中的所有应用和数据都将被删除。"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"访客,欢迎回来!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"要继续您的会话吗?"</string>
@@ -418,6 +423,10 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"字幕重叠显示"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"启用"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"停用"</string>
+ <!-- no translation found for sound_settings (8874581353127418308) -->
+ <skip />
+ <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) -->
+ <skip />
<string name="screen_pinning_title" msgid="9058007390337841305">"应用已固定"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"这将会固定显示此屏幕,直到您取消固定为止。触摸并按住“返回”和“概览”即可取消固定屏幕。"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"这将会固定显示此屏幕,直到您取消固定为止。触摸并按住“返回”和“主屏幕”即可取消固定屏幕。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 7f4e659..2415505 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"無法辨識面孔,請改用指紋完成驗證。"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"藍牙連線已建立。"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"電量百分比不明。"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"已連線至<xliff:g id="BLUETOOTH">%s</xliff:g>。"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"已使用面孔解鎖。按下即可開啟。"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"已識別面孔。按下即可開啟。"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"已識別面孔。按解鎖圖示即可開啟。"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"已使用面孔解鎖"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"已識別面孔"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"向左移"</item>
<item msgid="5558598599408514296">"向下移"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 快速充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在插座上充電 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉式選單"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會被刪除。"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"訪客您好,歡迎回來!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"您要繼續您的工作階段嗎?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"字幕重疊"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"啟用"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"停用"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"音效與震動"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"設定"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"已固定應用程式"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"應用程式將會固定在螢幕上顯示,直至您取消固定為止。按住「返回」和「概覽」按鈕即可取消固定。"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"應用程式將會固定在螢幕上顯示,直至您取消固定為止。按住「返回」按鈕和主按鈕即可取消固定。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index ad90947..2b6372a 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -119,7 +119,7 @@
<string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"語音小幫手"</string>
<string name="accessibility_wallet_button" msgid="1458258783460555507">"錢包"</string>
- <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR 圖碼掃描器"</string>
+ <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR code 掃描器"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"解除鎖定"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"裝置已鎖定"</string>
<string name="accessibility_scanning_face" msgid="3093828357921541387">"掃描臉孔"</string>
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"無法辨識臉孔,請改用指紋完成驗證。"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"藍牙連線已建立。"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"電池電量不明。"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"已連線至<xliff:g id="BLUETOOTH">%s</xliff:g>。"</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"裝置已透過你的臉解鎖,按下即可開啟。"</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"臉孔辨識完成,按下即可開啟。"</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"臉孔辨識完成,按下「解鎖」圖示即可開啟。"</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"裝置已透過你的臉解鎖"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"臉孔辨識完成"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"向左移"</item>
<item msgid="5558598599408514296">"向下移"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 快速充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在座架上充電 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉式選單"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會遭到刪除。"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"訪客你好,歡迎回來!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"你要繼續這個工作階段嗎?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"字幕重疊顯示"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"啟用"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"停用"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"音效與震動"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"設定"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"應用程式已固定"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"這會讓目前的螢幕畫面保持顯示狀態,直到取消固定為止。按住 [返回] 按鈕和 [總覽] 按鈕即可取消固定。"</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"這會讓應用程式顯示在螢幕上,直到取消固定為止。按住 [返回] 按鈕和主畫面按鈕即可取消固定。"</string>
@@ -918,10 +925,10 @@
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"新增設定方塊"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"不要新增設定方塊"</string>
<string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"選取使用者"</string>
- <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# 個應用程式使用中}other{# 個應用程式使用中}}"</string>
+ <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# 個應用程式正在運作}other{# 個應用程式正在運作}}"</string>
<string name="fgs_dot_content_description" msgid="2865071539464777240">"新資訊"</string>
- <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"使用中的應用程式"</string>
- <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"即使您並未使用,這些應用程式仍會持續啟用並執行。這可提升其功能,但也可能影響電池續航力。"</string>
+ <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"運作中的應用程式"</string>
+ <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"即使您並未使用,這些應用程式仍會持續運作。這可提升應用程式效能,但也可能影響電池續航力。"</string>
<string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"停止"</string>
<string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"已停止"</string>
<string name="clipboard_edit_text_done" msgid="4551887727694022409">"完成"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index bfa86f5..9a4d849 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -161,6 +161,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ayibazi ubuso. Sebenzisa izigxivizo zeminwe kunalokho."</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
<skip />
+ <!-- no translation found for keyguard_face_failed (9044619102286917151) -->
+ <skip />
+ <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) -->
+ <skip />
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ixhunyiwe"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Iphesenti lebhethri alaziwa."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Xhuma ku-<xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -312,6 +316,8 @@
<string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Vula ngobuso. Cindezela ukuze uvule."</string>
<string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Ubuso buyaziwa. Cindezela ukuze uvule."</string>
<string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ubuso buyaziwa. Cindezela isithonjana sokuvula ukuze uvule."</string>
+ <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Vula ngobuso"</string>
+ <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ubuso buyaziwa"</string>
<string-array name="udfps_accessibility_touch_hints">
<item msgid="1901953991150295169">"Yisa kwesokunxele"</item>
<item msgid="5558598599408514296">"Yehlisa"</item>
@@ -337,10 +343,9 @@
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Iyashaja • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja ngokushesha • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja kancane • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
- <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ukushaja Idokhi • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Iyashaja • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Shintsha umsebenzisi"</string>
- <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) -->
- <skip />
+ <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"imenyu yokudonsela phansi"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Zonke izinhlelo zokusebenza nedatha kulesi sikhathi zizosuswa."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Siyakwamukela futhi, sivakashi!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Ingabe ufuna ukuqhubeka ngesikhathi sakho?"</string>
@@ -418,6 +423,8 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Imbondela yamagama-ncazo"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"nika amandla"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"khubaza"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"Umsindo nokudlidliza"</string>
+ <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Amasethingi"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"I-app iphiniwe"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Lokhu kuyigcina ibukeka uze ususe ukuphina. Thinta uphinde ubambe okuthi Emuva Nokubuka konke ukuze ususe ukuphina."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Lokhu kuyigcina ibonakala uze uyisuse. Thinta uphinde ubambe okuthi Emuva nokuthi Ekhaya ukuze ususe ukuphina."</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 1eece4c..db2ac43 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -241,4 +241,6 @@
<color name="dream_overlay_aqi_very_unhealthy">#AD1457</color>
<color name="dream_overlay_aqi_hazardous">#880E4F</color>
<color name="dream_overlay_aqi_unknown">#BDC1C6</color>
+ <color name="dream_overlay_clock_key_text_shadow_color">#4D000000</color>
+ <color name="dream_overlay_clock_ambient_text_shadow_color">#4D000000</color>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 2298584..e3be365 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -380,6 +380,7 @@
<!-- (48dp - 40dp) / 2 -->
<dimen name="qs_footer_action_inset">4dp</dimen>
+ <dimen name="qs_footer_actions_top_padding">8dp</dimen>
<dimen name="qs_footer_actions_bottom_padding">4dp</dimen>
<dimen name="qs_footer_action_inset_negative">-4dp</dimen>
@@ -478,6 +479,10 @@
<dimen name="volume_tool_tip_arrow_corner_radius">2dp</dimen>
+ <!-- Volume panel slices dimensions -->
+ <dimen name="volume_panel_slice_vertical_padding">8dp</dimen>
+ <dimen name="volume_panel_slice_horizontal_padding">24dp</dimen>
+
<!-- Size of each item in the ringer selector drawer. -->
<dimen name="volume_ringer_drawer_item_size">42dp</dimen>
<dimen name="volume_ringer_drawer_item_size_half">21dp</dimen>
@@ -666,12 +671,6 @@
<!-- With the large clock, move up slightly from the center -->
<dimen name="keyguard_large_clock_top_margin">-60dp</dimen>
- <!-- TODO: Remove during migration -->
- <!-- Default line spacing multiplier between hours and minutes of the keyguard clock -->
- <item name="keyguard_clock_line_spacing_scale" type="dimen" format="float">.7</item>
- <!-- Burmese line spacing multiplier between hours and minutes of the keyguard clock -->
- <item name="keyguard_clock_line_spacing_scale_burmese" type="dimen" format="float">1</item>
-
<dimen name="notification_scrim_corner_radius">32dp</dimen>
<!-- The minimum amount the user needs to swipe to go to the camera / phone. -->
@@ -890,11 +889,6 @@
burn-in on AOD. -->
<dimen name="burn_in_prevention_offset_y_clock">42dp</dimen>
- <!-- Clock maximum font size (dp is intentional, to prevent any further scaling) -->
- <!-- TODO: Remove when clock migration complete -->
- <dimen name="large_clock_text_size">150dp</dimen>
- <dimen name="clock_text_size">86dp</dimen>
-
<!-- The maximum offset in either direction that icons move to prevent burn-in on AOD. -->
<dimen name="default_burn_in_prevention_offset">15dp</dimen>
@@ -1177,7 +1171,6 @@
<item name="shutdown_scrim_behind_alpha" format="float" type="dimen">0.95</item>
<!-- Output switcher panel related dimensions -->
- <dimen name="media_output_dialog_list_margin">12dp</dimen>
<dimen name="media_output_dialog_list_max_height">355dp</dimen>
<dimen name="media_output_dialog_header_album_icon_size">72dp</dimen>
<dimen name="media_output_dialog_header_back_icon_size">32dp</dimen>
@@ -1539,4 +1532,10 @@
<dimen name="broadcast_dialog_btn_text_size">16sp</dimen>
<dimen name="broadcast_dialog_btn_minHeight">44dp</dimen>
<dimen name="broadcast_dialog_margin">16dp</dimen>
+ <dimen name="dream_overlay_clock_key_text_shadow_dx">0dp</dimen>
+ <dimen name="dream_overlay_clock_key_text_shadow_dy">0dp</dimen>
+ <dimen name="dream_overlay_clock_key_text_shadow_radius">5dp</dimen>
+ <dimen name="dream_overlay_clock_ambient_text_shadow_dx">0dp</dimen>
+ <dimen name="dream_overlay_clock_ambient_text_shadow_dy">0dp</dimen>
+ <dimen name="dream_overlay_clock_ambient_text_shadow_radius">1dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index dca5ea8..8084254 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -131,7 +131,11 @@
<!-- For StatusIconContainer to tag its icon views -->
<item type="id" name="status_bar_view_state_tag" />
+ <!-- Default display cutout on the physical top of screen -->
<item type="id" name="display_cutout" />
+ <item type="id" name="display_cutout_left" />
+ <item type="id" name="display_cutout_right" />
+ <item type="id" name="display_cutout_bottom" />
<item type="id" name="row_tag_for_content_view" />
@@ -179,5 +183,7 @@
<!-- face scanning view id -->
<item type="id" name="face_scanning_anim"/>
+
+ <item type="id" name="qqs_tile_layout"/>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index e4fefc7..b33cea7 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -389,6 +389,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead">Can\u2019t recognize face. Use fingerprint instead.</string>
<!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
<string name="keyguard_face_failed_use_fp">@string/fingerprint_dialog_use_fingerprint_instead</string>
+ <!-- Message shown to inform the user a face cannot be recognized. [CHAR LIMIT=25] -->
+ <string name="keyguard_face_failed">Can\u2019t recognize face</string>
+ <!-- Message shown to suggest using fingerprint sensor to authenticate after another biometric failed. [CHAR LIMIT=25] -->
+ <string name="keyguard_suggest_fingerprint">Use fingerprint instead</string>
<!-- Content description of the bluetooth icon when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_bluetooth_connected">Bluetooth connected.</string>
@@ -1139,6 +1143,11 @@
<!-- Content description for accessibility: Hint if click will disable. [CHAR LIMIT=NONE] -->
<string name="volume_odi_captions_hint_disable">disable</string>
+ <!-- Sound and vibration settings dialog title. [CHAR LIMIT=30] -->
+ <string name="sound_settings">Sound & vibration</string>
+ <!-- Label for button to go to sound settings screen [CHAR_LIMIT=30] -->
+ <string name="volume_panel_dialog_settings_button">Settings</string>
+
<!-- content description for audio output chooser [CHAR LIMIT=NONE]-->
<!-- Screen pinning dialog title. -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 112d903..6b2ff37 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -928,6 +928,10 @@
<item name="rowStyle">@style/SliceRow</item>
</style>
+ <style name="Widget.SliceView.Panel.Slider">
+ <item name="rowStyle">@style/SliceRow.Slider</item>
+ </style>
+
<style name="SliceRow">
<!-- 2dp start padding for the start icon -->
<item name="titleItemStartPadding">2dp</item>
@@ -949,6 +953,26 @@
<item name="actionDividerHeight">32dp</item>
</style>
+ <style name="SliceRow.Slider">
+ <!-- Padding between content and the start icon is 5dp -->
+ <item name="contentStartPadding">5dp</item>
+ <item name="contentEndPadding">0dp</item>
+
+ <!-- 0dp start padding for the end item -->
+ <item name="endItemStartPadding">0dp</item>
+ <!-- 8dp end padding for the end item -->
+ <item name="endItemEndPadding">8dp</item>
+
+ <item name="titleSize">20sp</item>
+ <!-- Align text with slider -->
+ <item name="titleStartPadding">11dp</item>
+ <item name="subContentStartPadding">11dp</item>
+
+ <!-- Padding for indeterminate progress bar -->
+ <item name="progressBarStartPadding">12dp</item>
+ <item name="progressBarEndPadding">16dp</item>
+ </style>
+
<style name="TextAppearance.Dialog.Title" parent="@android:style/TextAppearance.DeviceDefault.Large">
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textSize">24sp</item>
diff --git a/packages/SystemUI/res/xml/combined_qs_header_scene.xml b/packages/SystemUI/res/xml/combined_qs_header_scene.xml
index 0fac76d..f3866c0 100644
--- a/packages/SystemUI/res/xml/combined_qs_header_scene.xml
+++ b/packages/SystemUI/res/xml/combined_qs_header_scene.xml
@@ -29,17 +29,15 @@
app:percentX="0"
app:percentY="0"
app:framePosition="49"
- app:percentWidth="1"
- app:percentHeight="1"
+ app:sizePercent="0"
app:curveFit="linear"
app:motionTarget="@id/date" />
<KeyPosition
app:keyPositionType="deltaRelative"
app:percentX="1"
app:percentY="0.51"
+ app:sizePercent="1"
app:framePosition="51"
- app:percentWidth="1"
- app:percentHeight="1"
app:curveFit="linear"
app:motionTarget="@id/date" />
<KeyAttribute
@@ -64,6 +62,7 @@
app:percentX="0"
app:percentY="0"
app:framePosition="50"
+ app:sizePercent="0"
app:curveFit="linear"
app:motionTarget="@id/statusIcons" />
<KeyPosition
@@ -71,6 +70,7 @@
app:percentX="1"
app:percentY="0.51"
app:framePosition="51"
+ app:sizePercent="1"
app:curveFit="linear"
app:motionTarget="@id/statusIcons" />
<KeyAttribute
diff --git a/packages/SystemUI/shared/res/layout/clock_default_large.xml b/packages/SystemUI/shared/res/layout/clock_default_large.xml
index 8510a0a..0139d50 100644
--- a/packages/SystemUI/shared/res/layout/clock_default_large.xml
+++ b/packages/SystemUI/shared/res/layout/clock_default_large.xml
@@ -18,7 +18,6 @@
-->
<com.android.systemui.shared.clocks.AnimatableClockView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/animatable_clock_view_large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
diff --git a/packages/SystemUI/shared/res/layout/clock_default_small.xml b/packages/SystemUI/shared/res/layout/clock_default_small.xml
index ec0e427..ff6d7f9 100644
--- a/packages/SystemUI/shared/res/layout/clock_default_small.xml
+++ b/packages/SystemUI/shared/res/layout/clock_default_small.xml
@@ -18,14 +18,14 @@
-->
<com.android.systemui.shared.clocks.AnimatableClockView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/animatable_clock_view"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:gravity="start"
android:textSize="@dimen/small_clock_text_size"
android:fontFamily="@*android:string/config_clockFontFamily"
android:elegantTextHeight="false"
+ android:ellipsize="none"
android:singleLine="true"
android:fontFeatureSettings="pnum"
chargeAnimationDelay="350"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
index c2fda82..b3b75f6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
@@ -20,12 +20,16 @@
import android.annotation.FloatRange
import android.annotation.IntRange
import android.annotation.SuppressLint
+import android.app.compat.ChangeIdStateCache.invalidate
import android.content.Context
import android.graphics.Canvas
import android.text.TextUtils
import android.text.format.DateFormat
import android.util.AttributeSet
import android.widget.TextView
+import com.android.internal.R.attr.contentDescription
+import com.android.internal.R.attr.format
+import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.animation.GlyphCallback
import com.android.systemui.animation.Interpolators
import com.android.systemui.animation.TextAnimator
@@ -74,7 +78,8 @@
private var textAnimator: TextAnimator? = null
private var onTextAnimatorInitialized: Runnable? = null
- var timeOverrideInMillis: Long? = null
+ @VisibleForTesting var isAnimationEnabled: Boolean = true
+ @VisibleForTesting var timeOverrideInMillis: Long? = null
val dozingWeight: Int
get() = if (useBoldedVersion()) dozingWeightInternal + 100 else dozingWeightInternal
@@ -82,6 +87,12 @@
val lockScreenWeight: Int
get() = if (useBoldedVersion()) lockScreenWeightInternal + 100 else lockScreenWeightInternal
+ /**
+ * The number of pixels below the baseline. For fonts that support languages such as
+ * Burmese, this space can be significant and should be accounted for when computing layout.
+ */
+ val bottom get() = paint?.fontMetrics?.bottom ?: 0f
+
init {
val animatableClockViewAttributes = context.obtainStyledAttributes(
attrs, R.styleable.AnimatableClockView, defStyleAttr, defStyleRes
@@ -141,6 +152,15 @@
if (!TextUtils.equals(text, formattedText)) {
text = formattedText
lastTextUpdate = getTimestamp()
+
+ // Because the TextLayout may mutate under the hood as a result of the new text, we
+ // notify the TextAnimator that it may have changed and request a measure/layout. A
+ // crash will occur on the next invocation of setTextStyle if the layout is mutated
+ // without being notified TextInterpolator being notified.
+ if (layout != null) {
+ textAnimator?.updateLayout(layout)
+ }
+ requestLayout()
}
}
@@ -200,7 +220,7 @@
}
fun animateAppearOnLockscreen() {
- if (textAnimator == null) {
+ if (isAnimationEnabled && textAnimator == null) {
return
}
setTextStyle(
@@ -216,7 +236,7 @@
weight = lockScreenWeight,
textSize = -1f,
color = lockScreenColor,
- animate = true,
+ animate = isAnimationEnabled,
duration = APPEAR_ANIM_DURATION,
delay = 0,
onAnimationEnd = null
@@ -224,7 +244,7 @@
}
fun animateFoldAppear(animate: Boolean = true) {
- if (textAnimator == null) {
+ if (isAnimationEnabled && textAnimator == null) {
return
}
setTextStyle(
@@ -240,7 +260,7 @@
weight = dozingWeightInternal,
textSize = -1f,
color = dozingColor,
- animate = animate,
+ animate = animate && isAnimationEnabled,
interpolator = Interpolators.EMPHASIZED_DECELERATE,
duration = ANIMATION_DURATION_FOLD_TO_AOD.toLong(),
delay = 0,
@@ -258,7 +278,7 @@
weight = if (isDozing()) dozingWeight else lockScreenWeight,
textSize = -1f,
color = null,
- animate = true,
+ animate = isAnimationEnabled,
duration = CHARGE_ANIM_DURATION_PHASE_1,
delay = 0,
onAnimationEnd = null
@@ -268,7 +288,7 @@
weight = if (isDozing()) lockScreenWeight else dozingWeight,
textSize = -1f,
color = null,
- animate = true,
+ animate = isAnimationEnabled,
duration = CHARGE_ANIM_DURATION_PHASE_0,
delay = chargeAnimationDelay.toLong(),
onAnimationEnd = startAnimPhase2
@@ -280,7 +300,7 @@
weight = if (isDozing) dozingWeight else lockScreenWeight,
textSize = -1f,
color = if (isDozing) dozingColor else lockScreenColor,
- animate = animate,
+ animate = animate && isAnimationEnabled,
duration = DOZE_ANIM_DURATION,
delay = 0,
onAnimationEnd = null
@@ -314,7 +334,7 @@
weight = weight,
textSize = textSize,
color = color,
- animate = animate,
+ animate = animate && isAnimationEnabled,
duration = duration,
interpolator = interpolator,
delay = delay,
@@ -352,7 +372,7 @@
weight = weight,
textSize = textSize,
color = color,
- animate = animate,
+ animate = animate && isAnimationEnabled,
interpolator = null,
duration = duration,
delay = delay,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index e707d4d..835d6e9 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -35,8 +35,6 @@
private val TAG = ClockRegistry::class.simpleName
private val DEBUG = true
-typealias ClockChangeListener = () -> Unit
-
/** ClockRegistry aggregates providers and plugins */
open class ClockRegistry(
val context: Context,
@@ -51,6 +49,11 @@
defaultClockProvider: DefaultClockProvider
) : this(context, pluginManager, handler, defaultClockProvider as ClockProvider) { }
+ // Usually this would be a typealias, but a SAM provides better java interop
+ fun interface ClockChangeListener {
+ fun onClockChanged()
+ }
+
var isEnabled: Boolean = false
private val gson = Gson()
@@ -58,7 +61,7 @@
private val clockChangeListeners = mutableListOf<ClockChangeListener>()
private val settingObserver = object : ContentObserver(handler) {
override fun onChange(selfChange: Boolean, uris: Collection<Uri>, flags: Int, userId: Int) =
- clockChangeListeners.forEach { it() }
+ clockChangeListeners.forEach { it.onClockChanged() }
}
private val pluginListener = object : PluginListener<ClockProviderPlugin> {
@@ -117,8 +120,11 @@
val id = clock.clockId
val current = availableClocks[id]
if (current != null) {
- Log.e(TAG, "Clock Id conflict: $id is registered by both " +
- "${provider::class.simpleName} and ${current.provider::class.simpleName}")
+ Log.e(
+ TAG,
+ "Clock Id conflict: $id is registered by both " +
+ "${provider::class.simpleName} and ${current.provider::class.simpleName}"
+ )
return
}
@@ -127,7 +133,7 @@
if (DEBUG) {
Log.i(TAG, "Current clock ($currentId) was connected")
}
- clockChangeListeners.forEach { it() }
+ clockChangeListeners.forEach { it.onClockChanged() }
}
}
}
@@ -139,7 +145,7 @@
if (currentId == clock.clockId) {
Log.w(TAG, "Current clock ($currentId) was disconnected")
- clockChangeListeners.forEach { it() }
+ clockChangeListeners.forEach { it.onClockChanged() }
}
}
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
index 5d8da59..b5e5766 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
@@ -13,16 +13,18 @@
*/
package com.android.systemui.shared.clocks
+import android.content.Context
import android.content.res.Resources
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.icu.text.NumberFormat
import android.util.TypedValue
import android.view.LayoutInflater
-import com.android.internal.colorextraction.ColorExtractor
+import android.widget.FrameLayout
+import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.Clock
-import com.android.systemui.plugins.ClockAnimation
+import com.android.systemui.plugins.ClockAnimations
import com.android.systemui.plugins.ClockEvents
import com.android.systemui.plugins.ClockId
import com.android.systemui.plugins.ClockMetadata
@@ -39,6 +41,7 @@
/** Provides the default system clock */
class DefaultClockProvider @Inject constructor(
+ val ctx: Context,
val layoutInflater: LayoutInflater,
@Main val resources: Resources
) : ClockProvider {
@@ -49,7 +52,7 @@
if (id != DEFAULT_CLOCK_ID) {
throw IllegalArgumentException("$id is unsupported by $TAG")
}
- return DefaultClock(layoutInflater, resources)
+ return DefaultClock(ctx, layoutInflater, resources)
}
override fun getClockThumbnail(id: ClockId): Drawable? {
@@ -69,14 +72,13 @@
* AnimatableClockView used by the existing lockscreen clock.
*/
class DefaultClock(
- private val layoutInflater: LayoutInflater,
- private val resources: Resources
+ ctx: Context,
+ private val layoutInflater: LayoutInflater,
+ private val resources: Resources
) : Clock {
- override val smallClock =
- layoutInflater.inflate(R.layout.clock_default_small, null) as AnimatableClockView
- override val largeClock =
- layoutInflater.inflate(R.layout.clock_default_large, null) as AnimatableClockView
- private val clocks = listOf(smallClock, largeClock)
+ override val smallClock: AnimatableClockView
+ override val largeClock: AnimatableClockView
+ private val clocks get() = listOf(smallClock, largeClock)
private val burmeseNf = NumberFormat.getInstance(Locale.forLanguageTag("my"))
private val burmeseNumerals = burmeseNf.format(FORMAT_NUMBER.toLong())
@@ -84,7 +86,43 @@
resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale_burmese)
private val defaultLineSpacing = resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale)
- override val events = object : ClockEvents {
+ override val events: ClockEvents
+ override lateinit var animations: ClockAnimations
+ private set
+
+ init {
+ val parent = FrameLayout(ctx)
+
+ smallClock = layoutInflater.inflate(
+ R.layout.clock_default_small,
+ parent,
+ false
+ ) as AnimatableClockView
+
+ largeClock = layoutInflater.inflate(
+ R.layout.clock_default_large,
+ parent,
+ false
+ ) as AnimatableClockView
+
+ events = DefaultClockEvents()
+ animations = DefaultClockAnimations(0f, 0f)
+
+ events.onLocaleChanged(Locale.getDefault())
+
+ // DOZE_COLOR is a placeholder, and will be assigned correctly in initialize
+ clocks.forEach { it.setColors(DOZE_COLOR, DOZE_COLOR) }
+ }
+
+ override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
+ recomputePadding()
+ animations = DefaultClockAnimations(dozeFraction, foldFraction)
+ events.onColorPaletteChanged(resources, true, true)
+ events.onTimeZoneChanged(TimeZone.getDefault())
+ events.onTimeTick()
+ }
+
+ inner class DefaultClockEvents() : ClockEvents {
override fun onTimeTick() = clocks.forEach { it.refreshTime() }
override fun onTimeFormatChanged(is24Hr: Boolean) =
@@ -102,10 +140,17 @@
TypedValue.COMPLEX_UNIT_PX,
resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()
)
+ recomputePadding()
}
- override fun onColorPaletteChanged(palette: ColorExtractor.GradientColors) =
- clocks.forEach { it.setColors(DOZE_COLOR, palette.mainColor) }
+ override fun onColorPaletteChanged(
+ resources: Resources,
+ smallClockIsDark: Boolean,
+ largeClockIsDark: Boolean
+ ) {
+ updateClockColor(smallClock, smallClockIsDark)
+ updateClockColor(largeClock, largeClockIsDark)
+ }
override fun onLocaleChanged(locale: Locale) {
val nf = NumberFormat.getInstance(locale)
@@ -119,8 +164,14 @@
}
}
- override val animation = object : ClockAnimation {
- override fun initialize(dozeFraction: Float, foldFraction: Float) {
+ inner class DefaultClockAnimations(
+ dozeFraction: Float,
+ foldFraction: Float
+ ) : ClockAnimations {
+ private var foldState = AnimationState(0f)
+ private var dozeState = AnimationState(0f)
+
+ init {
dozeState = AnimationState(dozeFraction)
foldState = AnimationState(foldFraction)
@@ -132,14 +183,13 @@
}
override fun enter() {
- if (dozeState.isActive) {
+ if (!dozeState.isActive) {
clocks.forEach { it.animateAppearOnLockscreen() }
}
}
override fun charge() = clocks.forEach { it.animateCharge { dozeState.isActive } }
- private var foldState = AnimationState(0f)
override fun fold(fraction: Float) {
val (hasChanged, hasJumped) = foldState.update(fraction)
if (hasChanged) {
@@ -147,7 +197,6 @@
}
}
- private var dozeState = AnimationState(0f)
override fun doze(fraction: Float) {
val (hasChanged, hasJumped) = dozeState.update(fraction)
if (hasChanged) {
@@ -170,14 +219,26 @@
}
}
- init {
- events.onLocaleChanged(Locale.getDefault())
+ private fun updateClockColor(clock: AnimatableClockView, isRegionDark: Boolean) {
+ val color = if (isRegionDark) {
+ resources.getColor(android.R.color.system_accent1_100)
+ } else {
+ resources.getColor(android.R.color.system_accent2_600)
+ }
+ clock.setColors(DOZE_COLOR, color)
+ clock.animateAppearOnLockscreen()
+ }
+
+ private fun recomputePadding() {
+ val lp = largeClock.getLayoutParams() as FrameLayout.LayoutParams
+ lp.topMargin = (-0.5f * largeClock.bottom).toInt()
+ largeClock.setLayoutParams(lp)
}
override fun dump(pw: PrintWriter) = clocks.forEach { it.dump(pw) }
companion object {
- private const val DOZE_COLOR = Color.WHITE
+ @VisibleForTesting const val DOZE_COLOR = Color.WHITE
private const val FORMAT_NUMBER = 1234567890
}
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSamplingInstance.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSamplingInstance.kt
index 0146795..dd2e55d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSamplingInstance.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSamplingInstance.kt
@@ -35,6 +35,7 @@
) {
private var isDark = RegionDarkness.DEFAULT
private var samplingBounds = Rect()
+ private val tmpScreenLocation = IntArray(2)
@VisibleForTesting var regionSampler: RegionSamplingHelper? = null
/**
@@ -99,10 +100,21 @@
isDark = convertToClockDarkness(isRegionDark)
updateFun.updateColors()
}
-
+ /**
+ * The method getLocationOnScreen is used to obtain the view coordinates
+ * relative to its left and top edges on the device screen.
+ * Directly accessing the X and Y coordinates of the view returns the
+ * location relative to its parent view instead.
+ */
override fun getSampledRegion(sampledView: View): Rect {
- samplingBounds = Rect(sampledView.left, sampledView.top,
- sampledView.right, sampledView.bottom)
+ val screenLocation = tmpScreenLocation
+ sampledView.getLocationOnScreen(screenLocation)
+ val left = screenLocation[0]
+ val top = screenLocation[1]
+ samplingBounds.left = left
+ samplingBounds.top = top
+ samplingBounds.right = left + sampledView.width
+ samplingBounds.bottom = top + sampledView.height
return samplingBounds
}
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index c69ff7e..6064be9 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -22,7 +22,9 @@
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.Color;
+import android.graphics.Rect;
import android.icu.text.NumberFormat;
+import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
@@ -30,16 +32,24 @@
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.clocks.AnimatableClockView;
+import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.ViewController;
import java.io.PrintWriter;
import java.util.Locale;
import java.util.Objects;
+import java.util.Optional;
import java.util.TimeZone;
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
/**
* Controller for an AnimatableClockView on the keyguard. Instantiated by
@@ -54,7 +64,10 @@
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final BatteryController mBatteryController;
private final int mDozingColor = Color.WHITE;
+ private Optional<RegionSamplingHelper> mRegionSamplingHelper = Optional.empty();
+ private Rect mSamplingBounds = new Rect();
private int mLockScreenColor;
+ private final boolean mRegionSamplingEnabled;
private boolean mIsDozing;
private boolean mIsCharging;
@@ -67,13 +80,17 @@
private final float mBurmeseLineSpacing;
private final float mDefaultLineSpacing;
+ @Inject
public AnimatableClockController(
AnimatableClockView view,
StatusBarStateController statusBarStateController,
BroadcastDispatcher broadcastDispatcher,
BatteryController batteryController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
- @Main Resources resources
+ @Main Resources resources,
+ @Main Executor mainExecutor,
+ @Background Executor bgExecutor,
+ FeatureFlags featureFlags
) {
super(view);
mStatusBarStateController = statusBarStateController;
@@ -86,6 +103,40 @@
R.dimen.keyguard_clock_line_spacing_scale_burmese);
mDefaultLineSpacing = resources.getFloat(
R.dimen.keyguard_clock_line_spacing_scale);
+
+ mRegionSamplingEnabled = featureFlags.isEnabled(Flags.REGION_SAMPLING);
+ if (!mRegionSamplingEnabled) {
+ return;
+ }
+
+ mRegionSamplingHelper = Optional.of(new RegionSamplingHelper(mView,
+ new RegionSamplingHelper.SamplingCallback() {
+ @Override
+ public void onRegionDarknessChanged(boolean isRegionDark) {
+ if (isRegionDark) {
+ mLockScreenColor = Color.WHITE;
+ } else {
+ mLockScreenColor = Color.BLACK;
+ }
+ initColors();
+ }
+
+ @Override
+ public Rect getSampledRegion(View sampledView) {
+ mSamplingBounds = new Rect(sampledView.getLeft(), sampledView.getTop(),
+ sampledView.getRight(), sampledView.getBottom());
+ return mSamplingBounds;
+ }
+
+ @Override
+ public boolean isSamplingEnabled() {
+ return mRegionSamplingEnabled;
+ }
+ }, mainExecutor, bgExecutor)
+ );
+ mRegionSamplingHelper.ifPresent((regionSamplingHelper) -> {
+ regionSamplingHelper.setWindowVisible(true);
+ });
}
private void reset() {
@@ -169,7 +220,11 @@
mStatusBarStateController.addCallback(mStatusBarStateListener);
- refreshTime();
+ mRegionSamplingHelper.ifPresent((regionSamplingHelper) -> {
+ regionSamplingHelper.start(mSamplingBounds);
+ });
+
+ mView.onTimeZoneChanged(TimeZone.getDefault());
initColors();
mView.animateDoze(mIsDozing, false);
}
@@ -180,18 +235,9 @@
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
mBatteryController.removeCallback(mBatteryCallback);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
- }
-
- /**
- * @return the number of pixels below the baseline. For fonts that support languages such as
- * Burmese, this space can be significant.
- */
- public float getBottom() {
- if (mView.getPaint() != null && mView.getPaint().getFontMetrics() != null) {
- return mView.getPaint().getFontMetrics().bottom;
- }
-
- return 0f;
+ mRegionSamplingHelper.ifPresent((regionSamplingHelper) -> {
+ regionSamplingHelper.stop();
+ });
}
/** Animate the clock appearance */
@@ -235,8 +281,10 @@
}
private void initColors() {
- mLockScreenColor = Utils.getColorAttrDefaultColor(getContext(),
- com.android.systemui.R.attr.wallpaperTextColorAccent);
+ if (!mRegionSamplingEnabled) {
+ mLockScreenColor = Utils.getColorAttrDefaultColor(getContext(),
+ com.android.systemui.R.attr.wallpaperTextColorAccent);
+ }
mView.setColors(mDozingColor, mLockScreenColor);
mView.animateDoze(mIsDozing, false);
}
@@ -247,5 +295,8 @@
public void dump(@NonNull PrintWriter pw) {
pw.println(this);
mView.dump(pw);
+ mRegionSamplingHelper.ifPresent((regionSamplingHelper) -> {
+ regionSamplingHelper.dump(pw);
+ });
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
new file mode 100644
index 0000000..0e1e0cb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.keyguard
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.res.Resources
+import android.text.format.DateFormat
+import android.util.TypedValue
+import android.view.View
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.plugins.Clock
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.shared.regionsampling.RegionSamplingInstance
+import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
+import com.android.systemui.statusbar.policy.ConfigurationController
+import java.io.PrintWriter
+import java.util.Locale
+import java.util.TimeZone
+import java.util.concurrent.Executor
+import javax.inject.Inject
+
+/**
+ * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by
+ * [KeyguardClockSwitchController]. Functionality is forked from [AnimatableClockController].
+ */
+open class ClockEventController @Inject constructor(
+ private val statusBarStateController: StatusBarStateController,
+ private val broadcastDispatcher: BroadcastDispatcher,
+ private val batteryController: BatteryController,
+ private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+ private val configurationController: ConfigurationController,
+ @Main private val resources: Resources,
+ private val context: Context,
+ @Main private val mainExecutor: Executor,
+ @Background private val bgExecutor: Executor,
+ private val featureFlags: FeatureFlags
+) {
+ var clock: Clock? = null
+ set(value) {
+ field = value
+ if (value != null) {
+ value.initialize(resources, dozeAmount, 0f)
+ updateRegionSamplers(value)
+ }
+ }
+
+ private var isDozing = false
+ private set
+
+ private var isCharging = false
+ private var dozeAmount = 0f
+ private var isKeyguardShowing = false
+
+ private val regionSamplingEnabled =
+ featureFlags.isEnabled(com.android.systemui.flags.Flags.REGION_SAMPLING)
+
+ private val updateFun = object : RegionSamplingInstance.UpdateColorCallback {
+ override fun updateColors() {
+ if (regionSamplingEnabled) {
+ smallClockIsDark = smallRegionSamplingInstance.currentRegionDarkness().isDark
+ largeClockIsDark = largeRegionSamplingInstance.currentRegionDarkness().isDark
+ } else {
+ val isLightTheme = TypedValue()
+ context.theme.resolveAttribute(android.R.attr.isLightTheme, isLightTheme, true)
+ smallClockIsDark = isLightTheme.data == 0
+ largeClockIsDark = isLightTheme.data == 0
+ }
+ clock?.events?.onColorPaletteChanged(resources, smallClockIsDark, largeClockIsDark)
+ }
+ }
+
+ fun updateRegionSamplers(currentClock: Clock?) {
+ smallRegionSamplingInstance = createRegionSampler(
+ currentClock?.smallClock,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingEnabled,
+ updateFun
+ )
+
+ largeRegionSamplingInstance = createRegionSampler(
+ currentClock?.largeClock,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingEnabled,
+ updateFun
+ )
+
+ smallRegionSamplingInstance.startRegionSampler()
+ largeRegionSamplingInstance.startRegionSampler()
+
+ updateFun.updateColors()
+ }
+
+ protected open fun createRegionSampler(
+ sampledView: View?,
+ mainExecutor: Executor?,
+ bgExecutor: Executor?,
+ regionSamplingEnabled: Boolean,
+ updateFun: RegionSamplingInstance.UpdateColorCallback
+ ): RegionSamplingInstance {
+ return RegionSamplingInstance(
+ sampledView,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingEnabled,
+ updateFun)
+ }
+
+ lateinit var smallRegionSamplingInstance: RegionSamplingInstance
+ lateinit var largeRegionSamplingInstance: RegionSamplingInstance
+
+ private var smallClockIsDark = true
+ private var largeClockIsDark = true
+
+ private val configListener = object : ConfigurationController.ConfigurationListener {
+ override fun onThemeChanged() {
+ updateFun.updateColors()
+ }
+ }
+
+ private val batteryCallback = object : BatteryStateChangeCallback {
+ override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
+ if (isKeyguardShowing && !isCharging && charging) {
+ clock?.animations?.charge()
+ }
+ isCharging = charging
+ }
+ }
+
+ private val localeBroadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ clock?.events?.onLocaleChanged(Locale.getDefault())
+ }
+ }
+
+ private val statusBarStateListener = object : StatusBarStateController.StateListener {
+ override fun onDozeAmountChanged(linear: Float, eased: Float) {
+ clock?.animations?.doze(linear)
+
+ isDozing = linear > dozeAmount
+ dozeAmount = linear
+ }
+ }
+
+ private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() {
+ override fun onKeyguardVisibilityChanged(showing: Boolean) {
+ isKeyguardShowing = showing
+ if (!isKeyguardShowing) {
+ clock?.animations?.doze(if (isDozing) 1f else 0f)
+ }
+ }
+
+ override fun onTimeFormatChanged(timeFormat: String) {
+ clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
+ }
+
+ override fun onTimeZoneChanged(timeZone: TimeZone) {
+ clock?.events?.onTimeZoneChanged(timeZone)
+ }
+
+ override fun onUserSwitchComplete(userId: Int) {
+ clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
+ }
+ }
+
+ init {
+ isDozing = statusBarStateController.isDozing
+ }
+
+ fun registerListeners() {
+ dozeAmount = statusBarStateController.dozeAmount
+ isDozing = statusBarStateController.isDozing || dozeAmount != 0f
+
+ broadcastDispatcher.registerReceiver(
+ localeBroadcastReceiver,
+ IntentFilter(Intent.ACTION_LOCALE_CHANGED)
+ )
+ configurationController.addCallback(configListener)
+ batteryController.addCallback(batteryCallback)
+ keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
+ statusBarStateController.addCallback(statusBarStateListener)
+ smallRegionSamplingInstance.startRegionSampler()
+ largeRegionSamplingInstance.startRegionSampler()
+ }
+
+ fun unregisterListeners() {
+ broadcastDispatcher.unregisterReceiver(localeBroadcastReceiver)
+ configurationController.removeCallback(configListener)
+ batteryController.removeCallback(batteryCallback)
+ keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
+ statusBarStateController.removeCallback(statusBarStateListener)
+ smallRegionSamplingInstance.stopRegionSampler()
+ largeRegionSamplingInstance.stopRegionSampler()
+ }
+
+ /**
+ * Dump information for debugging
+ */
+ fun dump(pw: PrintWriter) {
+ pw.println(this)
+ clock?.dump(pw)
+ smallRegionSamplingInstance.dump(pw)
+ largeRegionSamplingInstance.dump(pw)
+ }
+
+ companion object {
+ private val TAG = ClockEventController::class.simpleName
+ private const val FORMAT_NUMBER = 1234567890
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 9164108..d7cd1d0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -5,31 +5,23 @@
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
import android.util.AttributeSet;
-import android.util.TypedValue;
+import android.util.Log;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import androidx.annotation.IntDef;
import androidx.annotation.VisibleForTesting;
-import com.android.internal.colorextraction.ColorExtractor;
import com.android.keyguard.dagger.KeyguardStatusViewScope;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
-import com.android.systemui.plugins.ClockPlugin;
-import com.android.systemui.shared.clocks.AnimatableClockView;
+import com.android.systemui.plugins.Clock;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-import java.util.TimeZone;
-
/**
* Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
*/
@@ -50,17 +42,10 @@
public static final int SMALL = 1;
/**
- * Optional/alternative clock injected via plugin.
- */
- private ClockPlugin mClockPlugin;
-
- /**
* Frame for small/large clocks
*/
- private FrameLayout mClockFrame;
+ private FrameLayout mSmallClockFrame;
private FrameLayout mLargeClockFrame;
- private AnimatableClockView mClockView;
- private AnimatableClockView mLargeClockView;
private View mStatusArea;
private int mSmartspaceTopOffset;
@@ -80,12 +65,6 @@
@VisibleForTesting AnimatorSet mClockOutAnim = null;
private ObjectAnimator mStatusAreaAnim = null;
- /**
- * If the Keyguard Slice has a header (big center-aligned text.)
- */
- private boolean mSupportsDarkText;
- private int[] mColorPalette;
-
private int mClockSwitchYAmount;
@VisibleForTesting boolean mChildrenAreLaidOut = false;
@VisibleForTesting boolean mAnimateOnLayout = true;
@@ -98,97 +77,36 @@
* Apply dp changes on font/scale change
*/
public void onDensityOrFontScaleChanged() {
- mLargeClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources()
- .getDimensionPixelSize(R.dimen.large_clock_text_size));
- mClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources()
- .getDimensionPixelSize(R.dimen.clock_text_size));
-
mClockSwitchYAmount = mContext.getResources().getDimensionPixelSize(
R.dimen.keyguard_clock_switch_y_shift);
-
mSmartspaceTopOffset = mContext.getResources().getDimensionPixelSize(
R.dimen.keyguard_smartspace_top_offset);
}
- /**
- * Returns if this view is presenting a custom clock, or the default implementation.
- */
- public boolean hasCustomClock() {
- return mClockPlugin != null;
- }
-
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mClockFrame = findViewById(R.id.lockscreen_clock_view);
- mClockView = findViewById(R.id.animatable_clock_view);
+ mSmallClockFrame = findViewById(R.id.lockscreen_clock_view);
mLargeClockFrame = findViewById(R.id.lockscreen_clock_view_large);
- mLargeClockView = findViewById(R.id.animatable_clock_view_large);
mStatusArea = findViewById(R.id.keyguard_status_area);
onDensityOrFontScaleChanged();
}
- void setClockPlugin(ClockPlugin plugin, int statusBarState) {
+ void setClock(Clock clock, int statusBarState) {
// Disconnect from existing plugin.
- if (mClockPlugin != null) {
- View smallClockView = mClockPlugin.getView();
- if (smallClockView != null && smallClockView.getParent() == mClockFrame) {
- mClockFrame.removeView(smallClockView);
- }
- View bigClockView = mClockPlugin.getBigClockView();
- if (bigClockView != null && bigClockView.getParent() == mLargeClockFrame) {
- mLargeClockFrame.removeView(bigClockView);
- }
- mClockPlugin.onDestroyView();
- mClockPlugin = null;
- }
- if (plugin == null) {
- mClockView.setVisibility(View.VISIBLE);
- mLargeClockView.setVisibility(View.VISIBLE);
+ mSmallClockFrame.removeAllViews();
+ mLargeClockFrame.removeAllViews();
+
+ if (clock == null) {
+ Log.e(TAG, "No clock being shown");
return;
}
+
// Attach small and big clock views to hierarchy.
- View smallClockView = plugin.getView();
- if (smallClockView != null) {
- mClockFrame.addView(smallClockView, -1,
- new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- mClockView.setVisibility(View.GONE);
- }
- View bigClockView = plugin.getBigClockView();
- if (bigClockView != null) {
- mLargeClockFrame.addView(bigClockView);
- mLargeClockView.setVisibility(View.GONE);
- }
-
- // Initialize plugin parameters.
- mClockPlugin = plugin;
- mClockPlugin.setStyle(getPaint().getStyle());
- mClockPlugin.setTextColor(getCurrentTextColor());
- mClockPlugin.setDarkAmount(mDarkAmount);
- if (mColorPalette != null) {
- mClockPlugin.setColorPalette(mSupportsDarkText, mColorPalette);
- }
- }
-
- /**
- * It will also update plugin setStyle if plugin is connected.
- */
- public void setStyle(Style style) {
- if (mClockPlugin != null) {
- mClockPlugin.setStyle(style);
- }
- }
-
- /**
- * It will also update plugin setTextColor if plugin is connected.
- */
- public void setTextColor(int color) {
- if (mClockPlugin != null) {
- mClockPlugin.setTextColor(color);
- }
+ mSmallClockFrame.addView(clock.getSmallClock());
+ mLargeClockFrame.addView(clock.getLargeClock());
}
private void updateClockViews(boolean useLargeClock, boolean animate) {
@@ -204,14 +122,14 @@
int direction = 1;
float statusAreaYTranslation;
if (useLargeClock) {
- out = mClockFrame;
+ out = mSmallClockFrame;
in = mLargeClockFrame;
if (indexOfChild(in) == -1) addView(in);
direction = -1;
- statusAreaYTranslation = mClockFrame.getTop() - mStatusArea.getTop()
+ statusAreaYTranslation = mSmallClockFrame.getTop() - mStatusArea.getTop()
+ mSmartspaceTopOffset;
} else {
- in = mClockFrame;
+ in = mSmallClockFrame;
out = mLargeClockFrame;
statusAreaYTranslation = 0f;
@@ -270,18 +188,6 @@
}
/**
- * Set the amount (ratio) that the device has transitioned to doze.
- *
- * @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
- */
- public void setDarkAmount(float darkAmount) {
- mDarkAmount = darkAmount;
- if (mClockPlugin != null) {
- mClockPlugin.setDarkAmount(darkAmount);
- }
- }
-
- /**
* Display the desired clock and hide the other one
*
* @return true if desired clock appeared and false if it was already visible
@@ -312,64 +218,11 @@
mChildrenAreLaidOut = true;
}
- public Paint getPaint() {
- return mClockView.getPaint();
- }
-
- public int getCurrentTextColor() {
- return mClockView.getCurrentTextColor();
- }
-
- public float getTextSize() {
- return mClockView.getTextSize();
- }
-
- /**
- * Refresh the time of the clock, due to either time tick broadcast or doze time tick alarm.
- */
- public void refresh() {
- if (mClockPlugin != null) {
- mClockPlugin.onTimeTick();
- }
- }
-
- /**
- * Notifies that the time zone has changed.
- */
- public void onTimeZoneChanged(TimeZone timeZone) {
- if (mClockPlugin != null) {
- mClockPlugin.onTimeZoneChanged(timeZone);
- }
- }
-
- /**
- * Notifies that the time format has changed.
- *
- * @param timeFormat "12" for 12-hour format, "24" for 24-hour format
- */
- public void onTimeFormatChanged(String timeFormat) {
- if (mClockPlugin != null) {
- mClockPlugin.onTimeFormatChanged(timeFormat);
- }
- }
-
- void updateColors(ColorExtractor.GradientColors colors) {
- mSupportsDarkText = colors.supportsDarkText();
- mColorPalette = colors.getColorPalette();
- if (mClockPlugin != null) {
- mClockPlugin.setColorPalette(mSupportsDarkText, mColorPalette);
- }
- }
-
public void dump(PrintWriter pw, String[] args) {
pw.println("KeyguardClockSwitch:");
- pw.println(" mClockPlugin: " + mClockPlugin);
- pw.println(" mClockFrame: " + mClockFrame);
+ pw.println(" mSmallClockFrame: " + mSmallClockFrame);
pw.println(" mLargeClockFrame: " + mLargeClockFrame);
pw.println(" mStatusArea: " + mStatusArea);
- pw.println(" mDarkAmount: " + mDarkAmount);
- pw.println(" mSupportsDarkText: " + mSupportsDarkText);
- pw.println(" mColorPalette: " + Arrays.toString(mColorPalette));
pw.println(" mDisplayedClockSize: " + mDisplayedClockSize);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index ad06e05..2165099 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -22,8 +22,6 @@
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
-import android.app.WallpaperManager;
-import android.content.res.Resources;
import android.database.ContentObserver;
import android.os.UserHandle;
import android.provider.Settings;
@@ -32,36 +30,30 @@
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
import androidx.annotation.NonNull;
-import com.android.internal.colorextraction.ColorExtractor;
-import com.android.keyguard.clock.ClockManager;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.plugins.Clock;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.shared.clocks.ClockRegistry;
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
-import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.ViewController;
import com.android.systemui.util.settings.SecureSettings;
import java.io.PrintWriter;
import java.util.Locale;
-import java.util.TimeZone;
import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -71,48 +63,23 @@
*/
public class KeyguardClockSwitchController extends ViewController<KeyguardClockSwitch>
implements Dumpable {
- private static final boolean CUSTOM_CLOCKS_ENABLED = true;
-
private final StatusBarStateController mStatusBarStateController;
- private final SysuiColorExtractor mColorExtractor;
- private final ClockManager mClockManager;
+ private final ClockRegistry mClockRegistry;
private final KeyguardSliceViewController mKeyguardSliceViewController;
private final NotificationIconAreaController mNotificationIconAreaController;
- private final BroadcastDispatcher mBroadcastDispatcher;
- private final BatteryController mBatteryController;
private final LockscreenSmartspaceController mSmartspaceController;
- private final Resources mResources;
private final SecureSettings mSecureSettings;
private final DumpManager mDumpManager;
+ private final ClockEventController mClockEventController;
- /**
- * Clock for both small and large sizes
- */
- private AnimatableClockController mClockViewController;
- private FrameLayout mClockFrame; // top aligned clock
- private AnimatableClockController mLargeClockViewController;
+ private FrameLayout mSmallClockFrame; // top aligned clock
private FrameLayout mLargeClockFrame; // centered clock
@KeyguardClockSwitch.ClockSize
private int mCurrentClockSize = SMALL;
- private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-
private int mKeyguardClockTopMargin = 0;
-
- /**
- * Listener for changes to the color palette.
- *
- * The color palette changes when the wallpaper is changed.
- */
- private final ColorExtractor.OnColorsChangedListener mColorsListener =
- (extractor, which) -> {
- if ((which & WallpaperManager.FLAG_LOCK) != 0) {
- mView.updateColors(getGradientColors());
- }
- };
-
- private final ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;
+ private final ClockRegistry.ClockChangeListener mClockChangedListener;
private ViewGroup mStatusArea;
// If set will replace keyguard_slice_view
@@ -121,9 +88,9 @@
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private boolean mOnlyClock = false;
- private Executor mUiExecutor;
+ private final Executor mUiExecutor;
private boolean mCanShowDoubleLineClock = true;
- private ContentObserver mDoubleLineClockObserver = new ContentObserver(null) {
+ private final ContentObserver mDoubleLineClockObserver = new ContentObserver(null) {
@Override
public void onChange(boolean change) {
updateDoubleLineClock();
@@ -144,34 +111,32 @@
public KeyguardClockSwitchController(
KeyguardClockSwitch keyguardClockSwitch,
StatusBarStateController statusBarStateController,
- SysuiColorExtractor colorExtractor,
- ClockManager clockManager,
+ ClockRegistry clockRegistry,
KeyguardSliceViewController keyguardSliceViewController,
NotificationIconAreaController notificationIconAreaController,
- BroadcastDispatcher broadcastDispatcher,
- BatteryController batteryController,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
LockscreenSmartspaceController smartspaceController,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
SecureSettings secureSettings,
@Main Executor uiExecutor,
- @Main Resources resources,
- DumpManager dumpManager) {
+ DumpManager dumpManager,
+ ClockEventController clockEventController,
+ FeatureFlags featureFlags) {
super(keyguardClockSwitch);
mStatusBarStateController = statusBarStateController;
- mColorExtractor = colorExtractor;
- mClockManager = clockManager;
+ mClockRegistry = clockRegistry;
mKeyguardSliceViewController = keyguardSliceViewController;
mNotificationIconAreaController = notificationIconAreaController;
- mBroadcastDispatcher = broadcastDispatcher;
- mBatteryController = batteryController;
- mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mSmartspaceController = smartspaceController;
- mResources = resources;
mSecureSettings = secureSettings;
mUiExecutor = uiExecutor;
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
mDumpManager = dumpManager;
+ mClockEventController = clockEventController;
+
+ mClockRegistry.setEnabled(featureFlags.isEnabled(Flags.LOCKSCREEN_CUSTOM_CLOCKS));
+ mClockChangedListener = () -> {
+ setClock(mClockRegistry.createCurrentClock());
+ };
}
/**
@@ -185,43 +150,21 @@
* Attach the controller to the view it relates to.
*/
@Override
- public void onInit() {
+ protected void onInit() {
mKeyguardSliceViewController.init();
- mClockFrame = mView.findViewById(R.id.lockscreen_clock_view);
+ mSmallClockFrame = mView.findViewById(R.id.lockscreen_clock_view);
mLargeClockFrame = mView.findViewById(R.id.lockscreen_clock_view_large);
- mClockViewController =
- new AnimatableClockController(
- mView.findViewById(R.id.animatable_clock_view),
- mStatusBarStateController,
- mBroadcastDispatcher,
- mBatteryController,
- mKeyguardUpdateMonitor,
- mResources);
- mClockViewController.init();
-
- mLargeClockViewController =
- new AnimatableClockController(
- mView.findViewById(R.id.animatable_clock_view_large),
- mStatusBarStateController,
- mBroadcastDispatcher,
- mBatteryController,
- mKeyguardUpdateMonitor,
- mResources);
- mLargeClockViewController.init();
-
mDumpManager.unregisterDumpable(getClass().toString()); // unregister previous clocks
mDumpManager.registerDumpable(getClass().toString(), this);
}
@Override
protected void onViewAttached() {
- if (CUSTOM_CLOCKS_ENABLED) {
- mClockManager.addOnClockChangedListener(mClockChangedListener);
- }
- mColorExtractor.addOnColorsChangedListener(mColorsListener);
- mView.updateColors(getGradientColors());
+ mClockRegistry.registerClockChangeListener(mClockChangedListener);
+ setClock(mClockRegistry.createCurrentClock());
+ mClockEventController.registerListeners();
mKeyguardClockTopMargin =
mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
@@ -244,7 +187,6 @@
ksv.setVisibility(View.GONE);
addSmartspaceView(ksvIndex);
- updateClockLayout();
}
mSecureSettings.registerContentObserverForUser(
@@ -266,11 +208,9 @@
@Override
protected void onViewDetached() {
- if (CUSTOM_CLOCKS_ENABLED) {
- mClockManager.removeOnClockChangedListener(mClockChangedListener);
- }
- mColorExtractor.removeOnColorsChangedListener(mColorsListener);
- mView.setClockPlugin(null, mStatusBarStateController.getState());
+ mClockRegistry.unregisterClockChangeListener(mClockChangedListener);
+ mClockEventController.unregisterListeners();
+ setClock(null);
mSecureSettings.unregisterContentObserver(mDoubleLineClockObserver);
@@ -309,18 +249,6 @@
mView.onDensityOrFontScaleChanged();
mKeyguardClockTopMargin =
mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
-
- updateClockLayout();
- }
-
- private void updateClockLayout() {
- int largeClockTopMargin = getContext().getResources().getDimensionPixelSize(
- R.dimen.keyguard_large_clock_top_margin)
- - (int) mLargeClockViewController.getBottom();
- RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(MATCH_PARENT,
- MATCH_PARENT);
- lp.topMargin = largeClockTopMargin;
- mLargeClockFrame.setLayoutParams(lp);
}
/**
@@ -334,46 +262,34 @@
mCurrentClockSize = clockSize;
+ Clock clock = getClock();
boolean appeared = mView.switchToClock(clockSize, animate);
- if (animate && appeared && clockSize == LARGE) {
- mLargeClockViewController.animateAppear();
- }
- }
-
- public void animateFoldToAod() {
- if (mClockViewController != null) {
- mClockViewController.animateFoldAppear();
- mLargeClockViewController.animateFoldAppear();
+ if (clock != null && animate && appeared && clockSize == LARGE) {
+ clock.getAnimations().enter();
}
}
/**
- * If we're presenting a custom clock of just the default one.
+ * Animates the clock view between folded and unfolded states
*/
- public boolean hasCustomClock() {
- return mView.hasCustomClock();
- }
-
- /**
- * Get the clock text size.
- */
- public float getClockTextSize() {
- return mView.getTextSize();
+ public void animateFoldToAod(float foldFraction) {
+ Clock clock = getClock();
+ if (clock != null) {
+ clock.getAnimations().fold(foldFraction);
+ }
}
/**
* Refresh clock. Called in response to TIME_TICK broadcasts.
*/
void refresh() {
- if (mClockViewController != null) {
- mClockViewController.refreshTime();
- mLargeClockViewController.refreshTime();
- }
if (mSmartspaceController != null) {
mSmartspaceController.requestSmartspaceUpdate();
}
-
- mView.refresh();
+ Clock clock = getClock();
+ if (clock != null) {
+ clock.getEvents().onTimeTick();
+ }
}
/**
@@ -385,7 +301,7 @@
void updatePosition(int x, float scale, AnimationProperties props, boolean animate) {
x = getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -x : x;
- PropertyAnimator.setProperty(mClockFrame, AnimatableProperty.TRANSLATION_X,
+ PropertyAnimator.setProperty(mSmallClockFrame, AnimatableProperty.TRANSLATION_X,
x, props, animate);
PropertyAnimator.setProperty(mLargeClockFrame, AnimatableProperty.SCALE_X,
scale, props, animate);
@@ -398,25 +314,39 @@
}
}
- void updateTimeZone(TimeZone timeZone) {
- mView.onTimeZoneChanged(timeZone);
- }
-
/**
* Get y-bottom position of the currently visible clock on the keyguard.
* We can't directly getBottom() because clock changes positions in AOD for burn-in
*/
int getClockBottom(int statusBarHeaderHeight) {
+ Clock clock = getClock();
+ if (clock == null) {
+ return 0;
+ }
+
if (mLargeClockFrame.getVisibility() == View.VISIBLE) {
- View clock = mLargeClockFrame.findViewById(
- com.android.systemui.R.id.animatable_clock_view_large);
int frameHeight = mLargeClockFrame.getHeight();
- int clockHeight = clock.getHeight();
+ int clockHeight = clock.getLargeClock().getHeight();
return frameHeight / 2 + clockHeight / 2;
} else {
- return mClockFrame.findViewById(
- com.android.systemui.R.id.animatable_clock_view).getHeight()
- + statusBarHeaderHeight + mKeyguardClockTopMargin;
+ int clockHeight = clock.getSmallClock().getHeight();
+ return clockHeight + statusBarHeaderHeight + mKeyguardClockTopMargin;
+ }
+ }
+
+ /**
+ * Get the height of the currently visible clock on the keyguard.
+ */
+ int getClockHeight() {
+ Clock clock = getClock();
+ if (clock == null) {
+ return 0;
+ }
+
+ if (mLargeClockFrame.getVisibility() == View.VISIBLE) {
+ return clock.getLargeClock().getHeight();
+ } else {
+ return clock.getSmallClock().getHeight();
}
}
@@ -431,12 +361,13 @@
mNotificationIconAreaController.setupAodIcons(nic);
}
- private void setClockPlugin(ClockPlugin plugin) {
- mView.setClockPlugin(plugin, mStatusBarStateController.getState());
+ private void setClock(Clock clock) {
+ mClockEventController.setClock(clock);
+ mView.setClock(clock, mStatusBarStateController.getState());
}
- private ColorExtractor.GradientColors getGradientColors() {
- return mColorExtractor.getColors(WallpaperManager.FLAG_LOCK);
+ private Clock getClock() {
+ return mClockEventController.getClock();
}
private int getCurrentLayoutDirection() {
@@ -458,8 +389,6 @@
* bounds during the unlock transition.
*/
private void setClipChildrenForUnlock(boolean clip) {
- mView.setClipChildren(clip);
-
if (mStatusArea != null) {
mStatusArea.setClipChildren(clip);
}
@@ -469,8 +398,10 @@
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("currentClockSizeLarge=" + (mCurrentClockSize == LARGE));
pw.println("mCanShowDoubleLineClock=" + mCanShowDoubleLineClock);
- mClockViewController.dump(pw);
- mLargeClockViewController.dump(pw);
+ Clock clock = getClock();
+ if (clock != null) {
+ clock.dump(pw);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 3517d22..d0baf3d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -89,7 +89,7 @@
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.UserSwitcherController.BaseUserAdapter;
-import com.android.systemui.statusbar.policy.UserSwitcherController.UserRecord;
+import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.util.settings.GlobalSettings;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index e1957c0..93175e1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -418,6 +418,7 @@
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, state);
getCurrentSecurityController().onResume(reason);
+ updateSideFpsVisibility();
}
mView.onResume(
mSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser()),
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index cb3172d..83e23bd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -17,14 +17,11 @@
package com.android.keyguard;
import android.content.Context;
-import android.graphics.Color;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridLayout;
-import androidx.core.graphics.ColorUtils;
-
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
@@ -46,7 +43,6 @@
private View mMediaHostContainer;
private float mDarkAmount = 0;
- private int mTextColor;
public KeyguardStatusView(Context context) {
this(context, null, 0);
@@ -71,7 +67,6 @@
}
mKeyguardSlice = findViewById(R.id.keyguard_slice_view);
- mTextColor = mClockView.getCurrentTextColor();
mMediaHostContainer = findViewById(R.id.status_view_media_container);
@@ -83,15 +78,12 @@
return;
}
mDarkAmount = darkAmount;
- mClockView.setDarkAmount(darkAmount);
CrossFadeHelper.fadeOut(mMediaHostContainer, darkAmount);
updateDark();
}
void updateDark() {
- final int blendedTextColor = ColorUtils.blendARGB(mTextColor, Color.WHITE, mDarkAmount);
mKeyguardSlice.setDarkAmount(mDarkAmount);
- mClockView.setTextColor(blendedTextColor);
}
/** Sets a translationY value on every child view except for the media view. */
@@ -113,7 +105,6 @@
public void dump(PrintWriter pw, String[] args) {
pw.println("KeyguardStatusView:");
pw.println(" mDarkAmount: " + mDarkAmount);
- pw.println(" mTextColor: " + Integer.toHexString(mTextColor));
if (mClockView != null) {
mClockView.dump(pw, args);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 014d082..c715a4e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -30,8 +30,6 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
-import java.util.TimeZone;
-
import javax.inject.Inject;
/**
@@ -96,13 +94,6 @@
}
/**
- * The amount we're in doze.
- */
- public void setDarkAmount(float darkAmount) {
- mView.setDarkAmount(darkAmount);
- }
-
- /**
* Set which clock should be displayed on the keyguard. The other one will be automatically
* hidden.
*/
@@ -114,16 +105,10 @@
* Performs fold to aod animation of the clocks (changes font weight from bold to thin).
* This animation is played when AOD is enabled and foldable device is fully folded, it is
* displayed on the outer screen
+ * @param foldFraction current fraction of fold animation complete
*/
- public void animateFoldToAod() {
- mKeyguardClockSwitchController.animateFoldToAod();
- }
-
- /**
- * If we're presenting a custom clock of just the default one.
- */
- public boolean hasCustomClock() {
- return mKeyguardClockSwitchController.hasCustomClock();
+ public void animateFoldToAod(float foldFraction) {
+ mKeyguardClockSwitchController.animateFoldToAod(foldFraction);
}
/**
@@ -143,24 +128,11 @@
}
/**
- * Set pivot x.
+ * Update the pivot position based on the parent view
*/
- public void setPivotX(float pivot) {
- mView.setPivotX(pivot);
- }
-
- /**
- * Set pivot y.
- */
- public void setPivotY(float pivot) {
- mView.setPivotY(pivot);
- }
-
- /**
- * Get the clock text size.
- */
- public float getClockTextSize() {
- return mKeyguardClockSwitchController.getClockTextSize();
+ public void updatePivot(float parentWidth, float parentHeight) {
+ mView.setPivotX(parentWidth / 2f);
+ mView.setPivotY(mKeyguardClockSwitchController.getClockHeight() / 2f);
}
/**
@@ -240,11 +212,6 @@
}
@Override
- public void onTimeZoneChanged(TimeZone timeZone) {
- mKeyguardClockSwitchController.updateTimeZone(timeZone);
- }
-
- @Override
public void onKeyguardVisibilityChanged(boolean showing) {
if (showing) {
if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 6976e3e..167d8af 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -206,7 +206,8 @@
*/
private static final int BIOMETRIC_STATE_CANCELLING_RESTARTING = 3;
- private static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
+ @VisibleForTesting
+ public static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
public static final int BIOMETRIC_HELP_FACE_NOT_RECOGNIZED = -2;
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconView.java b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
index fdde402..0a82968 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconView.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
@@ -19,7 +19,7 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
-import android.graphics.PointF;
+import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
@@ -54,7 +54,7 @@
private boolean mAod;
@NonNull private final RectF mSensorRect;
- @NonNull private PointF mLockIconCenter = new PointF(0f, 0f);
+ @NonNull private Point mLockIconCenter = new Point(0, 0);
private float mRadius;
private int mLockIconPadding;
@@ -126,7 +126,7 @@
* Set the location of the lock icon.
*/
@VisibleForTesting
- public void setCenterLocation(@NonNull PointF center, float radius, int drawablePadding) {
+ public void setCenterLocation(@NonNull Point center, float radius, int drawablePadding) {
mLockIconCenter = center;
mRadius = radius;
mLockIconPadding = drawablePadding;
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 06e1828..2a36676 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -26,7 +26,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.PointF;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.AnimatedStateListDrawable;
import android.hardware.biometrics.BiometricSourceType;
@@ -357,8 +357,9 @@
mAuthController.getUdfpsRadius(), scaledPadding);
} else {
mView.setCenterLocation(
- new PointF(mWidthPixels / 2,
- mHeightPixels - ((mBottomPaddingPx + sLockIconRadiusPx) * scaleFactor)),
+ new Point((int) mWidthPixels / 2,
+ (int) (mHeightPixels
+ - ((mBottomPaddingPx + sLockIconRadiusPx) * scaleFactor))),
sLockIconRadiusPx * scaleFactor, scaledPadding);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java b/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java
index 43b3929..df65bcf 100644
--- a/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java
@@ -16,6 +16,7 @@
package com.android.systemui;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -34,12 +35,12 @@
@SysUISingleton
public class ActivityIntentHelper {
- private final Context mContext;
+ private final PackageManager mPm;
@Inject
public ActivityIntentHelper(Context context) {
// TODO: inject a package manager, not a context.
- mContext = context;
+ mPm = context.getPackageManager();
}
/**
@@ -57,6 +58,15 @@
}
/**
+ * @see #wouldLaunchResolverActivity(Intent, int)
+ */
+ public boolean wouldPendingLaunchResolverActivity(PendingIntent intent, int currentUserId) {
+ ActivityInfo targetActivityInfo = getPendingTargetActivityInfo(intent, currentUserId,
+ false /* onlyDirectBootAware */);
+ return targetActivityInfo == null;
+ }
+
+ /**
* Returns info about the target Activity of a given intent, or null if the intent does not
* resolve to a specific component meeting the requirements.
*
@@ -68,19 +78,45 @@
*/
public ActivityInfo getTargetActivityInfo(Intent intent, int currentUserId,
boolean onlyDirectBootAware) {
- PackageManager packageManager = mContext.getPackageManager();
- int flags = PackageManager.MATCH_DEFAULT_ONLY;
+ int flags = PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA;
if (!onlyDirectBootAware) {
flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
}
- final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
+ final List<ResolveInfo> appList = mPm.queryIntentActivitiesAsUser(
intent, flags, currentUserId);
if (appList.size() == 0) {
return null;
}
- ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
- flags | PackageManager.GET_META_DATA, currentUserId);
+ if (appList.size() == 1) {
+ return appList.get(0).activityInfo;
+ }
+ ResolveInfo resolved = mPm.resolveActivityAsUser(intent, flags, currentUserId);
+ if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) {
+ return null;
+ } else {
+ return resolved.activityInfo;
+ }
+ }
+
+ /**
+ * @see #getTargetActivityInfo(Intent, int, boolean)
+ */
+ public ActivityInfo getPendingTargetActivityInfo(PendingIntent intent, int currentUserId,
+ boolean onlyDirectBootAware) {
+ int flags = PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA;
+ if (!onlyDirectBootAware) {
+ flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+ }
+ final List<ResolveInfo> appList = intent.queryIntentComponents(flags);
+ if (appList.size() == 0) {
+ return null;
+ }
+ if (appList.size() == 1) {
+ return appList.get(0).activityInfo;
+ }
+ ResolveInfo resolved = mPm.resolveActivityAsUser(intent.getIntent(), flags, currentUserId);
if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) {
return null;
} else {
@@ -104,6 +140,17 @@
}
/**
+ * @see #wouldShowOverLockscreen(Intent, int)
+ */
+ public boolean wouldPendingShowOverLockscreen(PendingIntent intent, int currentUserId) {
+ ActivityInfo targetActivityInfo = getPendingTargetActivityInfo(intent,
+ currentUserId, false /* onlyDirectBootAware */);
+ return targetActivityInfo != null
+ && (targetActivityInfo.flags & (ActivityInfo.FLAG_SHOW_WHEN_LOCKED
+ | ActivityInfo.FLAG_SHOW_FOR_ALL_USERS)) > 0;
+ }
+
+ /**
* Determines if sending the given intent would result in starting an Intent resolver activity,
* instead of resolving to a specific component.
*
diff --git a/packages/SystemUI/src/com/android/systemui/ChooserSelector.kt b/packages/SystemUI/src/com/android/systemui/ChooserSelector.kt
new file mode 100644
index 0000000..109be40
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ChooserSelector.kt
@@ -0,0 +1,67 @@
+package com.android.systemui
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.PackageManager
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.FlagListenable
+import com.android.systemui.flags.Flags
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlinx.coroutines.withContext
+
+@SysUISingleton
+class ChooserSelector @Inject constructor(
+ context: Context,
+ private val featureFlags: FeatureFlags,
+ @Application private val coroutineScope: CoroutineScope,
+ @Background private val bgDispatcher: CoroutineDispatcher
+) : CoreStartable(context) {
+
+ private val packageManager = context.packageManager
+ private val chooserComponent = ComponentName.unflattenFromString(
+ context.resources.getString(ChooserSelectorResourceHelper.CONFIG_CHOOSER_ACTIVITY))
+
+ override fun start() {
+ coroutineScope.launch {
+ val listener = FlagListenable.Listener { event ->
+ if (event.flagId == Flags.CHOOSER_UNBUNDLED.id) {
+ launch { updateUnbundledChooserEnabled() }
+ event.requestNoRestart()
+ }
+ }
+ featureFlags.addListener(Flags.CHOOSER_UNBUNDLED, listener)
+ updateUnbundledChooserEnabled()
+
+ awaitCancellationAndThen { featureFlags.removeListener(listener) }
+ }
+ }
+
+ private suspend fun updateUnbundledChooserEnabled() {
+ setUnbundledChooserEnabled(withContext(bgDispatcher) {
+ featureFlags.isEnabled(Flags.CHOOSER_UNBUNDLED)
+ })
+ }
+
+ private fun setUnbundledChooserEnabled(enabled: Boolean) {
+ val newState = if (enabled) {
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ } else {
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+ }
+ packageManager.setComponentEnabledSetting(chooserComponent, newState, /* flags = */ 0)
+ }
+
+ suspend inline fun awaitCancellation(): Nothing = suspendCancellableCoroutine { }
+ suspend inline fun awaitCancellationAndThen(block: () -> Unit): Nothing = try {
+ awaitCancellation()
+ } finally {
+ block()
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java b/packages/SystemUI/src/com/android/systemui/ChooserSelectorResourceHelper.java
similarity index 61%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
copy to packages/SystemUI/src/com/android/systemui/ChooserSelectorResourceHelper.java
index e62a63a..7a2de7b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/ChooserSelectorResourceHelper.java
@@ -14,18 +14,18 @@
* limitations under the License.
*/
-package com.android.wm.shell.desktopmode;
+package com.android.systemui;
-import android.os.SystemProperties;
+import androidx.annotation.StringRes;
-/**
- * Constants for desktop mode feature
- */
-public class DesktopModeConstants {
+import com.android.internal.R;
- /**
- * Flag to indicate whether desktop mode is available on the device
- */
- public static final boolean IS_FEATURE_ENABLED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode", false);
+/** Helper class for referencing resources */
+class ChooserSelectorResourceHelper {
+
+ private ChooserSelectorResourceHelper() {
+ }
+
+ @StringRes
+ static final int CONFIG_CHOOSER_ACTIVITY = R.string.config_chooserActivity;
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 614a87f..7fc8123 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -85,10 +85,6 @@
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.events.PrivacyDotViewController;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
-import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
@@ -303,7 +299,6 @@
@Inject Lazy<IStatusBarService> mIStatusBarService;
@Inject Lazy<DisplayMetrics> mDisplayMetrics;
@Inject Lazy<LockscreenGestureLogger> mLockscreenGestureLogger;
- @Inject Lazy<KeyguardEnvironment> mKeyguardEnvironment;
@Inject Lazy<ShadeController> mShadeController;
@Inject Lazy<NotificationRemoteInputManager.Callback> mNotificationRemoteInputManagerCallback;
@Inject Lazy<AppOpsController> mAppOpsController;
@@ -311,8 +306,6 @@
@Inject Lazy<AccessibilityFloatingMenuController> mAccessibilityFloatingMenuController;
@Inject Lazy<StatusBarStateController> mStatusBarStateController;
@Inject Lazy<NotificationLockscreenUserManager> mNotificationLockscreenUserManager;
- @Inject Lazy<NotificationGroupManagerLegacy> mNotificationGroupManager;
- @Inject Lazy<VisualStabilityManager> mVisualStabilityManager;
@Inject Lazy<NotificationGutsManager> mNotificationGutsManager;
@Inject Lazy<NotificationMediaManager> mNotificationMediaManager;
@Inject Lazy<NotificationRemoteInputManager> mNotificationRemoteInputManager;
@@ -322,10 +315,8 @@
@Inject Lazy<KeyguardDismissUtil> mKeyguardDismissUtil;
@Inject Lazy<SmartReplyController> mSmartReplyController;
@Inject Lazy<RemoteInputQuickSettingsDisabler> mRemoteInputQuickSettingsDisabler;
- @Inject Lazy<NotificationEntryManager> mNotificationEntryManager;
@Inject Lazy<SensorPrivacyManager> mSensorPrivacyManager;
@Inject Lazy<AutoHideController> mAutoHideController;
- @Inject Lazy<ForegroundServiceNotificationListener> mForegroundServiceNotificationListener;
@Inject Lazy<PrivacyItemController> mPrivacyItemController;
@Inject @Background Lazy<Looper> mBgLooper;
@Inject @Background Lazy<Handler> mBgHandler;
@@ -507,7 +498,6 @@
mProviders.put(LockscreenGestureLogger.class, mLockscreenGestureLogger::get);
- mProviders.put(KeyguardEnvironment.class, mKeyguardEnvironment::get);
mProviders.put(ShadeController.class, mShadeController::get);
mProviders.put(NotificationRemoteInputManager.Callback.class,
@@ -523,8 +513,6 @@
mProviders.put(StatusBarStateController.class, mStatusBarStateController::get);
mProviders.put(NotificationLockscreenUserManager.class,
mNotificationLockscreenUserManager::get);
- mProviders.put(VisualStabilityManager.class, mVisualStabilityManager::get);
- mProviders.put(NotificationGroupManagerLegacy.class, mNotificationGroupManager::get);
mProviders.put(NotificationMediaManager.class, mNotificationMediaManager::get);
mProviders.put(NotificationGutsManager.class, mNotificationGutsManager::get);
mProviders.put(NotificationRemoteInputManager.class,
@@ -536,9 +524,6 @@
mProviders.put(SmartReplyController.class, mSmartReplyController::get);
mProviders.put(RemoteInputQuickSettingsDisabler.class,
mRemoteInputQuickSettingsDisabler::get);
- mProviders.put(NotificationEntryManager.class, mNotificationEntryManager::get);
- mProviders.put(ForegroundServiceNotificationListener.class,
- mForegroundServiceNotificationListener::get);
mProviders.put(ClockManager.class, mClockManager::get);
mProviders.put(PrivacyItemController.class, mPrivacyItemController::get);
mProviders.put(ActivityManagerWrapper.class, mActivityManagerWrapper::get);
diff --git a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
index d2c229b..a3351e1 100644
--- a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
+++ b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
@@ -47,7 +47,8 @@
open class DisplayCutoutBaseView : View, RegionInterceptableView {
private var shouldDrawCutout: Boolean = DisplayCutout.getFillBuiltInDisplayCutout(
- context.resources, context.display?.uniqueId)
+ context.resources, context.display?.uniqueId
+ )
private var displayUniqueId: String? = null
private var displayMode: Display.Mode? = null
protected val location = IntArray(2)
@@ -74,8 +75,8 @@
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
- constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
- : super(context, attrs, defStyleAttr)
+ constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
+ super(context, attrs, defStyleAttr)
override fun onAttachedToWindow() {
super.onAttachedToWindow()
@@ -85,7 +86,7 @@
onUpdate()
}
- fun onDisplayChanged(displayId: Int) {
+ fun onDisplayChanged(newDisplayUniqueId: String?) {
val oldMode: Display.Mode? = displayMode
val display: Display? = context.display
displayMode = display?.mode
@@ -93,7 +94,8 @@
if (displayUniqueId != display?.uniqueId) {
displayUniqueId = display?.uniqueId
shouldDrawCutout = DisplayCutout.getFillBuiltInDisplayCutout(
- context.resources, displayUniqueId)
+ context.resources, displayUniqueId
+ )
}
// Skip if display mode or cutout hasn't changed.
@@ -101,7 +103,7 @@
display?.cutout == displayInfo.displayCutout) {
return
}
- if (displayId == display?.displayId) {
+ if (newDisplayUniqueId == display?.uniqueId) {
updateCutout()
updateProtectionBoundingPath()
onUpdate()
@@ -147,8 +149,9 @@
cutoutBounds.translate(-location[0], -location[1])
// Intersect with window's frame
- cutoutBounds.op(rootView.left, rootView.top, rootView.right, rootView.bottom,
- Region.Op.INTERSECT)
+ cutoutBounds.op(
+ rootView.left, rootView.top, rootView.right, rootView.bottom, Region.Op.INTERSECT
+ )
return cutoutBounds
}
@@ -171,9 +174,12 @@
protected open fun drawCutoutProtection(canvas: Canvas) {
if (cameraProtectionProgress > HIDDEN_CAMERA_PROTECTION_SCALE &&
- !protectionRect.isEmpty) {
- canvas.scale(cameraProtectionProgress, cameraProtectionProgress,
- protectionRect.centerX(), protectionRect.centerY())
+ !protectionRect.isEmpty
+ ) {
+ canvas.scale(
+ cameraProtectionProgress, cameraProtectionProgress, protectionRect.centerX(),
+ protectionRect.centerY()
+ )
canvas.drawPath(protectionPath, paint)
}
}
@@ -205,14 +211,17 @@
requestLayout()
}
cameraProtectionAnimator?.cancel()
- cameraProtectionAnimator = ValueAnimator.ofFloat(cameraProtectionProgress,
- if (showProtection) 1.0f else HIDDEN_CAMERA_PROTECTION_SCALE).setDuration(750)
+ cameraProtectionAnimator = ValueAnimator.ofFloat(
+ cameraProtectionProgress,
+ if (showProtection) 1.0f else HIDDEN_CAMERA_PROTECTION_SCALE
+ ).setDuration(750)
cameraProtectionAnimator?.interpolator = Interpolators.DECELERATE_QUINT
- cameraProtectionAnimator?.addUpdateListener(ValueAnimator.AnimatorUpdateListener {
- animation: ValueAnimator ->
- cameraProtectionProgress = animation.animatedValue as Float
- invalidate()
- })
+ cameraProtectionAnimator?.addUpdateListener(
+ ValueAnimator.AnimatorUpdateListener { animation: ValueAnimator ->
+ cameraProtectionProgress = animation.animatedValue as Float
+ invalidate()
+ }
+ )
cameraProtectionAnimator?.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
cameraProtectionAnimator = null
@@ -245,8 +254,10 @@
// Apply rotation.
val lw: Int = displayInfo.logicalWidth
val lh: Int = displayInfo.logicalHeight
- val flipped = (displayInfo.rotation == Surface.ROTATION_90 ||
- displayInfo.rotation == Surface.ROTATION_270)
+ val flipped = (
+ displayInfo.rotation == Surface.ROTATION_90 ||
+ displayInfo.rotation == Surface.ROTATION_270
+ )
val dw = if (flipped) lh else lw
val dh = if (flipped) lw else lh
transformPhysicalToLogicalCoordinates(displayInfo.rotation, dw, dh, m)
@@ -275,7 +286,7 @@
// We purposely ignore refresh rate and id changes here, because we don't need to
// invalidate for those, and they can trigger the refresh rate to increase
return oldMode?.physicalHeight != newMode?.physicalHeight ||
- oldMode?.physicalWidth != newMode?.physicalWidth
+ oldMode?.physicalWidth != newMode?.physicalWidth
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index 04e26d3..a1a3b72 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -23,14 +23,10 @@
import android.service.notification.StatusBarNotification;
import android.util.Log;
-import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.statusbar.notification.NotificationEntryListener;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
-import com.android.systemui.util.time.SystemClock;
import javax.inject.Inject;
@@ -43,42 +39,20 @@
private final Context mContext;
private final ForegroundServiceController mForegroundServiceController;
- private final NotificationEntryManager mEntryManager;
+ private final NotifPipeline mNotifPipeline;
@Inject
public ForegroundServiceNotificationListener(Context context,
ForegroundServiceController foregroundServiceController,
- NotificationEntryManager notificationEntryManager,
- NotifPipeline notifPipeline,
- SystemClock systemClock) {
+ NotifPipeline notifPipeline) {
mContext = context;
mForegroundServiceController = foregroundServiceController;
+ mNotifPipeline = notifPipeline;
+ }
- // TODO: (b/145659174) remove mEntryManager when moving to NewNotifPipeline. Replaced by
- // ForegroundCoordinator
- mEntryManager = notificationEntryManager;
- mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
- @Override
- public void onPendingEntryAdded(NotificationEntry entry) {
- addNotification(entry, entry.getImportance());
- }
-
- @Override
- public void onPreEntryUpdated(NotificationEntry entry) {
- updateNotification(entry, entry.getImportance());
- }
-
- @Override
- public void onEntryRemoved(
- NotificationEntry entry,
- NotificationVisibility visibility,
- boolean removedByUser,
- int reason) {
- removeNotification(entry.getSbn());
- }
- });
-
- notifPipeline.addCollectionListener(new NotifCollectionListener() {
+ /** Initializes this listener by connecting it to the notification pipeline. */
+ public void init() {
+ mNotifPipeline.addCollectionListener(new NotifCollectionListener() {
@Override
public void onEntryAdded(NotificationEntry entry) {
addNotification(entry, entry.getImportance());
diff --git a/packages/SystemUI/src/com/android/systemui/GuestSessionNotification.java b/packages/SystemUI/src/com/android/systemui/GuestSessionNotification.java
index b0eaab9..fa9a83e 100644
--- a/packages/SystemUI/src/com/android/systemui/GuestSessionNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/GuestSessionNotification.java
@@ -25,7 +25,6 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
-import android.util.FeatureFlagUtils;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.systemui.util.NotificationChannels;
@@ -59,10 +58,8 @@
}
void createPersistentNotification(UserInfo userInfo, boolean isGuestFirstLogin) {
- if (!FeatureFlagUtils.isEnabled(mContext,
- FeatureFlagUtils.SETTINGS_GUEST_MODE_UX_CHANGES)
- || !userInfo.isGuest()) {
- // we create a persistent notification only if enabled and only for guests
+ if (!userInfo.isGuest()) {
+ // we create a persistent notification only for guests
return;
}
String contentText;
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index edcaf49..2e13903 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -32,7 +32,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
-import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
@@ -73,6 +72,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.decor.CutoutDecorProviderFactory;
import com.android.systemui.decor.DecorProvider;
import com.android.systemui.decor.DecorProviderFactory;
import com.android.systemui.decor.DecorProviderKt;
@@ -92,10 +92,8 @@
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
import java.util.Objects;
-import java.util.Set;
import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -121,6 +119,13 @@
private static final boolean VERBOSE = false;
static final boolean DEBUG_COLOR = DEBUG_SCREENSHOT_ROUNDED_CORNERS;
+ private static final int[] DISPLAY_CUTOUT_IDS = {
+ R.id.display_cutout,
+ R.id.display_cutout_left,
+ R.id.display_cutout_right,
+ R.id.display_cutout_bottom
+ };
+
private DisplayManager mDisplayManager;
@VisibleForTesting
protected boolean mIsRegistered;
@@ -142,13 +147,11 @@
protected RoundedCornerResDelegate mRoundedCornerResDelegate;
@VisibleForTesting
protected DecorProviderFactory mRoundedCornerFactory;
+ private CutoutDecorProviderFactory mCutoutFactory;
private int mProviderRefreshToken = 0;
@VisibleForTesting
protected OverlayWindow[] mOverlays = null;
@VisibleForTesting
- @Nullable
- DisplayCutoutView[] mCutoutViews;
- @VisibleForTesting
ViewGroup mScreenDecorHwcWindow;
@VisibleForTesting
ScreenDecorHwcLayer mScreenDecorHwcLayer;
@@ -190,18 +193,19 @@
return;
}
- if (mCutoutViews == null) {
- Log.w(TAG, "DisplayCutoutView not initialized onApplyCameraProtection");
- return;
- }
-
- // Show the extra protection around the front facing camera if necessary
- for (DisplayCutoutView dcv : mCutoutViews) {
- // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile
- if (dcv != null) {
- dcv.setProtection(protectionPath, bounds);
- dcv.enableShowProtection(true);
+ int setProtectionCnt = 0;
+ for (int id: DISPLAY_CUTOUT_IDS) {
+ final View view = getOverlayView(id);
+ if (!(view instanceof DisplayCutoutView)) {
+ continue;
}
+ ++setProtectionCnt;
+ final DisplayCutoutView dcv = (DisplayCutoutView) view;
+ dcv.setProtection(protectionPath, bounds);
+ dcv.enableShowProtection(true);
+ }
+ if (setProtectionCnt == 0) {
+ Log.e(TAG, "CutoutView not initialized showCameraProtection");
}
}
@@ -222,16 +226,17 @@
return;
}
- if (mCutoutViews == null) {
- Log.w(TAG, "DisplayCutoutView not initialized onHideCameraProtection");
- return;
- }
- // Go back to the regular anti-aliasing
- for (DisplayCutoutView dcv : mCutoutViews) {
- // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile
- if (dcv != null) {
- dcv.enableShowProtection(false);
+ int setProtectionCnt = 0;
+ for (int id: DISPLAY_CUTOUT_IDS) {
+ final View view = getOverlayView(id);
+ if (!(view instanceof DisplayCutoutView)) {
+ continue;
}
+ ++setProtectionCnt;
+ ((DisplayCutoutView) view).enableShowProtection(false);
+ }
+ if (setProtectionCnt == 0) {
+ Log.e(TAG, "CutoutView not initialized hideCameraProtection");
}
}
@@ -338,6 +343,7 @@
decorProviders.addAll(mFaceScanningFactory.getProviders());
if (!hasHwLayer) {
decorProviders.addAll(mRoundedCornerFactory.getProviders());
+ decorProviders.addAll(mCutoutFactory.getProviders());
}
return decorProviders;
}
@@ -382,6 +388,7 @@
mRoundedCornerResDelegate.setPhysicalPixelDisplaySizeRatio(
getPhysicalPixelDisplaySizeRatio());
mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate);
+ mCutoutFactory = getCutoutFactory();
mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
updateHwLayerRoundedCornerDrawable();
setupDecorations();
@@ -448,6 +455,7 @@
}
}
+ boolean needToUpdateProviderViews = false;
final String newUniqueId = mDisplayInfo.uniqueId;
if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
mDisplayUniqueId = newUniqueId;
@@ -470,8 +478,7 @@
updateHwLayerRoundedCornerDrawable();
updateHwLayerRoundedCornerExistAndSize();
}
-
- updateOverlayProviderViews();
+ needToUpdateProviderViews = true;
}
final float newRatio = getPhysicalPixelDisplaySizeRatio();
@@ -480,28 +487,23 @@
if (mScreenDecorHwcLayer != null) {
updateHwLayerRoundedCornerExistAndSize();
}
- updateOverlayProviderViews();
+ needToUpdateProviderViews = true;
}
- if (mCutoutViews != null) {
- final int size = mCutoutViews.length;
- for (int i = 0; i < size; i++) {
- final DisplayCutoutView cutoutView = mCutoutViews[i];
- if (cutoutView == null) {
- continue;
- }
- cutoutView.onDisplayChanged(displayId);
- }
- }
-
- DisplayCutoutView overlay = (DisplayCutoutView) getOverlayView(mFaceScanningViewId);
- if (overlay != null) {
- // handle display resolution changes
- overlay.onDisplayChanged(displayId);
+ if (needToUpdateProviderViews) {
+ updateOverlayProviderViews(null);
+ } else {
+ updateOverlayProviderViews(new Integer[] {
+ mFaceScanningViewId,
+ R.id.display_cutout,
+ R.id.display_cutout_left,
+ R.id.display_cutout_right,
+ R.id.display_cutout_bottom,
+ });
}
if (mScreenDecorHwcLayer != null) {
- mScreenDecorHwcLayer.onDisplayChanged(displayId);
+ mScreenDecorHwcLayer.onDisplayChanged(newUniqueId);
}
}
};
@@ -510,8 +512,9 @@
updateConfiguration();
}
+ @VisibleForTesting
@Nullable
- private View getOverlayView(@IdRes int id) {
+ View getOverlayView(@IdRes int id) {
if (mOverlays == null) {
return null;
}
@@ -568,18 +571,18 @@
removeHwcOverlay();
}
- final DisplayCutout cutout = getCutout();
+ boolean[] hasCreatedOverlay = new boolean[BOUNDS_POSITION_LENGTH];
final boolean shouldOptimizeVisibility = shouldOptimizeVisibility();
+ Integer bound;
+ while ((bound = DecorProviderKt.getProperBound(decorProviders)) != null) {
+ hasCreatedOverlay[bound] = true;
+ Pair<List<DecorProvider>, List<DecorProvider>> pair =
+ DecorProviderKt.partitionAlignedBound(decorProviders, bound);
+ decorProviders = pair.getSecond();
+ createOverlay(bound, pair.getFirst(), shouldOptimizeVisibility);
+ }
for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
- if (shouldShowSwLayerCutout(i, cutout)
- || shouldShowSwLayerFaceScan(i, cutout)
- || shouldShowSwLayerRoundedCorner(i, cutout)
- || shouldShowSwLayerPrivacyDot(i, cutout)) {
- Pair<List<DecorProvider>, List<DecorProvider>> pair =
- DecorProviderKt.partitionAlignedBound(decorProviders, i);
- decorProviders = pair.getSecond();
- createOverlay(i, pair.getFirst(), shouldOptimizeVisibility);
- } else {
+ if (!hasCreatedOverlay[i]) {
removeOverlay(i);
}
}
@@ -642,9 +645,10 @@
}
}
- @VisibleForTesting
- DisplayCutout getCutout() {
- return mContext.getDisplay().getCutout();
+ // For unit test to override
+ protected CutoutDecorProviderFactory getCutoutFactory() {
+ return new CutoutDecorProviderFactory(mContext.getResources(),
+ mContext.getDisplay());
}
@VisibleForTesting
@@ -734,16 +738,6 @@
overlayView.setAlpha(0);
overlayView.setForceDarkAllowed(false);
- // Only show cutout in mOverlays when hwc doesn't support screen decoration
- if (mHwcScreenDecorationSupport == null) {
- if (mCutoutViews == null) {
- mCutoutViews = new DisplayCutoutView[BOUNDS_POSITION_LENGTH];
- }
- mCutoutViews[pos] = new DisplayCutoutView(mContext, pos);
- overlayView.addView(mCutoutViews[pos]);
- mCutoutViews[pos].updateRotation(mRotation);
- }
-
mWindowManager.addView(overlayView, getWindowLayoutParams(pos));
overlayView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@@ -804,7 +798,7 @@
return;
}
removeOverlayView(provider.getViewId());
- overlay.addDecorProvider(provider, mRotation);
+ overlay.addDecorProvider(provider, mRotation, mTintColor);
});
}
// Use visibility of privacy dot views & face scanning view to determine the overlay's
@@ -923,6 +917,7 @@
}
private void setupCameraListener() {
+ // TODO(b/238143614) Support dual screen camera protection
Resources res = mContext.getResources();
boolean enabled = res.getBoolean(R.bool.config_enableDisplayCutoutProtection);
if (enabled) {
@@ -951,45 +946,17 @@
mTintColor = Color.RED;
}
- if (mOverlays == null) {
- return;
- }
-
- // When the hwc supports screen decorations, the layer will use the A8 color mode which
- // won't be affected by the color inversion. If the composition goes the client composition
- // route, the color inversion will be handled by the RenderEngine.
- final Set<Integer> viewsMayNeedColorUpdate = new HashSet<>();
- if (mHwcScreenDecorationSupport == null) {
- ColorStateList tintList = ColorStateList.valueOf(mTintColor);
- mRoundedCornerResDelegate.setColorTintList(tintList);
- viewsMayNeedColorUpdate.add(R.id.rounded_corner_top_left);
- viewsMayNeedColorUpdate.add(R.id.rounded_corner_top_right);
- viewsMayNeedColorUpdate.add(R.id.rounded_corner_bottom_left);
- viewsMayNeedColorUpdate.add(R.id.rounded_corner_bottom_right);
- viewsMayNeedColorUpdate.add(R.id.display_cutout);
- }
- if (getOverlayView(mFaceScanningViewId) != null) {
- viewsMayNeedColorUpdate.add(mFaceScanningViewId);
- }
- final Integer[] views = new Integer[viewsMayNeedColorUpdate.size()];
- viewsMayNeedColorUpdate.toArray(views);
- for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
- if (mOverlays[i] == null) {
- continue;
- }
- final ViewGroup overlayView = mOverlays[i].getRootView();
- final int size = overlayView.getChildCount();
- View child;
- for (int j = 0; j < size; j++) {
- child = overlayView.getChildAt(j);
- if (viewsMayNeedColorUpdate.contains(child.getId())
- && child instanceof DisplayCutoutView) {
- ((DisplayCutoutView) child).setColor(mTintColor);
- }
- }
- mOverlays[i].onReloadResAndMeasure(views, mProviderRefreshToken,
- mRotation, mDisplayUniqueId);
- }
+ updateOverlayProviderViews(new Integer[] {
+ mFaceScanningViewId,
+ R.id.display_cutout,
+ R.id.display_cutout_left,
+ R.id.display_cutout_right,
+ R.id.display_cutout_bottom,
+ R.id.rounded_corner_top_left,
+ R.id.rounded_corner_top_right,
+ R.id.rounded_corner_bottom_left,
+ R.id.rounded_corner_bottom_right
+ });
}
@VisibleForTesting
@@ -1109,18 +1076,9 @@
updateHwLayerRoundedCornerDrawable();
}
updateLayoutParams();
- // update cutout view rotation
- if (mCutoutViews != null) {
- for (final DisplayCutoutView cutoutView: mCutoutViews) {
- if (cutoutView == null) {
- continue;
- }
- cutoutView.updateRotation(mRotation);
- }
- }
// update all provider views inside overlay
- updateOverlayProviderViews();
+ updateOverlayProviderViews(null);
}
FaceScanningOverlay faceScanningOverlay =
@@ -1136,46 +1094,6 @@
return mRoundedCornerFactory.getHasProviders();
}
- private boolean isDefaultShownOverlayPos(@BoundsPosition int pos,
- @Nullable DisplayCutout cutout) {
- // for cutout is null or cutout with only waterfall.
- final boolean emptyBoundsOrWaterfall = cutout == null || cutout.isBoundsEmpty();
- // Shows rounded corner on left and right overlays only when there is no top or bottom
- // cutout.
- final int rotatedTop = getBoundPositionFromRotation(BOUNDS_POSITION_TOP, mRotation);
- final int rotatedBottom = getBoundPositionFromRotation(BOUNDS_POSITION_BOTTOM, mRotation);
- if (emptyBoundsOrWaterfall || !cutout.getBoundingRectsAll()[rotatedTop].isEmpty()
- || !cutout.getBoundingRectsAll()[rotatedBottom].isEmpty()) {
- return pos == BOUNDS_POSITION_TOP || pos == BOUNDS_POSITION_BOTTOM;
- } else {
- return pos == BOUNDS_POSITION_LEFT || pos == BOUNDS_POSITION_RIGHT;
- }
- }
-
- private boolean shouldShowSwLayerRoundedCorner(@BoundsPosition int pos,
- @Nullable DisplayCutout cutout) {
- return hasRoundedCorners() && isDefaultShownOverlayPos(pos, cutout)
- && mHwcScreenDecorationSupport == null;
- }
-
- private boolean shouldShowSwLayerPrivacyDot(@BoundsPosition int pos,
- @Nullable DisplayCutout cutout) {
- return isPrivacyDotEnabled() && isDefaultShownOverlayPos(pos, cutout);
- }
-
- private boolean shouldShowSwLayerFaceScan(@BoundsPosition int pos,
- @Nullable DisplayCutout cutout) {
- return mFaceScanningFactory.getHasProviders() && isDefaultShownOverlayPos(pos, cutout);
- }
-
- private boolean shouldShowSwLayerCutout(@BoundsPosition int pos,
- @Nullable DisplayCutout cutout) {
- final Rect[] bounds = cutout == null ? null : cutout.getBoundingRectsAll();
- final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
- return (bounds != null && !bounds[rotatedPos].isEmpty()
- && mHwcScreenDecorationSupport == null);
- }
-
private boolean shouldOptimizeVisibility() {
return (isPrivacyDotEnabled() || mFaceScanningFactory.getHasProviders())
&& (mHwcScreenDecorationSupport != null
@@ -1184,7 +1102,7 @@
}
private boolean shouldDrawCutout() {
- return shouldDrawCutout(mContext);
+ return mCutoutFactory.getHasProviders();
}
static boolean shouldDrawCutout(Context context) {
@@ -1192,7 +1110,7 @@
context.getResources(), context.getDisplay().getUniqueId());
}
- private void updateOverlayProviderViews() {
+ private void updateOverlayProviderViews(@Nullable Integer[] filterIds) {
if (mOverlays == null) {
return;
}
@@ -1201,7 +1119,8 @@
if (overlay == null) {
continue;
}
- overlay.onReloadResAndMeasure(null, mProviderRefreshToken, mRotation, mDisplayUniqueId);
+ overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation, mTintColor,
+ mDisplayUniqueId);
}
}
@@ -1240,19 +1159,12 @@
} catch (NumberFormatException e) {
mRoundedCornerResDelegate.setTuningSizeFactor(null);
}
- Integer[] filterIds = {
+ updateOverlayProviderViews(new Integer[] {
R.id.rounded_corner_top_left,
R.id.rounded_corner_top_right,
R.id.rounded_corner_bottom_left,
R.id.rounded_corner_bottom_right
- };
- for (final OverlayWindow overlay: mOverlays) {
- if (overlay == null) {
- continue;
- }
- overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation,
- mDisplayUniqueId);
- }
+ });
updateHwLayerRoundedCornerExistAndSize();
});
}
@@ -1306,7 +1218,6 @@
paint.setColor(mColor);
paint.setStyle(Paint.Style.FILL);
- setId(R.id.display_cutout);
if (DEBUG) {
getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG,
getWindowTitleByPos(pos) + " drawn in rot " + mRotation));
@@ -1314,6 +1225,9 @@
}
public void setColor(int color) {
+ if (color == mColor) {
+ return;
+ }
mColor = color;
paint.setColor(mColor);
invalidate();
@@ -1321,6 +1235,12 @@
@Override
public void updateRotation(int rotation) {
+ // updateRotation() is called inside CutoutDecorProviderImpl::onReloadResAndMeasure()
+ // during onDisplayChanged. In order to prevent reloading cutout info in super class,
+ // check mRotation at first
+ if (rotation == mRotation) {
+ return;
+ }
mRotation = rotation;
super.updateRotation(rotation);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
index 589ec0e..9b5f54a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
@@ -92,7 +92,7 @@
STATE_ERROR -> true
STATE_AUTHENTICATING_ANIMATING_IN,
STATE_AUTHENTICATING -> oldState == STATE_ERROR || oldState == STATE_HELP
- STATE_AUTHENTICATED -> false
+ STATE_AUTHENTICATED -> true
else -> false
}
@@ -114,7 +114,13 @@
R.raw.fingerprint_dialogue_fingerprint_to_error_lottie
}
}
- STATE_AUTHENTICATED -> R.raw.fingerprint_dialogue_fingerprint_to_error_lottie
+ STATE_AUTHENTICATED -> {
+ if (oldState == STATE_ERROR || oldState == STATE_HELP) {
+ R.raw.fingerprint_dialogue_error_to_success_lottie
+ } else {
+ R.raw.fingerprint_dialogue_fingerprint_to_success_lottie
+ }
+ }
else -> return null
}
return if (id != null) return id else null
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
index 31baa0f..9cce066 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
@@ -75,7 +75,7 @@
}
}
- override fun getDelayAfterAuthenticatedDurationMs() = 0
+ override fun getDelayAfterAuthenticatedDurationMs() = 500
override fun getStateForAfterError() = STATE_AUTHENTICATING
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index e866b9c..fc5cf9f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -468,6 +468,7 @@
break;
case STATE_AUTHENTICATED:
+ removePendingAnimations();
if (mSize != AuthDialog.SIZE_SMALL) {
mConfirmButton.setVisibility(View.GONE);
mNegativeButton.setVisibility(View.GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 84e1c3d..436b756 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -129,6 +129,8 @@
private final Set<Integer> mFailedModalities = new HashSet<Integer>();
private final @Background DelayableExecutor mBackgroundExecutor;
+ private int mOrientation;
+ private boolean mSkipFirstLostFocus = false;
// Non-null only if the dialog is in the act of dismissing and has not sent the reason yet.
@Nullable @AuthDialogCallback.DismissedReason private Integer mPendingCallbackReason;
@@ -441,6 +443,12 @@
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if (!hasWindowFocus) {
+ //it's a workaround to avoid closing BP incorrectly
+ //BP gets a onWindowFocusChanged(false) and then gets a onWindowFocusChanged(true)
+ if (mSkipFirstLostFocus) {
+ mSkipFirstLostFocus = false;
+ return;
+ }
Log.v(TAG, "Lost window focus, dismissing the dialog");
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
}
@@ -450,6 +458,9 @@
public void onAttachedToWindow() {
super.onAttachedToWindow();
+ //save the first orientation
+ mOrientation = getResources().getConfiguration().orientation;
+
mWakefulnessLifecycle.addObserver(this);
if (Utils.isBiometricAllowed(mConfig.mPromptInfo)) {
@@ -621,6 +632,12 @@
if (mBiometricView != null) {
mBiometricView.restoreState(savedState);
}
+
+ if (savedState != null) {
+ mSkipFirstLostFocus = savedState.getBoolean(
+ AuthDialog.KEY_BIOMETRIC_ORIENTATION_CHANGED);
+ }
+
wm.addView(this, getLayoutParams(mWindowToken, mConfig.mPromptInfo.getTitle()));
}
@@ -640,30 +657,50 @@
@Override
public void onAuthenticationSucceeded(@Modality int modality) {
- mBiometricView.onAuthenticationSucceeded(modality);
+ if (mBiometricView != null) {
+ mBiometricView.onAuthenticationSucceeded(modality);
+ } else {
+ Log.e(TAG, "onAuthenticationSucceeded(): mBiometricView is null");
+ }
}
@Override
public void onAuthenticationFailed(@Modality int modality, String failureReason) {
- mFailedModalities.add(modality);
- mBiometricView.onAuthenticationFailed(modality, failureReason);
+ if (mBiometricView != null) {
+ mFailedModalities.add(modality);
+ mBiometricView.onAuthenticationFailed(modality, failureReason);
+ } else {
+ Log.e(TAG, "onAuthenticationFailed(): mBiometricView is null");
+ }
}
@Override
public void onHelp(@Modality int modality, String help) {
- mBiometricView.onHelp(modality, help);
+ if (mBiometricView != null) {
+ mBiometricView.onHelp(modality, help);
+ } else {
+ Log.e(TAG, "onHelp(): mBiometricView is null");
+ }
}
@Override
public void onError(@Modality int modality, String error) {
- mBiometricView.onError(modality, error);
+ if (mBiometricView != null) {
+ mBiometricView.onError(modality, error);
+ } else {
+ Log.e(TAG, "onError(): mBiometricView is null");
+ }
}
@Override
public void onPointerDown() {
- if (mBiometricView.onPointerDown(mFailedModalities)) {
- Log.d(TAG, "retrying failed modalities (pointer down)");
- mBiometricCallback.onAction(AuthBiometricView.Callback.ACTION_BUTTON_TRY_AGAIN);
+ if (mBiometricView != null) {
+ if (mBiometricView.onPointerDown(mFailedModalities)) {
+ Log.d(TAG, "retrying failed modalities (pointer down)");
+ mBiometricCallback.onAction(AuthBiometricView.Callback.ACTION_BUTTON_TRY_AGAIN);
+ }
+ } else {
+ Log.e(TAG, "onPointerDown(): mBiometricView is null");
}
}
@@ -677,6 +714,10 @@
mBiometricView != null && mCredentialView == null);
outState.putBoolean(AuthDialog.KEY_CREDENTIAL_SHOWING, mCredentialView != null);
+ if (mOrientation != getResources().getConfiguration().orientation) {
+ outState.putBoolean(AuthDialog.KEY_BIOMETRIC_ORIENTATION_CHANGED, true);
+ }
+
if (mBiometricView != null) {
mBiometricView.onSaveState(outState);
}
@@ -694,7 +735,11 @@
@Override
public void animateToCredentialUI() {
- mBiometricView.startTransitionToCredentialUI();
+ if (mBiometricView != null) {
+ mBiometricView.startTransitionToCredentialUI();
+ } else {
+ Log.e(TAG, "animateToCredentialUI(): mBiometricView is null");
+ }
}
void animateAway(@AuthDialogCallback.DismissedReason int reason) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 47ff59c..a3b6cfc 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -19,6 +19,9 @@
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -31,7 +34,6 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricAuthenticator.Modality;
@@ -55,7 +57,9 @@
import android.os.RemoteException;
import android.os.UserManager;
import android.util.Log;
+import android.util.RotationUtils;
import android.util.SparseBooleanArray;
+import android.view.Display;
import android.view.DisplayInfo;
import android.view.MotionEvent;
import android.view.WindowManager;
@@ -116,8 +120,14 @@
@NonNull private Point mStableDisplaySize = new Point();
- @Nullable private final PointF mFaceAuthSensorLocation;
- @Nullable private PointF mFingerprintLocation;
+ private final Display mDisplay;
+ private float mScaleFactor = 1f;
+ // sensor locations without any resolution scaling nor rotation adjustments:
+ @Nullable private final Point mFaceSensorLocationDefault;
+ @Nullable private final Point mFingerprintSensorLocationDefault;
+ // cached sensor locations:
+ @Nullable private Point mFaceSensorLocation;
+ @Nullable private Point mFingerprintSensorLocation;
@Nullable private Rect mUdfpsBounds;
private final Set<Callback> mCallbacks = new HashSet<>();
@@ -147,6 +157,7 @@
@NonNull private final LockPatternUtils mLockPatternUtils;
@NonNull private final InteractionJankMonitor mInteractionJankMonitor;
private final @Background DelayableExecutor mBackgroundExecutor;
+ private final DisplayInfo mCachedDisplayInfo = new DisplayInfo();
@VisibleForTesting
final TaskStackListener mTaskStackListener = new TaskStackListener() {
@@ -184,7 +195,6 @@
Log.w(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received");
mCurrentDialog.dismissWithoutCallback(true /* animate */);
mCurrentDialog = null;
- mOrientationListener.disable();
for (Callback cb : mCallbacks) {
cb.onBiometricPromptDismissed();
@@ -218,7 +228,6 @@
Log.e(TAG, "Evicting client due to: " + topPackage);
mCurrentDialog.dismissWithoutCallback(true /* animate */);
mCurrentDialog = null;
- mOrientationListener.disable();
for (Callback cb : mCallbacks) {
cb.onBiometricPromptDismissed();
@@ -284,7 +293,6 @@
mUdfpsController.setAuthControllerUpdateUdfpsLocation(this::updateUdfpsLocation);
mUdfpsController.setHalControlsIllumination(mUdfpsProps.get(0).halControlsIllumination);
mUdfpsBounds = mUdfpsProps.get(0).getLocation().getRect();
- updateUdfpsLocation();
}
mSidefpsProps = !sidefpsProps.isEmpty() ? sidefpsProps : null;
@@ -292,8 +300,8 @@
mSidefpsController = mSidefpsControllerFactory.get();
}
+ updateSensorLocations();
mFingerprintManager.registerBiometricStateListener(mBiometricStateListener);
- updateFingerprintLocation();
for (Callback cb : mCallbacks) {
cb.onAllAuthenticatorsRegistered();
@@ -470,11 +478,11 @@
/**
* @return where the UDFPS exists on the screen in pixels in portrait mode.
*/
- @Nullable public PointF getUdfpsLocation() {
+ @Nullable public Point getUdfpsLocation() {
if (mUdfpsController == null || mUdfpsBounds == null) {
return null;
}
- return new PointF(mUdfpsBounds.centerX(), mUdfpsBounds.centerY());
+ return new Point(mUdfpsBounds.centerX(), mUdfpsBounds.centerY());
}
/**
@@ -488,45 +496,105 @@
}
/**
- * @return the scale factor representing the user's current resolution / the stable
- * (default) resolution
+ * Gets the cached scale factor representing the user's current resolution / the stable
+ * (default) resolution.
*/
public float getScaleFactor() {
- if (mUdfpsController == null || mUdfpsController.mOverlayParams == null) {
- return 1f;
- }
- return mUdfpsController.mOverlayParams.getScaleFactor();
+ return mScaleFactor;
}
/**
- * @return where the fingerprint sensor exists in pixels in portrait mode. devices without an
- * overridden value will use the default value even if they don't have a fingerprint sensor
+ * Updates the current display info and cached scale factor & sensor locations.
+ * Getting the display info is a relatively expensive call, so avoid superfluous calls.
*/
- @Nullable public PointF getFingerprintSensorLocation() {
+ private void updateSensorLocations() {
+ mDisplay.getDisplayInfo(mCachedDisplayInfo);
+
+ final float scaleFactor = android.util.DisplayUtils.getPhysicalPixelDisplaySizeRatio(
+ mStableDisplaySize.x, mStableDisplaySize.y, mCachedDisplayInfo.getNaturalWidth(),
+ mCachedDisplayInfo.getNaturalHeight());
+ if (scaleFactor == Float.POSITIVE_INFINITY) {
+ mScaleFactor = 1f;
+ } else {
+ mScaleFactor = scaleFactor;
+ }
+
+ updateUdfpsLocation();
+ updateFingerprintLocation();
+ updateFaceLocation();
+ }
+ /**
+ * @return where the fingerprint sensor exists in pixels in its natural orientation.
+ * Devices without location configs will use the default value even if they don't have a
+ * fingerprint sensor.
+ *
+ * May return null if the fingerprint sensor isn't available yet.
+ */
+ @Nullable private Point getFingerprintSensorLocationInNaturalOrientation() {
if (getUdfpsLocation() != null) {
return getUdfpsLocation();
}
- return mFingerprintLocation;
+ return new Point(
+ (int) (mFingerprintSensorLocationDefault.x * mScaleFactor),
+ (int) (mFingerprintSensorLocationDefault.y * mScaleFactor)
+ );
}
/**
- * @return where the face authentication sensor exists relative to the screen in pixels in
- * portrait mode.
+ * @return where the fingerprint sensor exists in pixels exists the current device orientation.
+ * Devices without location configs will use the default value even if they don't have a
+ * fingerprint sensor.
*/
- @Nullable public PointF getFaceAuthSensorLocation() {
- if (mFaceProps == null || mFaceAuthSensorLocation == null) {
- return null;
+ @Nullable public Point getFingerprintSensorLocation() {
+ return mFingerprintSensorLocation;
+ }
+
+ private void updateFingerprintLocation() {
+ if (mFpProps == null) {
+ mFingerprintSensorLocation = null;
+ } else {
+ mFingerprintSensorLocation = rotateToCurrentOrientation(
+ getFingerprintSensorLocationInNaturalOrientation(),
+ mCachedDisplayInfo);
}
- DisplayInfo displayInfo = new DisplayInfo();
- mContext.getDisplay().getDisplayInfo(displayInfo);
- final float scaleFactor = android.util.DisplayUtils.getPhysicalPixelDisplaySizeRatio(
- mStableDisplaySize.x, mStableDisplaySize.y, displayInfo.getNaturalWidth(),
- displayInfo.getNaturalHeight());
- if (scaleFactor == Float.POSITIVE_INFINITY) {
- return new PointF(mFaceAuthSensorLocation.x, mFaceAuthSensorLocation.y);
+ }
+
+ /**
+ * @return where the face sensor exists in pixels in the current device orientation. Returns
+ * null if no face sensor exists.
+ */
+ @Nullable public Point getFaceSensorLocation() {
+ return mFaceSensorLocation;
+ }
+
+ private void updateFaceLocation() {
+ if (mFaceProps == null || mFaceSensorLocationDefault == null) {
+ mFaceSensorLocation = null;
+ } else {
+ mFaceSensorLocation = rotateToCurrentOrientation(
+ new Point(
+ (int) (mFaceSensorLocationDefault.x * mScaleFactor),
+ (int) (mFaceSensorLocationDefault.y * mScaleFactor)),
+ mCachedDisplayInfo
+ );
}
- return new PointF(mFaceAuthSensorLocation.x * scaleFactor,
- mFaceAuthSensorLocation.y * scaleFactor);
+ }
+
+ /**
+ * @param inOutPoint point on the display in pixels. Going in, represents the point
+ * in the device's natural orientation. Going out, represents
+ * the point in the display's current orientation.
+ * @param displayInfo currently display information to use to rotate the point
+ */
+ @VisibleForTesting
+ protected Point rotateToCurrentOrientation(Point inOutPoint, DisplayInfo displayInfo) {
+ RotationUtils.rotatePoint(
+ inOutPoint,
+ displayInfo.rotation,
+ displayInfo.getNaturalWidth(),
+ displayInfo.getNaturalHeight()
+ );
+ return inOutPoint;
}
/**
@@ -590,7 +658,6 @@
@Background DelayableExecutor bgExecutor) {
super(context);
mExecution = execution;
- mWakefulnessLifecycle = wakefulnessLifecycle;
mUserManager = userManager;
mLockPatternUtils = lockPatternUtils;
mHandler = handler;
@@ -616,54 +683,58 @@
return Unit.INSTANCE;
});
+ mWakefulnessLifecycle = wakefulnessLifecycle;
+ mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() {
+ @Override
+ public void onFinishedWakingUp() {
+ notifyDozeChanged(mStatusBarStateController.isDozing(), WAKEFULNESS_AWAKE);
+ }
+
+ @Override
+ public void onStartedGoingToSleep() {
+ notifyDozeChanged(mStatusBarStateController.isDozing(), WAKEFULNESS_GOING_TO_SLEEP);
+ }
+ });
+
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(new StatusBarStateController.StateListener() {
@Override
public void onDozingChanged(boolean isDozing) {
- notifyDozeChanged(isDozing);
+ notifyDozeChanged(isDozing, wakefulnessLifecycle.getWakefulness());
}
});
mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;
-
int[] faceAuthLocation = context.getResources().getIntArray(
com.android.systemui.R.array.config_face_auth_props);
if (faceAuthLocation == null || faceAuthLocation.length < 2) {
- mFaceAuthSensorLocation = null;
+ mFaceSensorLocationDefault = null;
} else {
- mFaceAuthSensorLocation = new PointF(
- (float) faceAuthLocation[0],
- (float) faceAuthLocation[1]);
+ mFaceSensorLocationDefault = new Point(
+ faceAuthLocation[0],
+ faceAuthLocation[1]);
}
- updateFingerprintLocation();
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
-
- context.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_EXPORTED_UNAUDITED);
- mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
- }
-
- private int getDisplayWidth() {
- DisplayInfo displayInfo = new DisplayInfo();
- mContext.getDisplay().getDisplayInfo(displayInfo);
- return displayInfo.getNaturalWidth();
- }
-
- private void updateFingerprintLocation() {
- int xLocation = getDisplayWidth() / 2;
+ mDisplay = mContext.getDisplay();
+ mDisplay.getDisplayInfo(mCachedDisplayInfo);
+ int xFpLocation = mCachedDisplayInfo.getNaturalWidth() / 2;
try {
- xLocation = mContext.getResources().getDimensionPixelSize(
+ xFpLocation = mContext.getResources().getDimensionPixelSize(
com.android.systemui.R.dimen
.physical_fingerprint_sensor_center_screen_location_x);
} catch (Resources.NotFoundException e) {
}
- int yLocation = mContext.getResources().getDimensionPixelSize(
- com.android.systemui.R.dimen.physical_fingerprint_sensor_center_screen_location_y);
- mFingerprintLocation = new PointF(
- xLocation,
- yLocation);
+ mFingerprintSensorLocationDefault = new Point(
+ xFpLocation,
+ mContext.getResources().getDimensionPixelSize(com.android.systemui.R.dimen
+ .physical_fingerprint_sensor_center_screen_location_y)
+ );
+ updateSensorLocations();
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ context.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_EXPORTED_UNAUDITED);
+ mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
}
// TODO(b/229290039): UDFPS controller should manage its dimensions on its own. Remove this.
@@ -672,19 +743,14 @@
// updateFingerprintLocation in such a case are unclear.
private void updateUdfpsLocation() {
if (mUdfpsController != null) {
- final DisplayInfo displayInfo = new DisplayInfo();
- mContext.getDisplay().getDisplayInfo(displayInfo);
- final float scaleFactor = android.util.DisplayUtils.getPhysicalPixelDisplaySizeRatio(
- mStableDisplaySize.x, mStableDisplaySize.y, displayInfo.getNaturalWidth(),
- displayInfo.getNaturalHeight());
-
final FingerprintSensorPropertiesInternal udfpsProp = mUdfpsProps.get(0);
final Rect previousUdfpsBounds = mUdfpsBounds;
mUdfpsBounds = udfpsProp.getLocation().getRect();
- mUdfpsBounds.scale(scaleFactor);
+ mUdfpsBounds.scale(mScaleFactor);
mUdfpsController.updateOverlayParams(udfpsProp.sensorId,
- new UdfpsOverlayParams(mUdfpsBounds, displayInfo.getNaturalWidth(),
- displayInfo.getNaturalHeight(), scaleFactor, displayInfo.rotation));
+ new UdfpsOverlayParams(mUdfpsBounds, mCachedDisplayInfo.getNaturalWidth(),
+ mCachedDisplayInfo.getNaturalHeight(), mScaleFactor,
+ mCachedDisplayInfo.rotation));
if (!Objects.equals(previousUdfpsBounds, mUdfpsBounds)) {
for (Callback cb : mCallbacks) {
cb.onUdfpsLocationChanged();
@@ -705,18 +771,23 @@
mStableDisplaySize = mDisplayManager.getStableDisplaySize();
mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
+ mOrientationListener.enable();
+ updateSensorLocations();
}
@Override
public void setBiometicContextListener(IBiometricContextListener listener) {
mBiometricContextListener = listener;
- notifyDozeChanged(mStatusBarStateController.isDozing());
+ notifyDozeChanged(mStatusBarStateController.isDozing(),
+ mWakefulnessLifecycle.getWakefulness());
}
- private void notifyDozeChanged(boolean isDozing) {
+ private void notifyDozeChanged(boolean isDozing,
+ @WakefulnessLifecycle.Wakefulness int wakefullness) {
if (mBiometricContextListener != null) {
try {
- mBiometricContextListener.onDozeChanged(isDozing);
+ final boolean isAwake = wakefullness == WAKEFULNESS_AWAKE;
+ mBiometricContextListener.onDozeChanged(isDozing, isAwake);
} catch (RemoteException e) {
Log.w(TAG, "failed to notify initial doze state");
}
@@ -905,7 +976,6 @@
// BiometricService will have already sent the callback to the client in this case.
// This avoids a round trip to SystemUI. So, just dismiss the dialog and we're done.
mCurrentDialog = null;
- mOrientationListener.disable();
}
/**
@@ -996,7 +1066,6 @@
}
mCurrentDialog = newDialog;
mCurrentDialog.show(mWindowManager, savedState);
- mOrientationListener.enable();
if (!promptInfo.isAllowBackgroundAuthentication()) {
mHandler.post(this::cancelIfOwnerIsNotInForeground);
@@ -1015,14 +1084,12 @@
mReceiver = null;
mCurrentDialog = null;
- mOrientationListener.disable();
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- updateFingerprintLocation();
- updateUdfpsLocation();
+ updateSensorLocations();
// Save the state of the current dialog (buttons showing, etc)
if (mCurrentDialog != null) {
@@ -1030,7 +1097,6 @@
mCurrentDialog.onSaveState(savedState);
mCurrentDialog.dismissWithoutCallback(false /* animate */);
mCurrentDialog = null;
- mOrientationListener.disable();
// Only show the dialog if necessary. If it was animating out, the dialog is supposed
// to send its pending callback immediately.
@@ -1051,8 +1117,7 @@
}
private void onOrientationChanged() {
- updateFingerprintLocation();
- updateUdfpsLocation();
+ updateSensorLocations();
if (mCurrentDialog != null) {
mCurrentDialog.onOrientationChanged();
}
@@ -1062,6 +1127,7 @@
PromptInfo promptInfo, boolean requireConfirmation, int userId, int[] sensorIds,
String opPackageName, boolean skipIntro, long operationId, long requestId,
@BiometricMultiSensorMode int multiSensorConfig,
+
@NonNull WakefulnessLifecycle wakefulnessLifecycle,
@NonNull UserManager userManager,
@NonNull LockPatternUtils lockPatternUtils) {
@@ -1075,9 +1141,7 @@
.setOperationId(operationId)
.setRequestId(requestId)
.setMultiSensorConfig(multiSensorConfig)
- .setScaleFactorProvider(() -> {
- return getScaleFactor();
- })
+ .setScaleFactorProvider(() -> getScaleFactor())
.build(bgExecutor, sensorIds, mFpProps, mFaceProps, wakefulnessLifecycle,
userManager, lockPatternUtils, mInteractionJankMonitor);
}
@@ -1086,8 +1150,14 @@
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
final AuthDialog dialog = mCurrentDialog;
pw.println(" stableDisplaySize=" + mStableDisplaySize);
- pw.println(" faceAuthSensorLocation=" + mFaceAuthSensorLocation);
- pw.println(" fingerprintLocation=" + mFingerprintLocation);
+ pw.println(" mCachedDisplayInfo=" + mCachedDisplayInfo);
+ pw.println(" mScaleFactor=" + mScaleFactor);
+ pw.println(" faceAuthSensorLocationDefault=" + mFaceSensorLocationDefault);
+ pw.println(" faceAuthSensorLocation=" + getFaceSensorLocation());
+ pw.println(" fingerprintSensorLocationDefault=" + mFingerprintSensorLocationDefault);
+ pw.println(" fingerprintSensorLocationInNaturalOrientation="
+ + getFingerprintSensorLocationInNaturalOrientation());
+ pw.println(" fingerprintSensorLocation=" + getFingerprintSensorLocation());
pw.println(" udfpsBounds=" + mUdfpsBounds);
pw.println(" allFingerprintAuthenticatorsRegistered="
+ mAllFingerprintAuthenticatorsRegistered);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
index 51f39b3..cd0fc37 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
@@ -48,6 +48,8 @@
String KEY_BIOMETRIC_SENSOR_TYPE = "sensor_type";
String KEY_BIOMETRIC_SENSOR_PROPS = "sensor_props";
+ String KEY_BIOMETRIC_ORIENTATION_CHANGED = "orientation_changed";
+
int SIZE_UNKNOWN = 0;
/**
* Minimal UI, showing only biometric icon.
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index 38fab8f..d7bf261 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -20,7 +20,7 @@
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.content.Context
-import android.graphics.PointF
+import android.graphics.Point
import android.hardware.biometrics.BiometricFingerprintConstants
import android.hardware.biometrics.BiometricSourceType
import android.util.Log
@@ -79,8 +79,8 @@
@VisibleForTesting
internal var startLightRevealScrimOnKeyguardFadingAway = false
var lightRevealScrimAnimator: ValueAnimator? = null
- var fingerprintSensorLocation: PointF? = null
- private var faceSensorLocation: PointF? = null
+ var fingerprintSensorLocation: Point? = null
+ private var faceSensorLocation: Point? = null
private var circleReveal: LightRevealEffect? = null
private var udfpsController: UdfpsController? = null
@@ -131,10 +131,10 @@
circleReveal = CircleReveal(
it.x,
it.y,
- 0f,
+ 0,
Math.max(
- Math.max(it.x, centralSurfaces.displayWidth - it.x),
- Math.max(it.y, centralSurfaces.displayHeight - it.y)
+ Math.max(it.x, centralSurfaces.displayWidth.toInt() - it.x),
+ Math.max(it.y, centralSurfaces.displayHeight.toInt() - it.y)
)
)
showUnlockedRipple()
@@ -148,10 +148,10 @@
circleReveal = CircleReveal(
it.x,
it.y,
- 0f,
+ 0,
Math.max(
- Math.max(it.x, centralSurfaces.displayWidth - it.x),
- Math.max(it.y, centralSurfaces.displayHeight - it.y)
+ Math.max(it.x, centralSurfaces.displayWidth.toInt() - it.x),
+ Math.max(it.y, centralSurfaces.displayHeight.toInt() - it.y)
)
)
showUnlockedRipple()
@@ -228,7 +228,7 @@
fun updateSensorLocation() {
fingerprintSensorLocation = authController.fingerprintSensorLocation
- faceSensorLocation = authController.faceAuthSensorLocation
+ faceSensorLocation = authController.faceSensorLocation
}
private fun updateRippleColor() {
@@ -362,9 +362,8 @@
invalidCommand(pw)
return
}
- pw.println("custom ripple sensorLocation=" + args[1].toFloat() + ", " +
- args[2].toFloat())
- mView.setSensorLocation(PointF(args[1].toFloat(), args[2].toFloat()))
+ pw.println("custom ripple sensorLocation=" + args[1] + ", " + args[2])
+ mView.setSensorLocation(Point(args[1].toInt(), args[2].toInt()))
showUnlockedRipple()
}
else -> invalidCommand(pw)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 1c57480..c93fe6a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -23,7 +23,7 @@
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
-import android.graphics.PointF
+import android.graphics.Point
import android.util.AttributeSet
import android.view.View
import android.view.animation.PathInterpolator
@@ -68,7 +68,7 @@
dwellShader.maxRadius = value
field = value
}
- private var dwellOrigin: PointF = PointF()
+ private var dwellOrigin: Point = Point()
set(value) {
dwellShader.origin = value
field = value
@@ -78,9 +78,9 @@
rippleShader.setMaxSize(value * 2f, value * 2f)
field = value
}
- private var origin: PointF = PointF()
+ private var origin: Point = Point()
set(value) {
- rippleShader.setCenter(value.x, value.y)
+ rippleShader.setCenter(value.x.toFloat(), value.y.toFloat())
field = value
}
@@ -97,12 +97,12 @@
visibility = GONE
}
- fun setSensorLocation(location: PointF) {
+ fun setSensorLocation(location: Point) {
origin = location
radius = maxOf(location.x, location.y, width - location.x, height - location.y).toFloat()
}
- fun setFingerprintSensorLocation(location: PointF, sensorRadius: Float) {
+ fun setFingerprintSensorLocation(location: Point, sensorRadius: Float) {
origin = location
radius = maxOf(location.x, location.y, width - location.x, height - location.y).toFloat()
dwellOrigin = location
@@ -349,13 +349,15 @@
if (drawDwell) {
val maskRadius = (1 - (1 - dwellShader.progress) * (1 - dwellShader.progress) *
(1 - dwellShader.progress)) * dwellRadius * 2f
- canvas?.drawCircle(dwellOrigin.x, dwellOrigin.y, maskRadius, dwellPaint)
+ canvas?.drawCircle(dwellOrigin.x.toFloat(), dwellOrigin.y.toFloat(),
+ maskRadius, dwellPaint)
}
if (drawRipple) {
val mask = (1 - (1 - rippleShader.progress) * (1 - rippleShader.progress) *
(1 - rippleShader.progress)) * radius * 2f
- canvas?.drawCircle(origin.x, origin.y, mask, ripplePaint)
+ canvas?.drawCircle(origin.x.toFloat(), origin.y.toFloat(),
+ mask, ripplePaint)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt b/packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt
index 979fe33..e5c4fb4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt
@@ -16,7 +16,7 @@
package com.android.systemui.biometrics
-import android.graphics.PointF
+import android.graphics.Point
import android.graphics.RuntimeShader
import android.util.MathUtils
@@ -94,10 +94,10 @@
/**
* Origin coordinate of the ripple.
*/
- var origin: PointF = PointF()
+ var origin: Point = Point()
set(value) {
field = value
- setFloatUniform("in_origin", value.x, value.y)
+ setFloatUniform("in_origin", value.x.toFloat(), value.y.toFloat())
}
/**
@@ -107,7 +107,7 @@
set(value) {
field = value
setFloatUniform("in_radius",
- (1 - (1 - value) * (1 - value) * (1 - value))* maxRadius)
+ (1 - (1 - value) * (1 - value) * (1 - value)) * maxRadius)
setFloatUniform("in_blur", MathUtils.lerp(1f, 0.7f, value))
}
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
index d757b62..eb8cb47 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -31,6 +31,8 @@
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.Dumpable
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dump.DumpManager
@@ -38,6 +40,8 @@
import java.io.PrintWriter
import java.util.concurrent.Executor
import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
data class ReceiverData(
val receiver: BroadcastReceiver,
@@ -153,6 +157,55 @@
.sendToTarget()
}
+ /**
+ * Returns a [Flow] that, when collected, emits a new value whenever a broadcast matching
+ * [filter] is received. The value will be computed from the intent and the registered receiver
+ * using [map].
+ *
+ * @see registerReceiver
+ */
+ @JvmOverloads
+ fun <T> broadcastFlow(
+ filter: IntentFilter,
+ user: UserHandle? = null,
+ @Context.RegisterReceiverFlags flags: Int = Context.RECEIVER_EXPORTED,
+ permission: String? = null,
+ map: (Intent, BroadcastReceiver) -> T,
+ ): Flow<T> = conflatedCallbackFlow {
+ val receiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ trySendWithFailureLogging(map(intent, this), TAG)
+ }
+ }
+
+ registerReceiver(
+ receiver,
+ filter,
+ bgExecutor,
+ user,
+ flags,
+ permission,
+ )
+
+ awaitClose {
+ unregisterReceiver(receiver)
+ }
+ }
+
+ /**
+ * Returns a [Flow] that, when collected, emits `Unit` whenever a broadcast matching [filter] is
+ * received.
+ *
+ * @see registerReceiver
+ */
+ @JvmOverloads
+ fun broadcastFlow(
+ filter: IntentFilter,
+ user: UserHandle? = null,
+ @Context.RegisterReceiverFlags flags: Int = Context.RECEIVER_EXPORTED,
+ permission: String? = null,
+ ): Flow<Unit> = broadcastFlow(filter, user, flags, permission) { _, _ -> Unit }
+
private fun checkFilter(filter: IntentFilter) {
val sb = StringBuilder()
if (filter.countActions() == 0) sb.append("Filter must contain at least one action. ")
diff --git a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
index 81da8023..e2ef247 100644
--- a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
@@ -36,7 +36,6 @@
import com.android.systemui.shared.system.ActivityManagerKt.isInForeground
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.CentralSurfaces
-import com.android.systemui.shade.PanelViewController
import com.android.systemui.statusbar.policy.KeyguardStateController
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -117,7 +116,7 @@
)
} catch (e: RemoteException) {
Log.w(
- PanelViewController.TAG,
+ "CameraGestureHelper",
"Unable to start camera activity",
e
)
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt b/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
index da675de..dec3d6b 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
@@ -200,8 +200,7 @@
}
private fun updateRippleColor() {
- rippleView.setColor(
- Utils.getColorAttr(context, android.R.attr.colorAccent).defaultColor)
+ rippleView.setColor(Utils.getColorAttr(context, android.R.attr.colorAccent).defaultColor)
}
inner class ChargingRippleCommand : Command {
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index 0839338..c0cc6b4 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -30,13 +30,12 @@
import android.widget.ImageView;
import android.widget.TextView;
-import androidx.core.graphics.ColorUtils;
-
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.ripple.RippleShader.RippleShape;
import com.android.systemui.ripple.RippleView;
+import com.android.systemui.ripple.RippleViewKt;
import java.text.NumberFormat;
@@ -143,16 +142,15 @@
mRippleView = findViewById(R.id.wireless_charging_ripple);
mRippleView.setupShader(rippleShape);
+ int color = Utils.getColorAttr(mRippleView.getContext(),
+ android.R.attr.colorAccent).getDefaultColor();
if (mRippleView.getRippleShape() == RippleShape.ROUNDED_BOX) {
mRippleView.setDuration(ROUNDED_BOX_RIPPLE_ANIMATION_DURATION);
mRippleView.setSparkleStrength(0.22f);
- int color = Utils.getColorAttr(mRippleView.getContext(),
- android.R.attr.colorAccent).getDefaultColor();
- mRippleView.setColor(ColorUtils.setAlphaComponent(color, 28));
+ mRippleView.setColor(color, 28);
} else {
mRippleView.setDuration(CIRCLE_RIPPLE_ANIMATION_DURATION);
- mRippleView.setColor(Utils.getColorAttr(mRippleView.getContext(),
- android.R.attr.colorAccent).getDefaultColor());
+ mRippleView.setColor(color, RippleViewKt.RIPPLE_DEFAULT_ALPHA);
}
OnAttachStateChangeListener listener = new OnAttachStateChangeListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index e28a475..31a2134 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -80,12 +80,14 @@
private final Collection<FalsingClassifier> mClassifiers;
private final List<FalsingBeliefListener> mFalsingBeliefListeners = new ArrayList<>();
private List<FalsingTapListener> mFalsingTapListeners = new ArrayList<>();
+ private ProximityEvent mLastProximityEvent;
private boolean mDestroyed;
private final SessionListener mSessionListener = new SessionListener() {
@Override
public void onSessionEnded() {
+ mLastProximityEvent = null;
mClassifiers.forEach(FalsingClassifier::onSessionEnded);
}
@@ -336,6 +338,7 @@
public void onProximityEvent(ProximityEvent proximityEvent) {
// TODO: some of these classifiers might allow us to abort early, meaning we don't have to
// make these calls.
+ mLastProximityEvent = proximityEvent;
mClassifiers.forEach((classifier) -> classifier.onProximityEvent(proximityEvent));
}
@@ -348,6 +351,11 @@
}
@Override
+ public boolean isProximityNear() {
+ return mLastProximityEvent != null && mLastProximityEvent.getCovered();
+ }
+
+ @Override
public boolean isUnlockingDisabled() {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
index 56dd1e1..23d87ff 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
@@ -47,9 +47,9 @@
@SysUISingleton
class FalsingCollectorImpl implements FalsingCollector {
- private static final boolean DEBUG = false;
- private static final String TAG = "FalsingManager";
- private static final String PROXIMITY_SENSOR_TAG = "FalsingManager";
+ private static final String TAG = "FalsingCollector";
+ private static final String PROXIMITY_SENSOR_TAG = "FalsingCollector";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final long GESTURE_PROCESSING_DELAY_MS = 100;
private final FalsingDataProvider mFalsingDataProvider;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index 609f1d6..5d04b5f 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -144,6 +144,11 @@
}
@Override
+ public boolean isProximityNear() {
+ return mInternalFalsingManager.isProximityNear();
+ }
+
+ @Override
public boolean isClassifierEnabled() {
return mInternalFalsingManager.isClassifierEnabled();
}
diff --git a/packages/SystemUI/src/com/android/systemui/common/shared/model/ContentDescription.kt b/packages/SystemUI/src/com/android/systemui/common/shared/model/ContentDescription.kt
new file mode 100644
index 0000000..bebade0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/shared/model/ContentDescription.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.common.shared.model
+
+import android.annotation.StringRes
+
+/**
+ * Models a content description, that can either be already [loaded][ContentDescription.Loaded] or
+ * be a [reference][ContentDescription.Resource] to a resource.
+ */
+sealed class ContentDescription {
+ data class Loaded(
+ val description: String?,
+ ) : ContentDescription()
+
+ data class Resource(
+ @StringRes val res: Int,
+ ) : ContentDescription()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/common/shared/model/Icon.kt b/packages/SystemUI/src/com/android/systemui/common/shared/model/Icon.kt
new file mode 100644
index 0000000..0b65966
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/shared/model/Icon.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.common.shared.model
+
+import android.annotation.DrawableRes
+import android.graphics.drawable.Drawable
+
+/**
+ * Models an icon, that can either be already [loaded][Icon.Loaded] or be a [reference]
+ * [Icon.Resource] to a resource.
+ */
+sealed class Icon {
+ data class Loaded(
+ val drawable: Drawable,
+ ) : Icon()
+
+ data class Resource(
+ @DrawableRes val res: Int,
+ ) : Icon()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/binder/ContentDescriptionViewBinder.kt b/packages/SystemUI/src/com/android/systemui/common/ui/binder/ContentDescriptionViewBinder.kt
new file mode 100644
index 0000000..d6433aa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/binder/ContentDescriptionViewBinder.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.common.ui.binder
+
+import android.view.View
+import com.android.systemui.common.shared.model.ContentDescription
+
+object ContentDescriptionViewBinder {
+ fun bind(
+ contentDescription: ContentDescription,
+ view: View,
+ ) {
+ when (contentDescription) {
+ is ContentDescription.Loaded -> view.contentDescription = contentDescription.description
+ is ContentDescription.Resource -> {
+ view.contentDescription = view.context.resources.getString(contentDescription.res)
+ }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java b/packages/SystemUI/src/com/android/systemui/common/ui/binder/IconViewBinder.kt
similarity index 60%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
copy to packages/SystemUI/src/com/android/systemui/common/ui/binder/IconViewBinder.kt
index e62a63a..aecee2a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/binder/IconViewBinder.kt
@@ -14,18 +14,19 @@
* limitations under the License.
*/
-package com.android.wm.shell.desktopmode;
+package com.android.systemui.common.ui.binder
-import android.os.SystemProperties;
+import android.widget.ImageView
+import com.android.systemui.common.shared.model.Icon
-/**
- * Constants for desktop mode feature
- */
-public class DesktopModeConstants {
-
- /**
- * Flag to indicate whether desktop mode is available on the device
- */
- public static final boolean IS_FEATURE_ENABLED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode", false);
+object IconViewBinder {
+ fun bind(
+ icon: Icon,
+ view: ImageView,
+ ) {
+ when (icon) {
+ is Icon.Loaded -> view.setImageDrawable(icon.drawable)
+ is Icon.Resource -> view.setImageResource(icon.res)
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt
new file mode 100644
index 0000000..c27b82a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.common.ui.view
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.LinearLayout
+import com.android.systemui.animation.LaunchableView
+import com.android.systemui.animation.LaunchableViewDelegate
+
+/** A [LinearLayout] that also implements [LaunchableView]. */
+class LaunchableLinearLayout : LinearLayout, LaunchableView {
+ private val delegate =
+ LaunchableViewDelegate(
+ this,
+ superSetVisibility = { super.setVisibility(it) },
+ superSetTransitionVisibility = { super.setTransitionVisibility(it) },
+ )
+
+ constructor(context: Context?) : super(context)
+ constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
+ constructor(
+ context: Context?,
+ attrs: AttributeSet?,
+ defStyleAttr: Int,
+ ) : super(context, attrs, defStyleAttr)
+
+ constructor(
+ context: Context?,
+ attrs: AttributeSet?,
+ defStyleAttr: Int,
+ defStyleRes: Int,
+ ) : super(context, attrs, defStyleAttr, defStyleRes)
+
+ override fun setShouldBlockVisibilityChanges(block: Boolean) {
+ delegate.setShouldBlockVisibilityChanges(block)
+ }
+
+ override fun setVisibility(visibility: Int) {
+ delegate.setVisibility(visibility)
+ }
+
+ override fun setTransitionVisibility(visibility: Int) {
+ delegate.setTransitionVisibility(visibility)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
index f611c3e..5e8ce6d 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
@@ -25,6 +25,7 @@
import android.view.ViewStub
import android.widget.Button
import android.widget.TextView
+import androidx.activity.ComponentActivity
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
@@ -36,7 +37,6 @@
import com.android.systemui.controls.ui.ControlsActivity
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.settings.CurrentUserTracker
-import com.android.systemui.util.LifecycleActivity
import javax.inject.Inject
/**
@@ -47,7 +47,7 @@
private val broadcastDispatcher: BroadcastDispatcher,
private val customIconCache: CustomIconCache,
private val uiController: ControlsUiController
-) : LifecycleActivity() {
+) : ComponentActivity() {
companion object {
private const val TAG = "ControlsEditingActivity"
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index dca52a9..be572c5 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -32,6 +32,7 @@
import android.widget.FrameLayout
import android.widget.TextView
import android.widget.Toast
+import androidx.activity.ComponentActivity
import androidx.viewpager2.widget.ViewPager2
import com.android.systemui.Prefs
import com.android.systemui.R
@@ -44,7 +45,6 @@
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.settings.CurrentUserTracker
-import com.android.systemui.util.LifecycleActivity
import java.text.Collator
import java.util.concurrent.Executor
import java.util.function.Consumer
@@ -56,7 +56,7 @@
private val listingController: ControlsListingController,
private val broadcastDispatcher: BroadcastDispatcher,
private val uiController: ControlsUiController
-) : LifecycleActivity() {
+) : ComponentActivity() {
companion object {
private const val TAG = "ControlsFavoritingActivity"
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
index 8ad5099..b26615f 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
@@ -26,6 +26,7 @@
import android.view.ViewStub
import android.widget.Button
import android.widget.TextView
+import androidx.activity.ComponentActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
@@ -37,7 +38,6 @@
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.settings.CurrentUserTracker
-import com.android.systemui.util.LifecycleActivity
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -51,7 +51,7 @@
private val controlsController: ControlsController,
private val broadcastDispatcher: BroadcastDispatcher,
private val uiController: ControlsUiController
-) : LifecycleActivity() {
+) : ComponentActivity() {
companion object {
private const val TAG = "ControlsProviderSelectorActivity"
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
index f9e7f0e..b376455 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
@@ -30,6 +30,7 @@
import android.view.View
import android.widget.ImageView
import android.widget.TextView
+import androidx.activity.ComponentActivity
import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.controls.ControlsServiceInfo
@@ -38,14 +39,13 @@
import com.android.systemui.controls.ui.RenderInfo
import com.android.systemui.settings.CurrentUserTracker
import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.util.LifecycleActivity
import javax.inject.Inject
open class ControlsRequestDialog @Inject constructor(
private val controller: ControlsController,
private val broadcastDispatcher: BroadcastDispatcher,
private val controlsListingController: ControlsListingController
-) : LifecycleActivity(), DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
+) : ComponentActivity(), DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
companion object {
private const val TAG = "ControlsRequestDialog"
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
index 49f7584..77b6523 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
@@ -25,11 +25,10 @@
import android.view.ViewGroup
import android.view.WindowInsets
import android.view.WindowInsets.Type
-
+import androidx.activity.ComponentActivity
import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.controls.management.ControlsAnimations
-import com.android.systemui.util.LifecycleActivity
import javax.inject.Inject
/**
@@ -42,7 +41,7 @@
class ControlsActivity @Inject constructor(
private val uiController: ControlsUiController,
private val broadcastDispatcher: BroadcastDispatcher
-) : LifecycleActivity() {
+) : ComponentActivity() {
private lateinit var parent: ViewGroup
private lateinit var broadcastReceiver: BroadcastReceiver
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
index 8ba6f1c..d60a222 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
@@ -26,6 +26,7 @@
import com.android.systemui.screenshot.ActionProxyReceiver;
import com.android.systemui.screenshot.DeleteScreenshotReceiver;
import com.android.systemui.screenshot.SmartActionsReceiver;
+import com.android.systemui.volume.VolumePanelDialogReceiver;
import dagger.Binds;
import dagger.Module;
@@ -78,6 +79,15 @@
*/
@Binds
@IntoMap
+ @ClassKey(VolumePanelDialogReceiver.class)
+ public abstract BroadcastReceiver bindVolumePanelDialogReceiver(
+ VolumePanelDialogReceiver broadcastReceiver);
+
+ /**
+ *
+ */
+ @Binds
+ @IntoMap
@ClassKey(PeopleSpaceWidgetPinnedReceiver.class)
public abstract BroadcastReceiver bindPeopleSpaceWidgetPinnedReceiver(
PeopleSpaceWidgetPinnedReceiver broadcastReceiver);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
index a9e47c4..fbfc94a 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
@@ -26,6 +26,7 @@
import androidx.annotation.Nullable;
+import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.KeyguardViewController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
@@ -53,14 +54,13 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.dagger.StartCentralSurfacesModule;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryControllerImpl;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -168,10 +168,6 @@
abstract DockManager bindDockManager(DockManagerImpl dockManager);
@Binds
- abstract NotificationEntryManager.KeyguardEnvironment bindKeyguardEnvironment(
- KeyguardEnvironmentImpl keyguardEnvironment);
-
- @Binds
abstract ShadeController provideShadeController(ShadeControllerImpl shadeController);
@SysUISingleton
@@ -190,7 +186,10 @@
KeyguardBypassController bypassController,
GroupMembershipManager groupManager,
VisualStabilityProvider visualStabilityProvider,
- ConfigurationController configurationController) {
+ ConfigurationController configurationController,
+ @Main Handler handler,
+ AccessibilityManagerWrapper accessibilityManagerWrapper,
+ UiEventLogger uiEventLogger) {
return new HeadsUpManagerPhone(
context,
headsUpManagerLogger,
@@ -198,7 +197,10 @@
bypassController,
groupManager,
visualStabilityProvider,
- configurationController
+ configurationController,
+ handler,
+ accessibilityManagerWrapper,
+ uiEventLogger
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index 6db3e82..8bb27a7 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -17,6 +17,7 @@
package com.android.systemui.dagger
import com.android.keyguard.KeyguardBiometricLockoutLogger
+import com.android.systemui.ChooserSelector
import com.android.systemui.CoreStartable
import com.android.systemui.LatencyTester
import com.android.systemui.ScreenDecorations
@@ -60,6 +61,12 @@
@ClassKey(AuthController::class)
abstract fun bindAuthController(service: AuthController): CoreStartable
+ /** Inject into ChooserCoreStartable. */
+ @Binds
+ @IntoMap
+ @ClassKey(ChooserSelector::class)
+ abstract fun bindChooserSelector(sysui: ChooserSelector): CoreStartable
+
/** Inject into ClipboardListener. */
@Binds
@IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index e549a96..a0ecd22 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -49,8 +49,12 @@
import com.android.systemui.people.PeopleModule;
import com.android.systemui.plugins.BcSmartspaceDataPlugin;
import com.android.systemui.privacy.PrivacyModule;
+import com.android.systemui.qs.FgsManagerController;
+import com.android.systemui.qs.FgsManagerControllerImpl;
+import com.android.systemui.qs.footer.dagger.FooterActionsModule;
import com.android.systemui.recents.Recents;
import com.android.systemui.screenshot.dagger.ScreenshotModule;
+import com.android.systemui.security.data.repository.SecurityRepositoryModule;
import com.android.systemui.settings.dagger.MultiUserUtilsModule;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.smartspace.dagger.SmartspaceModule;
@@ -61,7 +65,6 @@
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
@@ -122,6 +125,7 @@
DemoModeModule.class,
FalsingModule.class,
FlagsModule.class,
+ FooterActionsModule.class,
LogModule.class,
MediaProjectionModule.class,
PeopleHubModule.class,
@@ -132,6 +136,7 @@
ScreenshotModule.class,
SensorModule.class,
MultiUserUtilsModule.class,
+ SecurityRepositoryModule.class,
SettingsUtilModule.class,
SmartRepliesInflationModule.class,
SmartspaceModule.class,
@@ -219,11 +224,9 @@
NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
- NotificationGroupManagerLegacy groupManager,
CommonNotifCollection notifCollection,
NotifPipeline notifPipeline,
SysUiState sysUiState,
- DumpManager dumpManager,
@Main Executor sysuiMainExecutor) {
return Optional.ofNullable(BubblesManager.create(context,
bubblesOptional,
@@ -237,7 +240,6 @@
interruptionStateProvider,
zenModeController,
notifUserManager,
- groupManager,
notifCollection,
notifPipeline,
sysUiState,
@@ -258,4 +260,7 @@
return Optional.empty();
}
}
+
+ @Binds
+ abstract FgsManagerController bindFgsManagerController(FgsManagerControllerImpl impl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt
new file mode 100644
index 0000000..cbed21c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.decor
+
+import android.content.res.Resources
+import android.util.Log
+import android.view.Display
+import android.view.DisplayCutout
+import android.view.DisplayInfo
+
+class CutoutDecorProviderFactory constructor(
+ private val res: Resources,
+ private val display: Display?,
+) : DecorProviderFactory() {
+
+ val displayInfo = DisplayInfo()
+
+ override val hasProviders: Boolean
+ get() {
+ display?.getDisplayInfo(displayInfo) ?: run {
+ Log.w(TAG, "display is null, can't update displayInfo")
+ }
+ return DisplayCutout.getFillBuiltInDisplayCutout(res, displayInfo.uniqueId)
+ }
+
+ override val providers: List<DecorProvider>
+ get() {
+ if (!hasProviders) {
+ return emptyList()
+ }
+
+ return ArrayList<DecorProvider>().also { list ->
+ // We need to update displayInfo before using it, but it has already updated during
+ // accessing hasProviders field
+ displayInfo.displayCutout?.getBoundBaseOnCurrentRotation()?.let { bounds ->
+ for (bound in bounds) {
+ list.add(
+ CutoutDecorProviderImpl(bound.baseOnRotation0(displayInfo.rotation))
+ )
+ }
+ }
+ }
+ }
+}
+
+private const val TAG = "CutoutDecorProviderFactory"
diff --git a/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt
new file mode 100644
index 0000000..991b54e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.decor
+
+import android.content.Context
+import android.view.DisplayCutout
+import android.view.Surface
+import android.view.View
+import android.view.ViewGroup
+import com.android.systemui.R
+import com.android.systemui.ScreenDecorations.DisplayCutoutView
+
+class CutoutDecorProviderImpl(
+ @DisplayCutout.BoundsPosition override val alignedBound: Int
+) : BoundDecorProvider() {
+
+ override val viewId: Int = when (alignedBound) {
+ DisplayCutout.BOUNDS_POSITION_TOP -> R.id.display_cutout
+ DisplayCutout.BOUNDS_POSITION_LEFT -> R.id.display_cutout_left
+ DisplayCutout.BOUNDS_POSITION_RIGHT -> R.id.display_cutout_right
+ else -> R.id.display_cutout_bottom
+ }
+
+ override fun inflateView(
+ context: Context,
+ parent: ViewGroup,
+ @Surface.Rotation rotation: Int,
+ tintColor: Int
+ ): View {
+ return DisplayCutoutView(context, alignedBound).also { view ->
+ view.id = viewId
+ view.setColor(tintColor)
+ parent.addView(view)
+ view.updateRotation(rotation)
+ }
+ }
+
+ override fun onReloadResAndMeasure(
+ view: View,
+ reloadToken: Int,
+ @Surface.Rotation rotation: Int,
+ tintColor: Int,
+ displayUniqueId: String?
+ ) {
+ (view as? DisplayCutoutView)?.let { cutoutView ->
+ cutoutView.setColor(tintColor)
+ cutoutView.updateRotation(rotation)
+ cutoutView.onDisplayChanged(displayUniqueId)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
index 169b50e..0681f50 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
@@ -32,8 +32,8 @@
abstract val viewId: Int
/** The number of total aligned bounds */
- val numOfAlignedEdge: Int
- get() = alignedBounds.size
+ val numOfAlignedBound: Int
+ get() = alignedBounds.size
/** The aligned bounds for the view which is created through inflateView() */
abstract val alignedBounds: List<Int>
@@ -46,25 +46,19 @@
view: View,
reloadToken: Int,
@Surface.Rotation rotation: Int,
- displayUniqueId: String? = null
+ tintColor: Int,
+ displayUniqueId: String?
)
/** Inflate view into parent as current rotation */
abstract fun inflateView(
context: Context,
parent: ViewGroup,
- @Surface.Rotation rotation: Int
+ @Surface.Rotation rotation: Int,
+ tintColor: Int
): View
-}
-/**
- * Split list to 2 list, and return it back as Pair<>. The providers on the first list contains this
- * alignedBound element. The providers on the second list do not contain this alignedBound element
- */
-fun List<DecorProvider>.partitionAlignedBound(
- @DisplayCutout.BoundsPosition alignedBound: Int
-): Pair<List<DecorProvider>, List<DecorProvider>> {
- return partition { it.alignedBounds.contains(alignedBound) }
+ override fun toString() = "${javaClass.simpleName}{alignedBounds=$alignedBounds}"
}
/**
@@ -92,3 +86,61 @@
listOf(alignedBound)
}
}
+
+/**
+ * Split list to 2 sub-lists, and return it back as Pair<>. The providers on the first list contains
+ * this alignedBound element. The providers on the second list do not contain this alignedBound
+ * element.
+ */
+fun List<DecorProvider>.partitionAlignedBound(
+ @DisplayCutout.BoundsPosition alignedBound: Int
+): Pair<List<DecorProvider>, List<DecorProvider>> {
+ return partition { it.alignedBounds.contains(alignedBound) }
+}
+
+/**
+ * Get the proper bound from DecorProvider list
+ * Time complexity: O(N), N is the number of providers
+ *
+ * Choose order
+ * 1. Return null if list is empty
+ * 2. If list contains BoundDecorProvider, return its alignedBound[0] because it is a must-have
+ * bound
+ * 3. Return the bound with most DecorProviders
+ */
+fun List<DecorProvider>.getProperBound(): Int? {
+ // Return null if list is empty
+ if (isEmpty()) {
+ return null
+ }
+
+ // Choose alignedBounds[0] of BoundDecorProvider if any
+ val singleBoundProvider = firstOrNull { it.numOfAlignedBound == 1 }
+ if (singleBoundProvider != null) {
+ return singleBoundProvider.alignedBounds[0]
+ }
+
+ // Return the bound with most DecorProviders
+ val boundCount = intArrayOf(0, 0, 0, 0)
+ for (provider in this) {
+ for (bound in provider.alignedBounds) {
+ boundCount[bound]++
+ }
+ }
+ var maxCount = 0
+ var maxCountBound: Int? = null
+ val bounds = arrayOf(
+ // Put top and bottom at first to get the highest priority to be chosen
+ DisplayCutout.BOUNDS_POSITION_TOP,
+ DisplayCutout.BOUNDS_POSITION_BOTTOM,
+ DisplayCutout.BOUNDS_POSITION_LEFT,
+ DisplayCutout.BOUNDS_POSITION_RIGHT
+ )
+ for (bound in bounds) {
+ if (boundCount[bound] > maxCount) {
+ maxCountBound = bound
+ maxCount = boundCount[bound]
+ }
+ }
+ return maxCountBound
+}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
index 81d3d6c..ec0013b 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
@@ -32,8 +32,8 @@
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.FaceScanningOverlay
import com.android.systemui.biometrics.AuthController
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -55,7 +55,7 @@
override val hasProviders: Boolean
get() {
if (!featureFlags.isEnabled(Flags.FACE_SCANNING_ANIM) ||
- authController.faceAuthSensorLocation == null) {
+ authController.faceSensorLocation == null) {
return false
}
@@ -115,19 +115,25 @@
override fun onReloadResAndMeasure(
view: View,
reloadToken: Int,
- rotation: Int,
+ @Surface.Rotation rotation: Int,
+ tintColor: Int,
displayUniqueId: String?
) {
(view.layoutParams as FrameLayout.LayoutParams).let {
updateLayoutParams(it, rotation)
view.layoutParams = it
+ (view as? FaceScanningOverlay)?.let { overlay ->
+ overlay.setColor(tintColor)
+ overlay.onDisplayChanged(displayUniqueId)
+ }
}
}
override fun inflateView(
context: Context,
parent: ViewGroup,
- @Surface.Rotation rotation: Int
+ @Surface.Rotation rotation: Int,
+ tintColor: Int
): View {
val view = FaceScanningOverlay(
context,
@@ -137,6 +143,7 @@
mainExecutor
)
view.id = viewId
+ view.setColor(tintColor)
FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT).let {
updateLayoutParams(it, rotation)
@@ -152,7 +159,7 @@
layoutParams.let { lp ->
lp.width = ViewGroup.LayoutParams.MATCH_PARENT
lp.height = ViewGroup.LayoutParams.MATCH_PARENT
- authController.faceAuthSensorLocation?.y?.let { faceAuthSensorHeight ->
+ authController.faceSensorLocation?.y?.let { faceAuthSensorHeight ->
val faceScanningHeight = (faceAuthSensorHeight * 2).toInt()
when (rotation) {
Surface.ROTATION_0, Surface.ROTATION_180 ->
diff --git a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
index 3c0748e..45b8a08 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
@@ -34,9 +34,10 @@
fun addDecorProvider(
decorProvider: DecorProvider,
- @Surface.Rotation rotation: Int
+ @Surface.Rotation rotation: Int,
+ tintColor: Int
) {
- val view = decorProvider.inflateView(context, rootView, rotation)
+ val view = decorProvider.inflateView(context, rootView, rotation, tintColor)
viewProviderMap[decorProvider.viewId] = Pair(view, decorProvider)
}
@@ -69,7 +70,7 @@
*/
fun hasSameProviders(newProviders: List<DecorProvider>): Boolean {
return (newProviders.size == viewProviderMap.size) &&
- newProviders.all { getView(it.viewId) != null }
+ newProviders.all { getView(it.viewId) != null }
}
/**
@@ -82,23 +83,28 @@
filterIds: Array<Int>? = null,
reloadToken: Int,
@Surface.Rotation rotation: Int,
+ tintColor: Int,
displayUniqueId: String? = null
) {
filterIds?.forEach { id ->
viewProviderMap[id]?.let {
it.second.onReloadResAndMeasure(
- view = it.first,
- reloadToken = reloadToken,
- displayUniqueId = displayUniqueId,
- rotation = rotation)
+ view = it.first,
+ reloadToken = reloadToken,
+ rotation = rotation,
+ tintColor = tintColor,
+ displayUniqueId = displayUniqueId
+ )
}
} ?: run {
viewProviderMap.values.forEach {
it.second.onReloadResAndMeasure(
- view = it.first,
- reloadToken = reloadToken,
- displayUniqueId = displayUniqueId,
- rotation = rotation)
+ view = it.first,
+ reloadToken = reloadToken,
+ rotation = rotation,
+ tintColor = tintColor,
+ displayUniqueId = displayUniqueId
+ )
}
}
}
@@ -108,7 +114,8 @@
pw.println(" rootView=$rootView")
for (i in 0 until rootView.childCount) {
val child = rootView.getChildAt(i)
- pw.println(" child[$i]=$child")
+ val provider = viewProviderMap[child.id]?.second
+ pw.println(" child[$i]=$child $provider")
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
index 9f624b3..e18c0e1 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
@@ -20,9 +20,9 @@
import android.content.res.Resources
import android.view.DisplayCutout
import android.view.LayoutInflater
+import android.view.Surface
import android.view.View
import android.view.ViewGroup
-import android.view.Surface
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
@@ -85,6 +85,7 @@
view: View,
reloadToken: Int,
rotation: Int,
+ tintColor: Int,
displayUniqueId: String?
) {
// Do nothing here because it is handled inside PrivacyDotViewController
@@ -93,7 +94,8 @@
override fun inflateView(
context: Context,
parent: ViewGroup,
- @Surface.Rotation rotation: Int
+ @Surface.Rotation rotation: Int,
+ tintColor: Int
): View {
LayoutInflater.from(context).inflate(layoutId, parent, true)
return parent.getChildAt(parent.childCount - 1 /* latest new added child */)
diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
index e316722..8156797 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
@@ -17,6 +17,7 @@
package com.android.systemui.decor
import android.content.Context
+import android.content.res.ColorStateList
import android.view.DisplayCutout
import android.view.Gravity
import android.view.Surface
@@ -38,12 +39,13 @@
override fun inflateView(
context: Context,
parent: ViewGroup,
- @Surface.Rotation rotation: Int
+ @Surface.Rotation rotation: Int,
+ tintColor: Int
): View {
return ImageView(context).also { view ->
// View
view.id = viewId
- initView(view, rotation)
+ initView(view, rotation, tintColor)
// LayoutParams
val layoutSize = if (isTop) {
@@ -52,31 +54,36 @@
roundedCornerResDelegate.bottomRoundedSize
}
val params = FrameLayout.LayoutParams(
- layoutSize.width,
- layoutSize.height,
- alignedBound1.toLayoutGravity(rotation) or
- alignedBound2.toLayoutGravity(rotation))
+ layoutSize.width,
+ layoutSize.height,
+ alignedBound1.toLayoutGravity(rotation) or alignedBound2.toLayoutGravity(rotation)
+ )
// AddView
parent.addView(view, params)
}
}
- private fun initView(view: ImageView, @Surface.Rotation rotation: Int) {
+ private fun initView(
+ view: ImageView,
+ @Surface.Rotation rotation: Int,
+ tintColor: Int
+ ) {
view.setRoundedCornerImage(roundedCornerResDelegate, isTop)
view.adjustRotation(alignedBounds, rotation)
- view.imageTintList = roundedCornerResDelegate.colorTintList
+ view.imageTintList = ColorStateList.valueOf(tintColor)
}
override fun onReloadResAndMeasure(
view: View,
reloadToken: Int,
@Surface.Rotation rotation: Int,
+ tintColor: Int,
displayUniqueId: String?
) {
roundedCornerResDelegate.updateDisplayUniqueId(displayUniqueId, reloadToken)
- initView((view as ImageView), rotation)
+ initView((view as ImageView), rotation, tintColor)
val layoutSize = if (isTop) {
roundedCornerResDelegate.topRoundedSize
@@ -87,7 +94,7 @@
it.width = layoutSize.width
it.height = layoutSize.height
it.gravity = alignedBound1.toLayoutGravity(rotation) or
- alignedBound2.toLayoutGravity(rotation)
+ alignedBound2.toLayoutGravity(rotation)
view.setLayoutParams(it)
}
}
@@ -134,10 +141,10 @@
setImageDrawable(drawable)
} else {
setImageResource(
- if (isTop)
- R.drawable.rounded_corner_top
- else
- R.drawable.rounded_corner_bottom
+ if (isTop)
+ R.drawable.rounded_corner_top
+ else
+ R.drawable.rounded_corner_bottom
)
}
}
@@ -187,4 +194,4 @@
this.rotation = newRotation
this.scaleX = newScaleX
this.scaleY = newScaleY
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
index b5a0cfc..a252864 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
@@ -18,9 +18,7 @@
import android.annotation.ArrayRes
import android.annotation.DrawableRes
-import android.content.res.ColorStateList
import android.content.res.Resources
-import android.graphics.Color
import android.graphics.drawable.Drawable
import android.util.DisplayUtils
import android.util.Size
@@ -57,8 +55,6 @@
var bottomRoundedSize = Size(0, 0)
private set
- var colorTintList = ColorStateList.valueOf(Color.BLACK)
-
var tuningSizeFactor: Int? = null
set(value) {
if (field == value) {
@@ -107,19 +103,19 @@
val hasDefaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId) > 0
hasTop = hasDefaultRadius ||
- (RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId) > 0)
+ (RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId) > 0)
hasBottom = hasDefaultRadius ||
- (RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId) > 0)
+ (RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId) > 0)
topRoundedDrawable = getDrawable(
- displayConfigIndex = configIdx,
- arrayResId = R.array.config_roundedCornerTopDrawableArray,
- backupDrawableId = R.drawable.rounded_corner_top
+ displayConfigIndex = configIdx,
+ arrayResId = R.array.config_roundedCornerTopDrawableArray,
+ backupDrawableId = R.drawable.rounded_corner_top
)
bottomRoundedDrawable = getDrawable(
- displayConfigIndex = configIdx,
- arrayResId = R.array.config_roundedCornerBottomDrawableArray,
- backupDrawableId = R.drawable.rounded_corner_bottom
+ displayConfigIndex = configIdx,
+ arrayResId = R.array.config_roundedCornerBottomDrawableArray,
+ backupDrawableId = R.drawable.rounded_corner_bottom
)
}
@@ -147,13 +143,15 @@
if (physicalPixelDisplaySizeRatio != 1f) {
if (topRoundedSize.width != 0) {
topRoundedSize = Size(
- (physicalPixelDisplaySizeRatio * topRoundedSize.width + 0.5f).toInt(),
- (physicalPixelDisplaySizeRatio * topRoundedSize.height + 0.5f).toInt())
+ (physicalPixelDisplaySizeRatio * topRoundedSize.width + 0.5f).toInt(),
+ (physicalPixelDisplaySizeRatio * topRoundedSize.height + 0.5f).toInt()
+ )
}
if (bottomRoundedSize.width != 0) {
bottomRoundedSize = Size(
- (physicalPixelDisplaySizeRatio * bottomRoundedSize.width + 0.5f).toInt(),
- (physicalPixelDisplaySizeRatio * bottomRoundedSize.height + 0.5f).toInt())
+ (physicalPixelDisplaySizeRatio * bottomRoundedSize.width + 0.5f).toInt(),
+ (physicalPixelDisplaySizeRatio * bottomRoundedSize.height + 0.5f).toInt()
+ )
}
}
}
@@ -180,8 +178,9 @@
pw.println(" hasTop=$hasTop")
pw.println(" hasBottom=$hasBottom")
pw.println(" topRoundedSize(w,h)=(${topRoundedSize.width},${topRoundedSize.height})")
- pw.println(" bottomRoundedSize(w,h)=(${bottomRoundedSize.width}," +
- "${bottomRoundedSize.height})")
+ pw.println(
+ " bottomRoundedSize(w,h)=(${bottomRoundedSize.width},${bottomRoundedSize.height})"
+ )
pw.println(" physicalPixelDisplaySizeRatio=$physicalPixelDisplaySizeRatio")
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 32bc9de..ae41215 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -269,9 +269,10 @@
return mPulseReason;
}
- /** Requests the PowerManager to wake up now. */
- public void wakeUp() {
- mDozeService.requestWakeUp();
+ /** Requests the PowerManager to wake up now.
+ * @param reason {@link DozeLog.Reason} that woke up the device.*/
+ public void wakeUp(@DozeLog.Reason int reason) {
+ mDozeService.requestWakeUp(reason);
}
public boolean isExecutingTransition() {
@@ -469,7 +470,7 @@
void setDozeScreenState(int state);
/** Request waking up. */
- void requestWakeUp();
+ void requestWakeUp(@DozeLog.Reason int reason);
/** Set screen brightness */
void setDozeScreenBrightness(int brightness);
@@ -492,8 +493,8 @@
}
@Override
- public void requestWakeUp() {
- mDelegate.requestWakeUp();
+ public void requestWakeUp(@DozeLog.Reason int reason) {
+ mDelegate.requestWakeUp(reason);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index b06bf89..a2eb4e3 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -113,10 +113,10 @@
}
@Override
- public void requestWakeUp() {
+ public void requestWakeUp(@DozeLog.Reason int reason) {
PowerManager pm = getSystemService(PowerManager.class);
pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
- "com.android.systemui:NODOZE");
+ "com.android.systemui:NODOZE " + DozeLog.reasonToString(reason));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 0014d6b..00ac8bc 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -16,6 +16,8 @@
package com.android.systemui.doze;
+import static android.app.StatusBarManager.SESSION_KEYGUARD;
+
import static com.android.systemui.doze.DozeMachine.State.DOZE_SUSPEND_TRIGGERS;
import static com.android.systemui.doze.DozeMachine.State.FINISH;
import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;
@@ -34,19 +36,19 @@
import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
import com.android.systemui.doze.DozeMachine.State;
import com.android.systemui.doze.dagger.DozeScope;
+import com.android.systemui.log.SessionTracker;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.Assert;
-import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.util.sensors.ProximityCheck;
import com.android.systemui.util.sensors.ProximitySensor;
@@ -80,6 +82,7 @@
private static final int PROXIMITY_TIMEOUT_DELAY_MS = 500;
private final Context mContext;
+ private final SessionTracker mSessionTracker;
private DozeMachine mMachine;
private final DozeLog mDozeLog;
private final DozeSensors mDozeSensors;
@@ -95,10 +98,8 @@
private final ProximityCheck mProxCheck;
private final BroadcastDispatcher mBroadcastDispatcher;
private final AuthController mAuthController;
- private final DelayableExecutor mMainExecutor;
private final KeyguardStateController mKeyguardStateController;
private final UiEventLogger mUiEventLogger;
- private final DevicePostureController mDevicePostureController;
private long mNotificationPulseTime;
private boolean mPulsePending;
@@ -185,8 +186,8 @@
ProximityCheck proxCheck,
DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher,
SecureSettings secureSettings, AuthController authController,
- @Main DelayableExecutor mainExecutor,
UiEventLogger uiEventLogger,
+ SessionTracker sessionTracker,
KeyguardStateController keyguardStateController,
DevicePostureController devicePostureController) {
mContext = context;
@@ -196,8 +197,8 @@
mSensorManager = sensorManager;
mWakeLock = wakeLock;
mAllowPulseTriggers = true;
+ mSessionTracker = sessionTracker;
- mDevicePostureController = devicePostureController;
mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters,
config, wakeLock, this::onSensor, this::onProximityFar, dozeLog, proximitySensor,
secureSettings, authController, devicePostureController);
@@ -206,14 +207,9 @@
mDozeLog = dozeLog;
mBroadcastDispatcher = broadcastDispatcher;
mAuthController = authController;
- mMainExecutor = mainExecutor;
mUiEventLogger = uiEventLogger;
mKeyguardStateController = keyguardStateController;
}
- private final DevicePostureController.Callback mDevicePostureCallback =
- posture -> {
-
- };
@Override
public void setDozeMachine(DozeMachine dozeMachine) {
@@ -271,7 +267,7 @@
mProxCheck.check(PROXIMITY_TIMEOUT_DELAY_MS, near -> {
final long end = SystemClock.uptimeMillis();
mDozeLog.traceProximityResult(
- near == null ? false : near,
+ near != null && near,
end - start,
reason);
callback.accept(near);
@@ -354,17 +350,17 @@
return mKeyguardStateController.isOccluded();
}
- private void gentleWakeUp(int reason) {
+ private void gentleWakeUp(@DozeLog.Reason int reason) {
// Log screen wake up reason (lift/pickup, tap, double-tap)
Optional.ofNullable(DozingUpdateUiEvent.fromReason(reason))
- .ifPresent(mUiEventLogger::log);
+ .ifPresent(uiEventEnum -> mUiEventLogger.log(uiEventEnum, getKeyguardSessionId()));
if (mDozeParameters.getDisplayNeedsBlanking()) {
// Let's prepare the display to wake-up by drawing black.
// This will cover the hardware wake-up sequence, where the display
// becomes black for a few frames.
mDozeHost.setAodDimmingScrim(1f);
}
- mMachine.wakeUp();
+ mMachine.wakeUp(reason);
}
private void onProximityFar(boolean far) {
@@ -384,11 +380,10 @@
if (state == DozeMachine.State.DOZE_PULSING
|| state == DozeMachine.State.DOZE_PULSING_BRIGHT) {
- boolean ignoreTouch = near;
if (DEBUG) {
- Log.i(TAG, "Prox changed, ignore touch = " + ignoreTouch);
+ Log.i(TAG, "Prox changed, ignore touch = " + near);
}
- mDozeHost.onIgnoreTouchWhilePulsing(ignoreTouch);
+ mDozeHost.onIgnoreTouchWhilePulsing(near);
}
if (far && (paused || pausing)) {
@@ -424,7 +419,8 @@
mMachine.requestState(DozeMachine.State.DOZE_AOD);
// Log sensor triggered
Optional.ofNullable(DozingUpdateUiEvent.fromReason(reason))
- .ifPresent(mUiEventLogger::log);
+ .ifPresent(uiEventEnum ->
+ mUiEventLogger.log(uiEventEnum, getKeyguardSessionId()));
}
}, false /* alreadyPerformedProxCheck */, reason);
} else {
@@ -564,7 +560,7 @@
// Logs request pulse reason on AOD screen.
Optional.ofNullable(DozingUpdateUiEvent.fromReason(reason))
- .ifPresent(mUiEventLogger::log);
+ .ifPresent(uiEventEnum -> mUiEventLogger.log(uiEventEnum, getKeyguardSessionId()));
}
private boolean canPulse() {
@@ -583,6 +579,11 @@
mMachine.requestPulse(reason);
}
+ @Nullable
+ private InstanceId getKeyguardSessionId() {
+ return mSessionTracker.getSessionId(SESSION_KEYGUARD);
+ }
+
@Override
public void dump(PrintWriter pw) {
pw.println(" mAodInterruptRunnable=" + mAodInterruptRunnable);
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationTypesUpdater.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationTypesUpdater.java
index 83249aa..bbcab60 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationTypesUpdater.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationTypesUpdater.java
@@ -69,7 +69,7 @@
};
mSecureSettings.registerContentObserverForUser(
- Settings.Secure.SCREENSAVER_ENABLED_COMPLICATIONS,
+ Settings.Secure.SCREENSAVER_COMPLICATIONS_ENABLED,
settingsObserver,
UserHandle.myUserId());
settingsObserver.onChange(false);
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
index d5db63d..75a97de 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
@@ -35,7 +35,7 @@
public class ComplicationUtils {
/**
* Converts a {@link com.android.settingslib.dream.DreamBackend.ComplicationType} to
- * {@link ComplicationType}.
+ * {@link Complication.ComplicationType}.
*/
@Complication.ComplicationType
public static int convertComplicationType(@DreamBackend.ComplicationType int type) {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextClock.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextClock.java
new file mode 100644
index 0000000..653f4dc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextClock.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.widget.TextClock;
+
+import com.android.systemui.R;
+
+/**
+ * Extension of {@link TextClock} which draws two shadows on the text (ambient and key shadows)
+ */
+public class DoubleShadowTextClock extends TextClock {
+ private final float mAmbientShadowBlur;
+ private final int mAmbientShadowColor;
+ private final float mKeyShadowBlur;
+ private final float mKeyShadowOffsetX;
+ private final float mKeyShadowOffsetY;
+ private final int mKeyShadowColor;
+ private final float mAmbientShadowOffsetX;
+ private final float mAmbientShadowOffsetY;
+
+ public DoubleShadowTextClock(Context context) {
+ this(context, null);
+ }
+
+ public DoubleShadowTextClock(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public DoubleShadowTextClock(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mKeyShadowBlur = context.getResources()
+ .getDimensionPixelSize(R.dimen.dream_overlay_clock_key_text_shadow_radius);
+ mKeyShadowOffsetX = context.getResources()
+ .getDimensionPixelSize(R.dimen.dream_overlay_clock_key_text_shadow_dx);
+ mKeyShadowOffsetY = context.getResources()
+ .getDimensionPixelSize(R.dimen.dream_overlay_clock_key_text_shadow_dy);
+ mKeyShadowColor = context.getResources().getColor(
+ R.color.dream_overlay_clock_key_text_shadow_color);
+ mAmbientShadowBlur = context.getResources()
+ .getDimensionPixelSize(R.dimen.dream_overlay_clock_ambient_text_shadow_radius);
+ mAmbientShadowColor = context.getResources().getColor(
+ R.color.dream_overlay_clock_ambient_text_shadow_color);
+ mAmbientShadowOffsetX = context.getResources()
+ .getDimensionPixelSize(R.dimen.dream_overlay_clock_ambient_text_shadow_dx);
+ mAmbientShadowOffsetY = context.getResources()
+ .getDimensionPixelSize(R.dimen.dream_overlay_clock_ambient_text_shadow_dy);
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ // We enhance the shadow by drawing the shadow twice
+ getPaint().setShadowLayer(mAmbientShadowBlur, mAmbientShadowOffsetX, mAmbientShadowOffsetY,
+ mAmbientShadowColor);
+ super.onDraw(canvas);
+ canvas.save();
+ canvas.clipRect(getScrollX(), getScrollY() + getExtendedPaddingTop(),
+ getScrollX() + getWidth(),
+ getScrollY() + getHeight());
+
+ getPaint().setShadowLayer(
+ mKeyShadowBlur, mKeyShadowOffsetX, mKeyShadowOffsetY, mKeyShadowColor);
+ super.onDraw(canvas);
+ canvas.restore();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java
index 1c72e49..2503d3c 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java
@@ -151,8 +151,8 @@
* Controls behavior of the dream complication.
*/
static class DreamHomeControlsChipViewController extends ViewController<ImageView> {
- private static final boolean DEBUG = false;
private static final String TAG = "DreamHomeControlsCtrl";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final ActivityStarter mActivityStarter;
private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamMediaEntryComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamMediaEntryComplication.java
new file mode 100644
index 0000000..21a51d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamMediaEntryComplication.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication;
+
+import static com.android.systemui.dreams.complication.dagger.DreamMediaEntryComplicationComponent.DreamMediaEntryModule.DREAM_MEDIA_ENTRY_VIEW;
+import static com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule.DREAM_MEDIA_ENTRY_LAYOUT_PARAMS;
+
+import android.util.Log;
+import android.view.View;
+
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.dreams.complication.dagger.DreamMediaEntryComplicationComponent;
+import com.android.systemui.media.dream.MediaDreamComplication;
+import com.android.systemui.util.ViewController;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * A dream complication that shows a media entry chip to launch media control view.
+ */
+public class DreamMediaEntryComplication implements Complication {
+ private final DreamMediaEntryComplicationComponent.Factory mComponentFactory;
+
+ @Inject
+ public DreamMediaEntryComplication(
+ DreamMediaEntryComplicationComponent.Factory componentFactory) {
+ mComponentFactory = componentFactory;
+ }
+
+ @Override
+ public ViewHolder createView(ComplicationViewModel model) {
+ return mComponentFactory.create().getViewHolder();
+ }
+
+ /**
+ * Contains values/logic associated with the dream complication view.
+ */
+ public static class DreamMediaEntryViewHolder implements ViewHolder {
+ private final View mView;
+ private final ComplicationLayoutParams mLayoutParams;
+ private final DreamMediaEntryViewController mViewController;
+
+ @Inject
+ DreamMediaEntryViewHolder(
+ DreamMediaEntryViewController dreamMediaEntryViewController,
+ @Named(DREAM_MEDIA_ENTRY_VIEW) View view,
+ @Named(DREAM_MEDIA_ENTRY_LAYOUT_PARAMS) ComplicationLayoutParams layoutParams
+ ) {
+ mView = view;
+ mLayoutParams = layoutParams;
+ mViewController = dreamMediaEntryViewController;
+ mViewController.init();
+ }
+
+ @Override
+ public View getView() {
+ return mView;
+ }
+
+ @Override
+ public ComplicationLayoutParams getLayoutParams() {
+ return mLayoutParams;
+ }
+ }
+
+ /**
+ * Controls behavior of the dream complication.
+ */
+ static class DreamMediaEntryViewController extends ViewController<View> {
+ private static final String TAG = "DreamMediaEntryVwCtrl";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final DreamOverlayStateController mDreamOverlayStateController;
+ private final MediaDreamComplication mMediaComplication;
+
+ private boolean mMediaComplicationAdded;
+
+ @Inject
+ DreamMediaEntryViewController(
+ @Named(DREAM_MEDIA_ENTRY_VIEW) View view,
+ DreamOverlayStateController dreamOverlayStateController,
+ MediaDreamComplication mediaComplication) {
+ super(view);
+ mDreamOverlayStateController = dreamOverlayStateController;
+ mMediaComplication = mediaComplication;
+ mView.setOnClickListener(this::onClickMediaEntry);
+ }
+
+ @Override
+ protected void onViewAttached() {
+ }
+
+ @Override
+ protected void onViewDetached() {
+ removeMediaComplication();
+ }
+
+ private void onClickMediaEntry(View v) {
+ if (DEBUG) Log.d(TAG, "media entry complication tapped");
+
+ if (!mMediaComplicationAdded) {
+ addMediaComplication();
+ } else {
+ removeMediaComplication();
+ }
+ }
+
+ private void addMediaComplication() {
+ mView.setSelected(true);
+ mDreamOverlayStateController.addComplication(mMediaComplication);
+ mMediaComplicationAdded = true;
+ }
+
+ private void removeMediaComplication() {
+ mView.setSelected(false);
+ mDreamOverlayStateController.removeComplication(mMediaComplication);
+ mMediaComplicationAdded = false;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
index 567bdbc..a981f25 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
@@ -70,11 +70,7 @@
new BcSmartspaceDataPlugin.SmartspaceTargetListener() {
@Override
public void onSmartspaceTargetsUpdated(List<? extends Parcelable> targets) {
- if (!targets.isEmpty()) {
- mDreamOverlayStateController.addComplication(mComplication);
- } else {
- mDreamOverlayStateController.removeComplication(mComplication);
- }
+ mDreamOverlayStateController.addComplication(mComplication);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamMediaEntryComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamMediaEntryComplicationComponent.java
new file mode 100644
index 0000000..ed05daf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamMediaEntryComplicationComponent.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.dreams.complication.DreamMediaEntryComplication;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Named;
+import javax.inject.Scope;
+
+import dagger.Module;
+import dagger.Provides;
+import dagger.Subcomponent;
+
+/**
+ * Responsible for generating dependencies for the {@link DreamMediaEntryComplication}.
+ */
+@Subcomponent(modules = DreamMediaEntryComplicationComponent.DreamMediaEntryModule.class)
+@DreamMediaEntryComplicationComponent.DreamMediaEntryComplicationScope
+public interface DreamMediaEntryComplicationComponent {
+ /**
+ * Creates a view holder for the media entry complication.
+ */
+ DreamMediaEntryComplication.DreamMediaEntryViewHolder getViewHolder();
+
+ /**
+ * Scope of the media entry complication.
+ */
+ @Documented
+ @Retention(RUNTIME)
+ @Scope
+ @interface DreamMediaEntryComplicationScope {}
+
+ /**
+ * Factory that generates a {@link DreamMediaEntryComplicationComponent}.
+ */
+ @Subcomponent.Factory
+ interface Factory {
+ DreamMediaEntryComplicationComponent create();
+ }
+
+ /**
+ * Scoped injected values for the {@link DreamMediaEntryComplicationComponent}.
+ */
+ @Module
+ interface DreamMediaEntryModule {
+ String DREAM_MEDIA_ENTRY_VIEW = "dream_media_entry_view";
+
+ /**
+ * Provides the dream media entry view.
+ */
+ @Provides
+ @DreamMediaEntryComplicationScope
+ @Named(DREAM_MEDIA_ENTRY_VIEW)
+ static View provideMediaEntryView(LayoutInflater layoutInflater) {
+ return (View) layoutInflater.inflate(R.layout.dream_overlay_media_entry_chip, null);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
index eb07238..759d6ec 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
@@ -38,15 +38,19 @@
},
subcomponents = {
DreamHomeControlsComplicationComponent.class,
+ DreamMediaEntryComplicationComponent.class
})
public interface RegisteredComplicationsModule {
String DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS = "time_complication_layout_params";
String DREAM_SMARTSPACE_LAYOUT_PARAMS = "smartspace_layout_params";
String DREAM_HOME_CONTROLS_CHIP_LAYOUT_PARAMS = "home_controls_chip_layout_params";
+ String DREAM_MEDIA_ENTRY_LAYOUT_PARAMS = "media_entry_layout_params";
int DREAM_CLOCK_TIME_COMPLICATION_WEIGHT = 1;
int DREAM_SMARTSPACE_COMPLICATION_WEIGHT = 0;
+ int DREAM_MEDIA_COMPLICATION_WEIGHT = -1;
int DREAM_HOME_CONTROLS_CHIP_COMPLICATION_WEIGHT = 1;
+ int DREAM_MEDIA_ENTRY_COMPLICATION_WEIGHT = 0;
/**
* Provides layout parameters for the clock time complication.
@@ -78,6 +82,21 @@
}
/**
+ * Provides layout parameters for the media entry complication.
+ */
+ @Provides
+ @Named(DREAM_MEDIA_ENTRY_LAYOUT_PARAMS)
+ static ComplicationLayoutParams provideMediaEntryLayoutParams(@Main Resources res) {
+ return new ComplicationLayoutParams(
+ res.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width),
+ res.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height),
+ ComplicationLayoutParams.POSITION_BOTTOM
+ | ComplicationLayoutParams.POSITION_START,
+ ComplicationLayoutParams.DIRECTION_END,
+ DREAM_MEDIA_ENTRY_COMPLICATION_WEIGHT);
+ }
+
+ /**
* Provides layout parameters for the smartspace complication.
*/
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java
index 9c22dc6..081bab0 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java
@@ -25,7 +25,7 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.touch.BouncerSwipeTouchHandler;
import com.android.systemui.dreams.touch.DreamTouchHandler;
-import com.android.systemui.shade.PanelViewController;
+import com.android.systemui.shade.NotificationPanelViewController;
import com.android.wm.shell.animation.FlingAnimationUtils;
import javax.inject.Named;
@@ -77,8 +77,9 @@
Provider<FlingAnimationUtils.Builder> flingAnimationUtilsBuilderProvider) {
return flingAnimationUtilsBuilderProvider.get()
.reset()
- .setMaxLengthSeconds(PanelViewController.FLING_CLOSING_MAX_LENGTH_SECONDS)
- .setSpeedUpFactor(PanelViewController.FLING_SPEED_UP_FACTOR)
+ .setMaxLengthSeconds(
+ NotificationPanelViewController.FLING_CLOSING_MAX_LENGTH_SECONDS)
+ .setSpeedUpFactor(NotificationPanelViewController.FLING_SPEED_UP_FACTOR)
.build();
}
@@ -91,8 +92,8 @@
Provider<FlingAnimationUtils.Builder> flingAnimationUtilsBuilderProvider) {
return flingAnimationUtilsBuilderProvider.get()
.reset()
- .setMaxLengthSeconds(PanelViewController.FLING_MAX_LENGTH_SECONDS)
- .setSpeedUpFactor(PanelViewController.FLING_SPEED_UP_FACTOR)
+ .setMaxLengthSeconds(NotificationPanelViewController.FLING_MAX_LENGTH_SECONDS)
+ .setSpeedUpFactor(NotificationPanelViewController.FLING_SPEED_UP_FACTOR)
.build();
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index f868263..1482303 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -60,8 +60,8 @@
public static final ResourceBooleanFlag NOTIFICATION_DRAG_TO_CONTENTS =
new ResourceBooleanFlag(108, R.bool.config_notificationToContents);
- public static final UnreleasedFlag REMOVE_UNRANKED_NOTIFICATIONS =
- new UnreleasedFlag(109, true);
+ public static final ReleasedFlag REMOVE_UNRANKED_NOTIFICATIONS =
+ new ReleasedFlag(109);
public static final UnreleasedFlag FSI_REQUIRES_KEYGUARD =
new UnreleasedFlag(110, true);
@@ -103,6 +103,10 @@
*/
public static final ReleasedFlag MODERN_BOUNCER = new ReleasedFlag(208);
+ /** Whether UserSwitcherActivity should use modern architecture. */
+ public static final UnreleasedFlag MODERN_USER_SWITCHER_ACTIVITY =
+ new UnreleasedFlag(209, true);
+
/***************************************/
// 300 - power menu
public static final ReleasedFlag POWER_MENU_LITE =
@@ -147,6 +151,8 @@
public static final ResourceBooleanFlag FULL_SCREEN_USER_SWITCHER =
new ResourceBooleanFlag(506, R.bool.config_enableFullscreenUserSwitcher);
+ public static final UnreleasedFlag NEW_FOOTER_ACTIONS = new UnreleasedFlag(507, true);
+
/***************************************/
// 600- status bar
public static final ResourceBooleanFlag STATUS_BAR_USER_SWITCHER =
@@ -156,10 +162,10 @@
new ReleasedFlag(603, false);
public static final UnreleasedFlag NEW_STATUS_BAR_PIPELINE_BACKEND =
- new UnreleasedFlag(604, true);
+ new UnreleasedFlag(604, false);
public static final UnreleasedFlag NEW_STATUS_BAR_PIPELINE_FRONTEND =
- new UnreleasedFlag(605, true);
+ new UnreleasedFlag(605, false);
/***************************************/
// 700 - dialer/calls
@@ -244,6 +250,12 @@
public static final UnreleasedFlag SCREENSHOT_REQUEST_PROCESSOR = new UnreleasedFlag(1300);
public static final UnreleasedFlag SCREENSHOT_WORK_PROFILE_POLICY = new UnreleasedFlag(1301);
+ // 1400 - columbus, b/242800729
+ public static final UnreleasedFlag QUICK_TAP_IN_PCC = new UnreleasedFlag(1400);
+
+ // 1500 - chooser
+ public static final UnreleasedFlag CHOOSER_UNBUNDLED = new UnreleasedFlag(1500);
+
// Pay no attention to the reflection behind the curtain.
// ========================== Curtain ==========================
// | |
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index 9e2b7c7..a3dc779 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -50,7 +50,6 @@
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.systemui.CoreStartable;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
@@ -61,6 +60,7 @@
import java.util.Set;
import javax.inject.Inject;
+import javax.inject.Provider;
/** */
@SysUISingleton
@@ -106,6 +106,8 @@
protected volatile Context mContext;
+ private final Provider<LocalBluetoothManager> mBluetoothManagerProvider;
+
private boolean mEnabled;
private String mKeyboardName;
private CachedBluetoothDeviceManager mCachedDeviceManager;
@@ -122,8 +124,9 @@
private int mState;
@Inject
- public KeyboardUI(Context context) {
+ public KeyboardUI(Context context, Provider<LocalBluetoothManager> bluetoothManagerProvider) {
super(context);
+ this.mBluetoothManagerProvider = bluetoothManagerProvider;
}
@Override
@@ -181,7 +184,7 @@
return;
}
- LocalBluetoothManager bluetoothManager = Dependency.get(LocalBluetoothManager.class);
+ LocalBluetoothManager bluetoothManager = mBluetoothManagerProvider.get();
if (bluetoothManager == null) {
if (DEBUG) {
Slog.e(TAG, "Failed to retrieve LocalBluetoothManager instance");
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index e9caaaf..4c6aa7b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -148,6 +148,32 @@
}
}
}
+
+ companion object {
+ private const val SQUISHINESS_SCALE_START = 0.5
+ private const val SQUISHINESS_SCALE_FACTOR = 0.5
+ private fun getSquishinessScale(squishinessFraction: Float): Double {
+ return SQUISHINESS_SCALE_START + SQUISHINESS_SCALE_FACTOR * squishinessFraction
+ }
+ }
+
+ var squishinessFraction: Float = 1f
+ set(value) {
+ if (field == value) {
+ return
+ }
+ field = value
+
+ val scale = getSquishinessScale(field)
+ for (mediaPlayer in MediaPlayerData.players()) {
+ mediaPlayer.mediaViewHolder?.let {
+ it.player.bottom = it.player.top + (scale * it.player.measuredHeight).toInt()
+ } ?: mediaPlayer.recommendationViewHolder?.let {
+ it.recommendations.bottom = it.recommendations.top +
+ (scale * it.recommendations.measuredHeight).toInt()
+ }
+ }
+ }
private val configListener = object : ConfigurationController.ConfigurationListener {
override fun onDensityOrFontScaleChanged() {
// System font changes should only happen when UMO is offscreen or a flicker may occur
@@ -1076,4 +1102,4 @@
}
fun isSsReactivated(key: String): Boolean = mediaData.get(key)?.isSsReactivated ?: false
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 012d766..b02393b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -488,8 +488,8 @@
TextView deviceName = mMediaViewHolder.getSeamlessText();
final MediaDeviceData device = data.getDevice();
- final boolean enabled;
- final boolean seamlessDisabled;
+ final boolean isTapEnabled;
+ final boolean useDisabledAlpha;
final int iconResource;
CharSequence deviceString;
if (showBroadcastButton) {
@@ -499,21 +499,25 @@
&& TextUtils.equals(device.getName(),
MediaDataUtils.getAppLabel(mContext, mPackageName, mContext.getString(
R.string.bt_le_audio_broadcast_dialog_unknown_name)));
- seamlessDisabled = !mIsCurrentBroadcastedApp;
+ useDisabledAlpha = !mIsCurrentBroadcastedApp;
// Always be enabled if the broadcast button is shown
- enabled = true;
+ isTapEnabled = true;
+
+ // Defaults for broadcasting state
deviceString = mContext.getString(R.string.bt_le_audio_broadcast_dialog_unknown_name);
iconResource = R.drawable.settings_input_antenna;
} else {
// Disable clicking on output switcher for invalid devices and resumption controls
- seamlessDisabled = (device != null && !device.getEnabled()) || data.getResumption();
- enabled = !seamlessDisabled;
+ useDisabledAlpha = (device != null && !device.getEnabled()) || data.getResumption();
+ isTapEnabled = !useDisabledAlpha;
+
+ // Defaults for non-broadcasting state
deviceString = mContext.getString(R.string.media_seamless_other_device);
iconResource = R.drawable.ic_media_home_devices;
}
- mMediaViewHolder.getSeamlessButton().setAlpha(seamlessDisabled ? DISABLED_ALPHA : 1.0f);
- seamlessView.setEnabled(enabled);
+ mMediaViewHolder.getSeamlessButton().setAlpha(useDisabledAlpha ? DISABLED_ALPHA : 1.0f);
+ seamlessView.setEnabled(isTapEnabled);
if (device != null) {
Drawable icon = device.getIcon();
@@ -524,7 +528,9 @@
} else {
iconView.setImageDrawable(icon);
}
- deviceString = device.getName();
+ if (device.getName() != null) {
+ deviceString = device.getName();
+ }
} else {
// Set to default icon
iconView.setImageResource(iconResource);
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index c882675..fb37446 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -518,9 +518,20 @@
}
val actions = createActionsFromState(it.packageName,
mediaControllerFactory.create(it.token), UserHandle(it.userId))
- val data = it.copy(
- semanticActions = actions,
- isPlaying = isPlayingState(state.state))
+
+ // Control buttons
+ // If flag is enabled and controller has a PlaybackState,
+ // create actions from session info
+ // otherwise, no need to update semantic actions.
+ val data = if (actions != null) {
+ it.copy(
+ semanticActions = actions,
+ isPlaying = isPlayingState(state.state))
+ } else {
+ it.copy(
+ isPlaying = isPlayingState(state.state)
+ )
+ }
if (DEBUG) Log.d(TAG, "State updated outside of notification")
onMediaDataLoaded(key, key, data)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
index 8305050..267c1f5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
@@ -265,7 +265,6 @@
updateCurrent()
}
-
override fun onBroadcastStarted(reason: Int, broadcastId: Int) {
if (DEBUG) {
Log.d(TAG, "onBroadcastStarted(), reason = $reason , broadcastId = $broadcastId")
@@ -279,8 +278,10 @@
}
}
- override fun onBroadcastMetadataChanged(broadcastId: Int,
- metadata: BluetoothLeBroadcastMetadata) {
+ override fun onBroadcastMetadataChanged(
+ broadcastId: Int,
+ metadata: BluetoothLeBroadcastMetadata
+ ) {
if (DEBUG) {
Log.d(TAG, "onBroadcastMetadataChanged(), broadcastId = $broadcastId , " +
"metadata = $metadata")
@@ -291,7 +292,6 @@
override fun onBroadcastStopped(reason: Int, broadcastId: Int) {
if (DEBUG) {
Log.d(TAG, "onBroadcastStopped(), reason = $reason , broadcastId = $broadcastId")
-
}
updateCurrent()
}
@@ -344,7 +344,11 @@
// If we have a controller but get a null route, then don't trust the device
val enabled = device != null && (controller == null || route != null)
- val name = route?.name?.toString() ?: device?.name
+ val name = if (controller == null || route != null) {
+ route?.name?.toString() ?: device?.name
+ } else {
+ null
+ }
current = MediaDeviceData(enabled, device?.iconWithoutBackground, name,
id = device?.id, showBroadcastButton = false)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index e360d10..ee59561 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -16,6 +16,7 @@
package com.android.systemui.media.dialog;
+import android.annotation.DrawableRes;
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
@@ -42,9 +43,6 @@
private static final String TAG = "MediaOutputAdapter";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private ViewGroup mConnectedItem;
- private boolean mIncludeDynamicGroup;
-
public MediaOutputAdapter(MediaOutputController controller) {
super(controller);
setHasStableIds(true);
@@ -102,141 +100,90 @@
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin, int position) {
super.onBind(device, topMargin, bottomMargin, position);
boolean isMutingExpectedDeviceExist = mController.hasMutingExpectedDevice();
- final boolean currentlyConnected = !mIncludeDynamicGroup
- && isCurrentlyConnected(device);
+ final boolean currentlyConnected = isCurrentlyConnected(device);
boolean isCurrentSeekbarInvisible = mSeekBar.getVisibility() == View.GONE;
- if (currentlyConnected) {
- mConnectedItem = mContainerLayout;
- }
- mCheckBox.setVisibility(View.GONE);
- mStatusIcon.setVisibility(View.GONE);
- mEndTouchArea.setVisibility(View.GONE);
- mEndTouchArea.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
- mContainerLayout.setOnClickListener(null);
- mContainerLayout.setContentDescription(null);
- mTitleText.setTextColor(mController.getColorItemContent());
- mSubTitleText.setTextColor(mController.getColorItemContent());
- mTwoLineTitleText.setTextColor(mController.getColorItemContent());
- mSeekBar.getProgressDrawable().setColorFilter(
- new PorterDuffColorFilter(mController.getColorSeekbarProgress(),
- PorterDuff.Mode.SRC_IN));
if (mCurrentActivePosition == position) {
mCurrentActivePosition = -1;
}
- if (mController.isTransferring()) {
+ if (mController.isAnyDeviceTransferring()) {
if (device.getState() == MediaDeviceState.STATE_CONNECTING
&& !mController.hasAdjustVolumeUserRestriction()) {
setUpDeviceIcon(device);
- mProgressBar.getIndeterminateDrawable().setColorFilter(
- new PorterDuffColorFilter(
- mController.getColorItemContent(),
- PorterDuff.Mode.SRC_IN));
- setSingleLineLayout(getItemTitle(device), true /* bFocused */,
- false /* showSeekBar*/,
- true /* showProgressBar */, false /* showStatus */);
+ updateProgressBarColor();
+ setSingleLineLayout(getItemTitle(device), false /* showSeekBar*/,
+ true /* showProgressBar */, false /* showCheckBox */,
+ false /* showEndTouchArea */);
} else {
setUpDeviceIcon(device);
- setSingleLineLayout(getItemTitle(device), false /* bFocused */);
+ setSingleLineLayout(getItemTitle(device));
}
} else {
// Set different layout for each device
if (device.isMutingExpectedDevice()
&& !mController.isCurrentConnectedDeviceRemote()) {
- mTitleIcon.setImageDrawable(
- mContext.getDrawable(R.drawable.media_output_icon_volume));
- mTitleIcon.setColorFilter(mController.getColorItemContent());
- mTitleText.setTextColor(mController.getColorItemContent());
- setSingleLineLayout(getItemTitle(device), true /* bFocused */,
- false /* showSeekBar */,
- false /* showProgressBar */, false /* showStatus */);
+ updateTitleIcon(R.drawable.media_output_icon_volume,
+ mController.getColorItemContent());
initMutingExpectedDevice();
mCurrentActivePosition = position;
- mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
+ updateContainerClickListener(v -> onItemClick(v, device));
+ setSingleLineLayout(getItemTitle(device));
} else if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
setUpDeviceIcon(device);
- mStatusIcon.setImageDrawable(
- mContext.getDrawable(R.drawable.media_output_status_failed));
- mStatusIcon.setColorFilter(mController.getColorItemContent());
- setTwoLineLayout(device, false /* bFocused */,
- false /* showSeekBar */, false /* showProgressBar */,
- true /* showSubtitle */, true /* showStatus */);
+ updateConnectionFailedStatusIcon();
mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
- mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
+ updateContainerClickListener(v -> onItemClick(v, device));
+ setTwoLineLayout(device, false /* bFocused */, false /* showSeekBar */,
+ false /* showProgressBar */, true /* showSubtitle */,
+ true /* showStatus */);
} else if (device.getState() == MediaDeviceState.STATE_GROUPING) {
setUpDeviceIcon(device);
- mProgressBar.getIndeterminateDrawable().setColorFilter(
- new PorterDuffColorFilter(
- mController.getColorItemContent(),
- PorterDuff.Mode.SRC_IN));
- setSingleLineLayout(getItemTitle(device), true /* bFocused */,
- false /* showSeekBar*/,
- true /* showProgressBar */, false /* showStatus */);
+ updateProgressBarColor();
+ setSingleLineLayout(getItemTitle(device), false /* showSeekBar*/,
+ true /* showProgressBar */, false /* showCheckBox */,
+ false /* showEndTouchArea */);
} else if (mController.getSelectedMediaDevice().size() > 1
&& isDeviceIncluded(mController.getSelectedMediaDevice(), device)) {
boolean isDeviceDeselectable = isDeviceIncluded(
mController.getDeselectableMediaDevice(), device);
- mTitleText.setTextColor(mController.getColorItemContent());
- mTitleIcon.setImageDrawable(
- mContext.getDrawable(R.drawable.media_output_icon_volume));
- mTitleIcon.setColorFilter(mController.getColorItemContent());
- setSingleLineLayout(getItemTitle(device), true /* bFocused */,
- true /* showSeekBar */,
- false /* showProgressBar */, false /* showStatus */);
+ updateTitleIcon(R.drawable.media_output_icon_volume,
+ mController.getColorItemContent());
+ updateGroupableCheckBox(true, isDeviceDeselectable, device);
+ updateEndClickArea(device, isDeviceDeselectable);
setUpContentDescriptionForView(mContainerLayout, false, device);
- mCheckBox.setOnCheckedChangeListener(null);
- mCheckBox.setVisibility(View.VISIBLE);
- mCheckBox.setChecked(true);
- mCheckBox.setOnCheckedChangeListener(isDeviceDeselectable
- ? (buttonView, isChecked) -> onGroupActionTriggered(false, device)
- : null);
- mCheckBox.setEnabled(isDeviceDeselectable);
- setCheckBoxColor(mCheckBox, mController.getColorItemContent());
+ setSingleLineLayout(getItemTitle(device), true /* showSeekBar */,
+ false /* showProgressBar */, true /* showCheckBox */,
+ true /* showEndTouchArea */);
initSeekbar(device, isCurrentSeekbarInvisible);
- mEndTouchArea.setVisibility(View.VISIBLE);
- mEndTouchArea.setOnClickListener(null);
- mEndTouchArea.setOnClickListener(
- isDeviceDeselectable ? (v) -> mCheckBox.performClick() : null);
- mEndTouchArea.setImportantForAccessibility(
- View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- setUpContentDescriptionForView(mEndTouchArea, true, device);
} else if (!mController.hasAdjustVolumeUserRestriction()
&& currentlyConnected) {
if (isMutingExpectedDeviceExist
&& !mController.isCurrentConnectedDeviceRemote()) {
// mark as disconnected and set special click listener
setUpDeviceIcon(device);
- setSingleLineLayout(getItemTitle(device), false /* bFocused */);
- mContainerLayout.setOnClickListener(v -> cancelMuteAwaitConnection());
+ updateContainerClickListener(v -> cancelMuteAwaitConnection());
+ setSingleLineLayout(getItemTitle(device));
} else {
- mTitleIcon.setImageDrawable(
- mContext.getDrawable(R.drawable.media_output_icon_volume));
- mTitleIcon.setColorFilter(mController.getColorItemContent());
- mTitleText.setTextColor(mController.getColorItemContent());
- setSingleLineLayout(getItemTitle(device), true /* bFocused */,
- true /* showSeekBar */,
- false /* showProgressBar */, false /* showStatus */);
- initSeekbar(device, isCurrentSeekbarInvisible);
+ updateTitleIcon(R.drawable.media_output_icon_volume,
+ mController.getColorItemContent());
setUpContentDescriptionForView(mContainerLayout, false, device);
mCurrentActivePosition = position;
+ setSingleLineLayout(getItemTitle(device), true /* showSeekBar */,
+ false /* showProgressBar */, false /* showCheckBox */,
+ false /* showEndTouchArea */);
+ initSeekbar(device, isCurrentSeekbarInvisible);
}
} else if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
setUpDeviceIcon(device);
- mCheckBox.setOnCheckedChangeListener(null);
- mCheckBox.setVisibility(View.VISIBLE);
- mCheckBox.setChecked(false);
- mCheckBox.setOnCheckedChangeListener(
- (buttonView, isChecked) -> onGroupActionTriggered(true, device));
- mEndTouchArea.setVisibility(View.VISIBLE);
- mContainerLayout.setOnClickListener(v -> onGroupActionTriggered(true, device));
- setCheckBoxColor(mCheckBox, mController.getColorItemContent());
- setSingleLineLayout(getItemTitle(device), false /* bFocused */,
- false /* showSeekBar */,
- false /* showProgressBar */, false /* showStatus */);
+ updateGroupableCheckBox(false, true, device);
+ updateContainerClickListener(v -> onGroupActionTriggered(true, device));
+ setSingleLineLayout(getItemTitle(device), false /* showSeekBar */,
+ false /* showProgressBar */, true /* showCheckBox */,
+ true /* showEndTouchArea */);
} else {
setUpDeviceIcon(device);
- setSingleLineLayout(getItemTitle(device), false /* bFocused */);
- mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
+ setSingleLineLayout(getItemTitle(device));
+ updateContainerClickListener(v -> onItemClick(v, device));
}
}
}
@@ -248,15 +195,56 @@
ColorStateList(states, colors));
}
+ private void updateConnectionFailedStatusIcon() {
+ mStatusIcon.setImageDrawable(
+ mContext.getDrawable(R.drawable.media_output_status_failed));
+ mStatusIcon.setColorFilter(mController.getColorItemContent());
+ }
+
+ private void updateProgressBarColor() {
+ mProgressBar.getIndeterminateDrawable().setColorFilter(
+ new PorterDuffColorFilter(
+ mController.getColorItemContent(),
+ PorterDuff.Mode.SRC_IN));
+ }
+
+ public void updateEndClickArea(MediaDevice device, boolean isDeviceDeselectable) {
+ mEndTouchArea.setOnClickListener(null);
+ mEndTouchArea.setOnClickListener(
+ isDeviceDeselectable ? (v) -> mCheckBox.performClick() : null);
+ mEndTouchArea.setImportantForAccessibility(
+ View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ setUpContentDescriptionForView(mEndTouchArea, true, device);
+ }
+
+ private void updateGroupableCheckBox(boolean isSelected, boolean isGroupable,
+ MediaDevice device) {
+ mCheckBox.setOnCheckedChangeListener(null);
+ mCheckBox.setChecked(isSelected);
+ mCheckBox.setOnCheckedChangeListener(
+ isGroupable ? (buttonView, isChecked) -> onGroupActionTriggered(!isSelected,
+ device) : null);
+ mCheckBox.setEnabled(isGroupable);
+ setCheckBoxColor(mCheckBox, mController.getColorItemContent());
+ }
+
+ private void updateTitleIcon(@DrawableRes int id, int color) {
+ mTitleIcon.setImageDrawable(mContext.getDrawable(id));
+ mTitleIcon.setColorFilter(color);
+ }
+
+ private void updateContainerClickListener(View.OnClickListener listener) {
+ mContainerLayout.setOnClickListener(listener);
+ }
+
@Override
void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) {
mTitleText.setTextColor(mController.getColorItemContent());
mCheckBox.setVisibility(View.GONE);
- setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new),
- false /* bFocused */);
- final Drawable d = mContext.getDrawable(R.drawable.ic_add);
- mTitleIcon.setImageDrawable(d);
+ setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new));
+ final Drawable addDrawable = mContext.getDrawable(R.drawable.ic_add);
+ mTitleIcon.setImageDrawable(addDrawable);
mTitleIcon.setColorFilter(mController.getColorItemContent());
mContainerLayout.setOnClickListener(mController::launchBluetoothPairing);
}
@@ -273,7 +261,7 @@
}
private void onItemClick(View view, MediaDevice device) {
- if (mController.isTransferring()) {
+ if (mController.isAnyDeviceTransferring()) {
return;
}
if (isCurrentlyConnected(device)) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 3b4ca48..3f7b226 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -63,8 +63,6 @@
protected final MediaOutputController mController;
- private int mMargin;
-
Context mContext;
View mHolderView;
boolean mIsDragging;
@@ -82,8 +80,6 @@
public MediaDeviceBaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
int viewType) {
mContext = viewGroup.getContext();
- mMargin = mContext.getResources().getDimensionPixelSize(
- R.dimen.media_output_dialog_list_margin);
mHolderView = LayoutInflater.from(mContext).inflate(R.layout.media_output_list_item,
viewGroup, false);
@@ -168,16 +164,28 @@
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin, int position) {
mDeviceId = device.getId();
+ mCheckBox.setVisibility(View.GONE);
+ mStatusIcon.setVisibility(View.GONE);
+ mEndTouchArea.setVisibility(View.GONE);
+ mEndTouchArea.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+ mContainerLayout.setOnClickListener(null);
+ mContainerLayout.setContentDescription(null);
+ mTitleText.setTextColor(mController.getColorItemContent());
+ mSubTitleText.setTextColor(mController.getColorItemContent());
+ mTwoLineTitleText.setTextColor(mController.getColorItemContent());
+ mSeekBar.getProgressDrawable().setColorFilter(
+ new PorterDuffColorFilter(mController.getColorSeekbarProgress(),
+ PorterDuff.Mode.SRC_IN));
}
abstract void onBind(int customizedItem, boolean topMargin, boolean bottomMargin);
- void setSingleLineLayout(CharSequence title, boolean bFocused) {
- setSingleLineLayout(title, bFocused, false, false, false);
+ void setSingleLineLayout(CharSequence title) {
+ setSingleLineLayout(title, false, false, false, false);
}
- void setSingleLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar,
- boolean showProgressBar, boolean showStatus) {
+ void setSingleLineLayout(CharSequence title, boolean showSeekBar,
+ boolean showProgressBar, boolean showCheckBox, boolean showEndTouchArea) {
mTwoLineLayout.setVisibility(View.GONE);
boolean isActive = showSeekBar || showProgressBar;
if (!mCornerAnimator.isRunning()) {
@@ -188,10 +196,6 @@
.mutate() : mContext.getDrawable(
R.drawable.media_output_item_background)
.mutate();
- backgroundDrawable.setColorFilter(new PorterDuffColorFilter(
- isActive ? mController.getColorConnectedItemBackground()
- : mController.getColorItemBackground(),
- PorterDuff.Mode.SRC_IN));
mItemLayout.setBackground(backgroundDrawable);
if (showSeekBar) {
final ClipDrawable clipDrawable =
@@ -201,27 +205,21 @@
(GradientDrawable) clipDrawable.getDrawable();
progressDrawable.setCornerRadius(mController.getActiveRadius());
}
- } else {
- mItemLayout.getBackground().setColorFilter(new PorterDuffColorFilter(
- isActive ? mController.getColorConnectedItemBackground()
- : mController.getColorItemBackground(),
- PorterDuff.Mode.SRC_IN));
}
+ mItemLayout.getBackground().setColorFilter(new PorterDuffColorFilter(
+ isActive ? mController.getColorConnectedItemBackground()
+ : mController.getColorItemBackground(),
+ PorterDuff.Mode.SRC_IN));
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
mSeekBar.setAlpha(1);
mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
if (!showSeekBar) {
mSeekBar.resetVolume();
}
- mStatusIcon.setVisibility(showStatus ? View.VISIBLE : View.GONE);
mTitleText.setText(title);
mTitleText.setVisibility(View.VISIBLE);
- }
-
- void setTwoLineLayout(MediaDevice device, boolean bFocused, boolean showSeekBar,
- boolean showProgressBar, boolean showSubtitle) {
- setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle,
- false);
+ mCheckBox.setVisibility(showCheckBox ? View.VISIBLE : View.GONE);
+ mEndTouchArea.setVisibility(showEndTouchArea ? View.VISIBLE : View.GONE);
}
void setTwoLineLayout(MediaDevice device, boolean bFocused, boolean showSeekBar,
@@ -230,12 +228,6 @@
showStatus);
}
- void setTwoLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar,
- boolean showProgressBar, boolean showSubtitle) {
- setTwoLineLayout(null, title, bFocused, showSeekBar, showProgressBar, showSubtitle,
- false);
- }
-
private void setTwoLineLayout(MediaDevice device, CharSequence title, boolean bFocused,
boolean showSeekBar, boolean showProgressBar, boolean showSubtitle,
boolean showStatus) {
@@ -254,20 +246,11 @@
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
mSubTitleText.setVisibility(showSubtitle ? View.VISIBLE : View.GONE);
mTwoLineTitleText.setTranslationY(0);
- if (device == null) {
- mTwoLineTitleText.setText(title);
- } else {
- mTwoLineTitleText.setText(getItemTitle(device));
- }
-
- if (bFocused) {
- mTwoLineTitleText.setTypeface(Typeface.create(mContext.getString(
- com.android.internal.R.string.config_headlineFontFamilyMedium),
- Typeface.NORMAL));
- } else {
- mTwoLineTitleText.setTypeface(Typeface.create(mContext.getString(
- com.android.internal.R.string.config_headlineFontFamily), Typeface.NORMAL));
- }
+ mTwoLineTitleText.setText(device == null ? title : getItemTitle(device));
+ mTwoLineTitleText.setTypeface(Typeface.create(mContext.getString(
+ bFocused ? com.android.internal.R.string.config_headlineFontFamilyMedium
+ : com.android.internal.R.string.config_headlineFontFamily),
+ Typeface.NORMAL));
}
void initSeekbar(MediaDevice device, boolean isCurrentSeekbarInvisible) {
@@ -327,35 +310,6 @@
mItemLayout.setBackground(backgroundDrawable);
}
- void initSessionSeekbar() {
- disableSeekBar();
- mSeekBar.setMax(mController.getSessionVolumeMax());
- mSeekBar.setMin(0);
- final int currentVolume = mController.getSessionVolume();
- if (mSeekBar.getProgress() != currentVolume) {
- mSeekBar.setProgress(currentVolume, true);
- }
- mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if (!fromUser) {
- return;
- }
- mController.adjustSessionVolume(progress);
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- mIsDragging = true;
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- mIsDragging = false;
- }
- });
- }
-
private void animateCornerAndVolume(int fromProgress, int toProgress) {
final GradientDrawable layoutBackgroundDrawable =
(GradientDrawable) mItemLayout.getBackground();
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index bec130b..e08e338 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -356,15 +356,6 @@
mHeaderSubtitle.setText(subTitle);
mHeaderTitle.setGravity(Gravity.NO_GRAVITY);
}
- if (!mAdapter.isDragging()) {
- int currentActivePosition = mAdapter.getCurrentActivePosition();
- if (!colorSetUpdated && !deviceSetChanged && currentActivePosition >= 0
- && currentActivePosition < mAdapter.getItemCount()) {
- mAdapter.notifyItemChanged(currentActivePosition);
- } else {
- mAdapter.notifyDataSetChanged();
- }
- }
// Show when remote media session is available or
// when the device supports BT LE audio + media is playing
mStopButton.setVisibility(getStopButtonVisibility());
@@ -374,6 +365,18 @@
mBroadcastIcon.setVisibility(getBroadcastIconVisibility());
mBroadcastIcon.setOnClickListener(v -> onBroadcastIconClick());
+ if (!mAdapter.isDragging()) {
+ int currentActivePosition = mAdapter.getCurrentActivePosition();
+ if (!colorSetUpdated && !deviceSetChanged && currentActivePosition >= 0
+ && currentActivePosition < mAdapter.getItemCount()) {
+ mAdapter.notifyItemChanged(currentActivePosition);
+ } else {
+ mAdapter.notifyDataSetChanged();
+ }
+ } else {
+ mMediaOutputController.setRefreshing(false);
+ mMediaOutputController.refreshDataSetIfNeeded();
+ }
}
private void updateButtonBackgroundColorFilter() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index dad6544..8dd843a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -421,7 +421,7 @@
device.getId());
boolean isSelectedDeviceInGroup = getSelectedMediaDevice().size() > 1
&& getSelectedMediaDevice().contains(device);
- return (!hasAdjustVolumeUserRestriction() && isConnected && !isTransferring())
+ return (!hasAdjustVolumeUserRestriction() && isConnected && !isAnyDeviceTransferring())
|| isSelectedDeviceInGroup;
}
@@ -726,7 +726,7 @@
UserHandle.of(UserHandle.myUserId()));
}
- boolean isTransferring() {
+ boolean isAnyDeviceTransferring() {
synchronized (mMediaDevicesLock) {
for (MediaDevice device : mMediaDevices) {
if (device.getState() == LocalMediaManager.MediaDeviceState.STATE_CONNECTING) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java
index c544871..acd04f2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java
@@ -25,6 +25,7 @@
import com.android.systemui.CoreStartable;
import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.dreams.complication.DreamMediaEntryComplication;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.MediaData;
import com.android.systemui.media.MediaDataManager;
@@ -54,7 +55,7 @@
}
mAdded = false;
- mDreamOverlayStateController.removeComplication(mComplication);
+ mDreamOverlayStateController.removeComplication(mMediaEntryComplication);
}
@Override
@@ -79,24 +80,24 @@
}
mAdded = true;
- mDreamOverlayStateController.addComplication(mComplication);
+ mDreamOverlayStateController.addComplication(mMediaEntryComplication);
}
};
private final MediaDataManager mMediaDataManager;
private final DreamOverlayStateController mDreamOverlayStateController;
- private final MediaDreamComplication mComplication;
+ private final DreamMediaEntryComplication mMediaEntryComplication;
private final FeatureFlags mFeatureFlags;
@Inject
public MediaDreamSentinel(Context context, MediaDataManager mediaDataManager,
DreamOverlayStateController dreamOverlayStateController,
- MediaDreamComplication complication,
+ DreamMediaEntryComplication mediaEntryComplication,
FeatureFlags featureFlags) {
super(context);
mMediaDataManager = mediaDataManager;
mDreamOverlayStateController = dreamOverlayStateController;
- mComplication = complication;
+ mMediaEntryComplication = mediaEntryComplication;
mFeatureFlags = featureFlags;
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java
index 3408d97..052608f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java
@@ -16,6 +16,8 @@
package com.android.systemui.media.dream.dagger;
+import static com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule.DREAM_MEDIA_COMPLICATION_WEIGHT;
+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import android.content.Context;
@@ -93,7 +95,7 @@
ComplicationLayoutParams.POSITION_TOP
| ComplicationLayoutParams.POSITION_START,
ComplicationLayoutParams.DIRECTION_DOWN,
- 0,
+ DREAM_MEDIA_COMPLICATION_WEIGHT,
true);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
index 00a22f2..35a6c74 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
@@ -30,7 +30,6 @@
import android.view.ViewGroup
import android.view.WindowManager
import android.view.accessibility.AccessibilityManager
-import androidx.core.graphics.ColorUtils
import com.android.settingslib.Utils
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
@@ -209,8 +208,7 @@
// Center the ripple on the bottom of the screen in the middle.
rippleView.setCenter(width * 0.5f, height.toFloat())
val color = Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColorAccent)
- val colorWithAlpha = ColorUtils.setAlphaComponent(color, 70)
- rippleView.setColor(colorWithAlpha)
+ rippleView.setColor(color, 70)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 6ac3ead..7c4c64c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -814,8 +814,10 @@
}
mLogGesture = false;
String logPackageName = "";
+ Map<String, Integer> vocab = mVocab;
// Due to privacy, only top 100 most used apps by all users can be logged.
- if (mUseMLModel && mVocab.containsKey(mPackageName) && mVocab.get(mPackageName) < 100) {
+ if (mUseMLModel && vocab != null && vocab.containsKey(mPackageName)
+ && vocab.get(mPackageName) < 100) {
logPackageName = mPackageName;
}
SysUiStatsLog.write(SysUiStatsLog.BACK_GESTURE_REPORTED_REPORTED, backType,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
index 0288c9f..482a139 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
@@ -40,11 +40,13 @@
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.GuardedBy
+import androidx.annotation.VisibleForTesting
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_FOOTER_DOT
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.Dumpable
import com.android.systemui.R
@@ -66,9 +68,73 @@
import java.util.concurrent.Executor
import javax.inject.Inject
import kotlin.math.max
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+/** A controller for the dealing with services running in the foreground. */
+interface FgsManagerController {
+ /** Whether the TaskManager (and therefore this controller) is actually available. */
+ val isAvailable: StateFlow<Boolean>
+
+ /** The number of packages with a service running in the foreground. */
+ val numRunningPackages: Int
+
+ /**
+ * Whether there were new changes to the foreground services since the last [shown][showDialog]
+ * dialog was dismissed.
+ */
+ val newChangesSinceDialogWasDismissed: Boolean
+
+ /**
+ * Whether we should show a dot to indicate when [newChangesSinceDialogWasDismissed] is true.
+ */
+ val showFooterDot: StateFlow<Boolean>
+
+ /**
+ * Initialize this controller. This should be called once, before this controller is used for
+ * the first time.
+ */
+ fun init()
+
+ /**
+ * Show the foreground services dialog. The dialog will be expanded from [viewLaunchedFrom] if
+ * it's not `null`.
+ */
+ fun showDialog(viewLaunchedFrom: View?)
+
+ /** Add a [OnNumberOfPackagesChangedListener]. */
+ fun addOnNumberOfPackagesChangedListener(listener: OnNumberOfPackagesChangedListener)
+
+ /** Remove a [OnNumberOfPackagesChangedListener]. */
+ fun removeOnNumberOfPackagesChangedListener(listener: OnNumberOfPackagesChangedListener)
+
+ /** Add a [OnDialogDismissedListener]. */
+ fun addOnDialogDismissedListener(listener: OnDialogDismissedListener)
+
+ /** Remove a [OnDialogDismissedListener]. */
+ fun removeOnDialogDismissedListener(listener: OnDialogDismissedListener)
+
+ /** Whether we should update the footer visibility. */
+ // TODO(b/242040009): Remove this.
+ fun shouldUpdateFooterVisibility(): Boolean
+
+ @VisibleForTesting
+ fun visibleButtonsCount(): Int
+
+ interface OnNumberOfPackagesChangedListener {
+ /** Called when [numRunningPackages] changed. */
+ fun onNumberOfPackagesChanged(numPackages: Int)
+ }
+
+ interface OnDialogDismissedListener {
+ /** Called when a dialog shown using [showDialog] was dismissed. */
+ fun onDialogDismissed()
+ }
+}
@SysUISingleton
-class FgsManagerController @Inject constructor(
+class FgsManagerControllerImpl @Inject constructor(
private val context: Context,
@Main private val mainExecutor: Executor,
@Background private val backgroundExecutor: Executor,
@@ -80,22 +146,32 @@
private val dialogLaunchAnimator: DialogLaunchAnimator,
private val broadcastDispatcher: BroadcastDispatcher,
private val dumpManager: DumpManager
-) : IForegroundServiceObserver.Stub(), Dumpable {
+) : IForegroundServiceObserver.Stub(), Dumpable, FgsManagerController {
companion object {
private const val INTERACTION_JANK_TAG = "active_background_apps"
- private val LOG_TAG = FgsManagerController::class.java.simpleName
private const val DEFAULT_TASK_MANAGER_ENABLED = true
private const val DEFAULT_TASK_MANAGER_SHOW_FOOTER_DOT = false
+ private const val DEFAULT_TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS = true
}
- var changesSinceDialog = false
+ override var newChangesSinceDialogWasDismissed = false
private set
- var isAvailable = false
- private set
- var showFooterDot = false
- private set
+ val _isAvailable = MutableStateFlow(false)
+ override val isAvailable: StateFlow<Boolean> = _isAvailable.asStateFlow()
+
+ val _showFooterDot = MutableStateFlow(false)
+ override val showFooterDot: StateFlow<Boolean> = _showFooterDot.asStateFlow()
+
+ private var showStopBtnForUserAllowlistedApps = false
+
+ override val numRunningPackages: Int
+ get() {
+ synchronized(lock) {
+ return getNumVisiblePackagesLocked()
+ }
+ }
private val lock = Any()
@@ -133,15 +209,7 @@
}
}
- interface OnNumberOfPackagesChangedListener {
- fun onNumberOfPackagesChanged(numPackages: Int)
- }
-
- interface OnDialogDismissedListener {
- fun onDialogDismissed()
- }
-
- fun init() {
+ override fun init() {
synchronized(lock) {
if (initialized) {
return
@@ -160,19 +228,26 @@
NAMESPACE_SYSTEMUI,
backgroundExecutor
) {
- isAvailable = it.getBoolean(TASK_MANAGER_ENABLED, isAvailable)
- showFooterDot =
- it.getBoolean(TASK_MANAGER_SHOW_FOOTER_DOT, showFooterDot)
+ _isAvailable.value = it.getBoolean(TASK_MANAGER_ENABLED, _isAvailable.value)
+ _showFooterDot.value =
+ it.getBoolean(TASK_MANAGER_SHOW_FOOTER_DOT, _showFooterDot.value)
+ showStopBtnForUserAllowlistedApps = it.getBoolean(
+ TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
+ showStopBtnForUserAllowlistedApps)
}
- isAvailable = deviceConfigProxy.getBoolean(
+ _isAvailable.value = deviceConfigProxy.getBoolean(
NAMESPACE_SYSTEMUI,
TASK_MANAGER_ENABLED, DEFAULT_TASK_MANAGER_ENABLED
)
- showFooterDot = deviceConfigProxy.getBoolean(
+ _showFooterDot.value = deviceConfigProxy.getBoolean(
NAMESPACE_SYSTEMUI,
TASK_MANAGER_SHOW_FOOTER_DOT, DEFAULT_TASK_MANAGER_SHOW_FOOTER_DOT
)
+ showStopBtnForUserAllowlistedApps = deviceConfigProxy.getBoolean(
+ NAMESPACE_SYSTEMUI,
+ TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
+ DEFAULT_TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS)
dumpManager.registerDumpable(this)
@@ -220,42 +295,45 @@
}
@GuardedBy("lock")
- val onNumberOfPackagesChangedListeners: MutableSet<OnNumberOfPackagesChangedListener> =
- mutableSetOf()
+ private val onNumberOfPackagesChangedListeners =
+ mutableSetOf<FgsManagerController.OnNumberOfPackagesChangedListener>()
@GuardedBy("lock")
- val onDialogDismissedListeners: MutableSet<OnDialogDismissedListener> = mutableSetOf()
+ private val onDialogDismissedListeners =
+ mutableSetOf<FgsManagerController.OnDialogDismissedListener>()
- fun addOnNumberOfPackagesChangedListener(listener: OnNumberOfPackagesChangedListener) {
+ override fun addOnNumberOfPackagesChangedListener(
+ listener: FgsManagerController.OnNumberOfPackagesChangedListener
+ ) {
synchronized(lock) {
onNumberOfPackagesChangedListeners.add(listener)
}
}
- fun removeOnNumberOfPackagesChangedListener(listener: OnNumberOfPackagesChangedListener) {
+ override fun removeOnNumberOfPackagesChangedListener(
+ listener: FgsManagerController.OnNumberOfPackagesChangedListener
+ ) {
synchronized(lock) {
onNumberOfPackagesChangedListeners.remove(listener)
}
}
- fun addOnDialogDismissedListener(listener: OnDialogDismissedListener) {
+ override fun addOnDialogDismissedListener(
+ listener: FgsManagerController.OnDialogDismissedListener
+ ) {
synchronized(lock) {
onDialogDismissedListeners.add(listener)
}
}
- fun removeOnDialogDismissedListener(listener: OnDialogDismissedListener) {
+ override fun removeOnDialogDismissedListener(
+ listener: FgsManagerController.OnDialogDismissedListener
+ ) {
synchronized(lock) {
onDialogDismissedListeners.remove(listener)
}
}
- fun getNumRunningPackages(): Int {
- synchronized(lock) {
- return getNumVisiblePackagesLocked()
- }
- }
-
private fun getNumVisiblePackagesLocked(): Int {
return runningServiceTokens.keys.count {
it.uiControl != UIControl.HIDE_ENTRY && currentProfileIds.contains(it.userId)
@@ -266,7 +344,7 @@
val num = getNumVisiblePackagesLocked()
if (num != lastNumberOfVisiblePackages) {
lastNumberOfVisiblePackages = num
- changesSinceDialog = true
+ newChangesSinceDialogWasDismissed = true
onNumberOfPackagesChangedListeners.forEach {
backgroundExecutor.execute {
it.onNumberOfPackagesChanged(num)
@@ -275,9 +353,21 @@
}
}
- fun shouldUpdateFooterVisibility() = dialog == null
+ override fun visibleButtonsCount(): Int {
+ synchronized(lock) {
+ return getNumVisibleButtonsLocked()
+ }
+ }
- fun showDialog(viewLaunchedFrom: View?) {
+ private fun getNumVisibleButtonsLocked(): Int {
+ return runningServiceTokens.keys.count {
+ it.uiControl != UIControl.HIDE_BUTTON && currentProfileIds.contains(it.userId)
+ }
+ }
+
+ override fun shouldUpdateFooterVisibility() = dialog == null
+
+ override fun showDialog(viewLaunchedFrom: View?) {
synchronized(lock) {
if (dialog == null) {
@@ -302,7 +392,7 @@
this.dialog = dialog
dialog.setOnDismissListener {
- changesSinceDialog = false
+ newChangesSinceDialogWasDismissed = false
synchronized(lock) {
this.dialog = null
updateAppItemsLocked()
@@ -505,6 +595,13 @@
PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI,
PowerExemptionManager.REASON_ROLE_DIALER,
PowerExemptionManager.REASON_SYSTEM_MODULE -> UIControl.HIDE_BUTTON
+
+ PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE ->
+ if (showStopBtnForUserAllowlistedApps) {
+ UIControl.NORMAL
+ } else {
+ UIControl.HIDE_BUTTON
+ }
else -> UIControl.NORMAL
}
uiControlInitialized = true
@@ -623,7 +720,7 @@
val pw = IndentingPrintWriter(printwriter)
synchronized(lock) {
pw.println("current user profiles = $currentProfileIds")
- pw.println("changesSinceDialog=$changesSinceDialog")
+ pw.println("newChangesSinceDialogWasShown=$newChangesSinceDialogWasDismissed")
pw.println("Running service tokens: [")
pw.indentIfPossible {
runningServiceTokens.forEach { (userPackage, startTimeAndTokens) ->
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
index c790cfe..9d64781 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
@@ -56,6 +56,7 @@
* determined by [buttonsVisibleState]
*/
@QSScope
+// TODO(b/242040009): Remove this file.
internal class FooterActionsController @Inject constructor(
view: FooterActionsView,
multiUserSwitchControllerFactory: MultiUserSwitchController.Factory,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
index 309ac2a..d602b0b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
@@ -38,6 +38,7 @@
* in split shade mode visible also in collapsed state. May contain up to 5 buttons: settings,
* edit tiles, power off and conditionally: user switch and tuner
*/
+// TODO(b/242040009): Remove this file.
class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) {
private lateinit var settingsContainer: View
private lateinit var multiUserSwitch: MultiUserSwitch
diff --git a/packages/SystemUI/src/com/android/systemui/qs/NewFooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/NewFooterActionsController.kt
new file mode 100644
index 0000000..7c67d9f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/NewFooterActionsController.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs
+
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+
+/** Controller for the footer actions. This manages the initialization of its dependencies. */
+@SysUISingleton
+class NewFooterActionsController
+@Inject
+// TODO(b/242040009): Rename this to FooterActionsController.
+constructor(
+ private val fgsManagerController: FgsManagerController,
+) {
+ fun init() {
+ fgsManagerController.init()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java
index 875493d7..7511278e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java
@@ -41,6 +41,7 @@
/**
* Footer entry point for the foreground service manager
*/
+// TODO(b/242040009): Remove this file.
@QSScope
public class QSFgsManagerFooter implements View.OnClickListener,
FgsManagerController.OnDialogDismissedListener,
@@ -149,9 +150,11 @@
mNumberView.setContentDescription(text);
if (mFgsManagerController.shouldUpdateFooterVisibility()) {
mRootView.setVisibility(mNumPackages > 0
- && mFgsManagerController.isAvailable() ? View.VISIBLE : View.GONE);
- int dotVis = mFgsManagerController.getShowFooterDot()
- && mFgsManagerController.getChangesSinceDialog() ? View.VISIBLE : View.GONE;
+ && mFgsManagerController.isAvailable().getValue() ? View.VISIBLE
+ : View.GONE);
+ int dotVis = mFgsManagerController.getShowFooterDot().getValue()
+ && mFgsManagerController.getNewChangesSinceDialogWasDismissed()
+ ? View.VISIBLE : View.GONE;
mDotView.setVisibility(dotVis);
mCollapsedDotView.setVisibility(dotVis);
if (mVisibilityChangedListener != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 139fb8b..05b3eae 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -36,6 +36,9 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
import com.android.keyguard.BouncerPanelExpansionCalculator;
import com.android.systemui.Dumpable;
@@ -43,6 +46,8 @@
import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
@@ -50,6 +55,8 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSFragmentComponent;
+import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder;
+import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
@@ -104,6 +111,10 @@
private final QSFragmentComponent.Factory mQsComponentFactory;
private final QSFragmentDisableFlagsLogger mQsFragmentDisableFlagsLogger;
private final QSTileHost mHost;
+ private final FeatureFlags mFeatureFlags;
+ private final NewFooterActionsController mNewFooterActionsController;
+ private final FooterActionsViewModel.Factory mFooterActionsViewModelFactory;
+ private final ListeningAndVisibilityLifecycleOwner mListeningAndVisibilityLifecycleOwner;
private boolean mShowCollapsedOnKeyguard;
private boolean mLastKeyguardAndExpanded;
/**
@@ -119,8 +130,11 @@
private QSPanelController mQSPanelController;
private QuickQSPanelController mQuickQSPanelController;
private QSCustomizerController mQSCustomizerController;
+ @Nullable
private FooterActionsController mQSFooterActionController;
@Nullable
+ private FooterActionsViewModel mQSFooterActionsViewModel;
+ @Nullable
private ScrollListener mScrollListener;
/**
* When true, QS will translate from outside the screen. It will be clipped with parallax
@@ -161,7 +175,9 @@
KeyguardBypassController keyguardBypassController,
QSFragmentComponent.Factory qsComponentFactory,
QSFragmentDisableFlagsLogger qsFragmentDisableFlagsLogger,
- FalsingManager falsingManager, DumpManager dumpManager) {
+ FalsingManager falsingManager, DumpManager dumpManager, FeatureFlags featureFlags,
+ NewFooterActionsController newFooterActionsController,
+ FooterActionsViewModel.Factory footerActionsViewModelFactory) {
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
mQsMediaHost = qsMediaHost;
mQqsMediaHost = qqsMediaHost;
@@ -173,6 +189,10 @@
mBypassController = keyguardBypassController;
mStatusBarStateController = statusBarStateController;
mDumpManager = dumpManager;
+ mFeatureFlags = featureFlags;
+ mNewFooterActionsController = newFooterActionsController;
+ mFooterActionsViewModelFactory = footerActionsViewModelFactory;
+ mListeningAndVisibilityLifecycleOwner = new ListeningAndVisibilityLifecycleOwner();
}
@Override
@@ -193,11 +213,22 @@
QSFragmentComponent qsFragmentComponent = mQsComponentFactory.create(this);
mQSPanelController = qsFragmentComponent.getQSPanelController();
mQuickQSPanelController = qsFragmentComponent.getQuickQSPanelController();
- mQSFooterActionController = qsFragmentComponent.getQSFooterActionController();
mQSPanelController.init();
mQuickQSPanelController.init();
- mQSFooterActionController.init();
+
+ if (mFeatureFlags.isEnabled(Flags.NEW_FOOTER_ACTIONS)) {
+ mQSFooterActionsViewModel = mFooterActionsViewModelFactory.create(/* lifecycleOwner */
+ this);
+ FooterActionsView footerActionsView = view.findViewById(R.id.qs_footer_actions);
+ FooterActionsViewBinder.bind(footerActionsView, mQSFooterActionsViewModel,
+ mListeningAndVisibilityLifecycleOwner);
+
+ mNewFooterActionsController.init();
+ } else {
+ mQSFooterActionController = qsFragmentComponent.getQSFooterActionController();
+ mQSFooterActionController.init();
+ }
mQSPanelScrollView = view.findViewById(R.id.expanded_qs_scroll_view);
mQSPanelScrollView.addOnLayoutChangeListener(
@@ -283,6 +314,7 @@
mDumpManager.unregisterDumpable(mContainer.getClass().getName());
}
mDumpManager.unregisterDumpable(getClass().getName());
+ mListeningAndVisibilityLifecycleOwner.destroy();
}
@Override
@@ -395,7 +427,9 @@
mContainer.disable(state1, state2, animate);
mHeader.disable(state1, state2, animate);
mFooter.disable(state1, state2, animate);
- mQSFooterActionController.disable(state2);
+ if (mQSFooterActionController != null) {
+ mQSFooterActionController.disable(state2);
+ }
updateQsState();
}
@@ -415,7 +449,11 @@
boolean footerVisible = qsPanelVisible && (expanded || !keyguardShowing || mHeaderAnimating
|| mShowCollapsedOnKeyguard);
mFooter.setVisibility(footerVisible ? View.VISIBLE : View.INVISIBLE);
- mQSFooterActionController.setVisible(footerVisible);
+ if (mQSFooterActionController != null) {
+ mQSFooterActionController.setVisible(footerVisible);
+ } else {
+ mQSFooterActionsViewModel.onVisibilityChangeRequested(footerVisible);
+ }
mFooter.setExpanded((keyguardShowing && !mHeaderAnimating && !mShowCollapsedOnKeyguard)
|| (expanded && !mStackScrollerOverscrolling));
mQSPanelController.setVisibility(qsPanelVisible ? View.VISIBLE : View.INVISIBLE);
@@ -482,7 +520,9 @@
}
mFooter.setKeyguardShowing(keyguardShowing);
- mQSFooterActionController.setKeyguardShowing(keyguardShowing);
+ if (mQSFooterActionController != null) {
+ mQSFooterActionController.setKeyguardShowing(keyguardShowing);
+ }
updateQsState();
}
@@ -498,7 +538,10 @@
if (DEBUG) Log.d(TAG, "setListening " + listening);
mListening = listening;
mQSContainerImplController.setListening(listening && mQsVisible);
- mQSFooterActionController.setListening(listening && mQsVisible);
+ if (mQSFooterActionController != null) {
+ mQSFooterActionController.setListening(listening && mQsVisible);
+ }
+ mListeningAndVisibilityLifecycleOwner.updateState();
updateQsPanelControllerListening();
}
@@ -511,6 +554,7 @@
if (DEBUG) Log.d(TAG, "setQsVisible " + visible);
mQsVisible = visible;
setListening(mListening);
+ mListeningAndVisibilityLifecycleOwner.updateState();
}
@Override
@@ -602,7 +646,12 @@
mFooter.setExpansion(onKeyguardAndExpanded ? 1 : expansion);
float footerActionsExpansion =
onKeyguardAndExpanded ? 1 : mInSplitShade ? alphaProgress : expansion;
- mQSFooterActionController.setExpansion(footerActionsExpansion);
+ if (mQSFooterActionController != null) {
+ mQSFooterActionController.setExpansion(footerActionsExpansion);
+ } else {
+ mQSFooterActionsViewModel.onQuickSettingsExpansionChanged(footerActionsExpansion,
+ mInSplitShade);
+ }
mQSPanelController.setRevealExpansion(expansion);
mQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation);
mQuickQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation);
@@ -714,7 +763,11 @@
boolean customizing = isCustomizing();
mQSPanelScrollView.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE);
mFooter.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE);
- mQSFooterActionController.setVisible(!customizing);
+ if (mQSFooterActionController != null) {
+ mQSFooterActionController.setVisible(!customizing);
+ } else {
+ mQSFooterActionsViewModel.onVisibilityChangeRequested(!customizing);
+ }
mHeader.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE);
// Let the panel know the position changed and it needs to update where notifications
// and whatnot are.
@@ -860,4 +913,56 @@
}
return "GONE";
}
+
+ /**
+ * A {@link LifecycleOwner} whose state is driven by the current state of this fragment:
+ *
+ * - DESTROYED when the fragment is destroyed.
+ * - CREATED when mListening == mQsVisible == false.
+ * - STARTED when mListening == true && mQsVisible == false.
+ * - RESUMED when mListening == true && mQsVisible == true.
+ */
+ private class ListeningAndVisibilityLifecycleOwner implements LifecycleOwner {
+ private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
+ private boolean mDestroyed = false;
+
+ {
+ updateState();
+ }
+
+ @Override
+ public Lifecycle getLifecycle() {
+ return mLifecycleRegistry;
+ }
+
+ /**
+ * Update the state of the associated lifecycle. This should be called whenever
+ * {@code mListening} or {@code mQsVisible} is changed.
+ */
+ public void updateState() {
+ if (mDestroyed) {
+ mLifecycleRegistry.setCurrentState(Lifecycle.State.DESTROYED);
+ return;
+ }
+
+ if (!mListening) {
+ mLifecycleRegistry.setCurrentState(Lifecycle.State.CREATED);
+ return;
+ }
+
+ // mListening && !mQsVisible.
+ if (!mQsVisible) {
+ mLifecycleRegistry.setCurrentState(Lifecycle.State.STARTED);
+ return;
+ }
+
+ // mListening && mQsVisible.
+ mLifecycleRegistry.setCurrentState(Lifecycle.State.RESUMED);
+ }
+
+ public void destroy() {
+ mDestroyed = true;
+ updateState();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 918c6be..59b871c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -27,8 +27,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaCarouselController;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.media.MediaHost;
import com.android.systemui.media.MediaHostState;
@@ -61,8 +61,6 @@
private final BrightnessMirrorHandler mBrightnessMirrorHandler;
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- private boolean mGridContentVisible = true;
-
private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
new QSPanel.OnConfigurationChangedListener() {
@Override
@@ -90,13 +88,14 @@
@Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
@Named(QS_PANEL) MediaHost mediaHost,
QSTileRevealController.Factory qsTileRevealControllerFactory,
- DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
+ DumpManager dumpManager, MediaCarouselController mediaCarouselController,
+ MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
BrightnessSliderController.Factory brightnessSliderFactory,
FalsingManager falsingManager,
StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
- metricsLogger, uiEventLogger, qsLogger, dumpManager);
+ metricsLogger, uiEventLogger, qsLogger, dumpManager, mediaCarouselController);
mTunerService = tunerService;
mQsCustomizerController = qsCustomizerController;
mQsTileRevealControllerFactory = qsTileRevealControllerFactory;
@@ -204,16 +203,6 @@
});
}
- /** */
- public void setGridContentVisibility(boolean visible) {
- int newVis = visible ? View.VISIBLE : View.INVISIBLE;
- setVisibility(newVis);
- if (mGridContentVisible != visible) {
- mMetricsLogger.visibility(MetricsEvent.QS_PANEL, newVis);
- }
- mGridContentVisible = visible;
- }
-
public boolean isLayoutRtl() {
return mView.isLayoutRtl();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 6d5f844..57bea67 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -31,6 +31,7 @@
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.Dumpable;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaCarouselController;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
@@ -68,6 +69,7 @@
private final UiEventLogger mUiEventLogger;
private final QSLogger mQSLogger;
private final DumpManager mDumpManager;
+ private final MediaCarouselController mMediaCarouselController;
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
protected boolean mShouldUseSplitNotificationShade;
@@ -122,7 +124,8 @@
MetricsLogger metricsLogger,
UiEventLogger uiEventLogger,
QSLogger qsLogger,
- DumpManager dumpManager
+ DumpManager dumpManager,
+ MediaCarouselController mediaCarouselController
) {
super(view);
mHost = host;
@@ -135,6 +138,7 @@
mDumpManager = dumpManager;
mShouldUseSplitNotificationShade =
LargeScreenUtils.shouldUseSplitNotificationShade(getResources());
+ mMediaCarouselController = mediaCarouselController;
}
@Override
@@ -152,6 +156,7 @@
public void setSquishinessFraction(float squishinessFraction) {
mView.setSquishinessFraction(squishinessFraction);
+ mMediaCarouselController.setSquishinessFraction(squishinessFraction);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 87fcce4..b20d7ba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -15,126 +15,66 @@
*/
package com.android.systemui.qs;
-import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_CA_CERT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_NETWORK;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MONITORING_CA_CERT_SUBTITLE;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MONITORING_NETWORK_SUBTITLE;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MONITORING_VPN_SUBTITLE;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_NAMED_MANAGEMENT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_PERSONAL_PROFILE_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_VIEW_POLICIES;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_CA_CERT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_NETWORK;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_MONITORING;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_MULTIPLE_VPNS;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_MONITORING;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_MULTIPLE_VPNS;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_WORK_PROFILE_MONITORING;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_PERSONAL_PROFILE_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_MONITORING;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_NETWORK;
-
import static com.android.systemui.qs.dagger.QSFragmentModule.QS_SECURITY_FOOTER_VIEW;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.UserInfo;
import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.text.SpannableStringBuilder;
-import android.text.method.LinkMovementMethod;
-import android.text.style.ClickableSpan;
import android.util.Log;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
-import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.util.FrameworkStatsLog;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
-import com.android.systemui.animation.DialogCuj;
-import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.common.shared.model.Icon;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.dagger.QSScope;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig;
+import com.android.systemui.security.data.model.SecurityModel;
import com.android.systemui.statusbar.policy.SecurityController;
import com.android.systemui.util.ViewController;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Supplier;
-
import javax.inject.Inject;
import javax.inject.Named;
+/** ViewController for the footer actions. */
+// TODO(b/242040009): Remove this class.
@QSScope
-class QSSecurityFooter extends ViewController<View>
- implements OnClickListener, DialogInterface.OnClickListener,
- VisibilityChangedDispatcher {
+public class QSSecurityFooter extends ViewController<View>
+ implements OnClickListener, VisibilityChangedDispatcher {
protected static final String TAG = "QSSecurityFooter";
- protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final boolean DEBUG_FORCE_VISIBLE = false;
-
- private static final String INTERACTION_JANK_TAG = "managed_device_info";
private final TextView mFooterText;
private final ImageView mPrimaryFooterIcon;
private Context mContext;
- private final DevicePolicyManager mDpm;
private final Callback mCallback = new Callback();
private final SecurityController mSecurityController;
- private final ActivityStarter mActivityStarter;
private final Handler mMainHandler;
- private final UserTracker mUserTracker;
- private final DialogLaunchAnimator mDialogLaunchAnimator;
private final BroadcastDispatcher mBroadcastDispatcher;
+ private final QSSecurityFooterUtils mQSSecurityFooterUtils;
- private final AtomicBoolean mShouldUseSettingsButton = new AtomicBoolean(false);
-
- private AlertDialog mDialog;
protected H mHandler;
private boolean mIsVisible;
+ private boolean mIsClickable;
@Nullable
private CharSequence mFooterTextContent = null;
- private int mFooterIconId;
- @Nullable
- private Drawable mPrimaryFooterIconDrawable;
+ private Icon mFooterIcon;
@Nullable
private VisibilityChangedDispatcher.OnVisibilityChangedListener mVisibilityChangedListener;
@@ -149,82 +89,21 @@
}
};
- private Supplier<String> mManagementTitleSupplier = () ->
- mContext == null ? null : mContext.getString(R.string.monitoring_title_device_owned);
-
- private Supplier<String> mManagementMessageSupplier = () ->
- mContext == null ? null : mContext.getString(
- R.string.quick_settings_disclosure_management);
-
- private Supplier<String> mManagementMonitoringStringSupplier = () ->
- mContext == null ? null : mContext.getString(
- R.string.quick_settings_disclosure_management_monitoring);
-
- private Supplier<String> mManagementMultipleVpnStringSupplier = () ->
- mContext == null ? null : mContext.getString(
- R.string.quick_settings_disclosure_management_vpns);
-
- private Supplier<String> mWorkProfileMonitoringStringSupplier = () ->
- mContext == null ? null : mContext.getString(
- R.string.quick_settings_disclosure_managed_profile_monitoring);
-
- private Supplier<String> mWorkProfileNetworkStringSupplier = () ->
- mContext == null ? null : mContext.getString(
- R.string.quick_settings_disclosure_managed_profile_network_activity);
-
- private Supplier<String> mMonitoringSubtitleCaCertStringSupplier = () ->
- mContext == null ? null : mContext.getString(
- R.string.monitoring_subtitle_ca_certificate);
-
- private Supplier<String> mMonitoringSubtitleNetworkStringSupplier = () ->
- mContext == null ? null : mContext.getString(
- R.string.monitoring_subtitle_network_logging);
-
- private Supplier<String> mMonitoringSubtitleVpnStringSupplier = () ->
- mContext == null ? null : mContext.getString(R.string.monitoring_subtitle_vpn);
-
- private Supplier<String> mViewPoliciesButtonStringSupplier = () ->
- mContext == null ? null : mContext.getString(R.string.monitoring_button_view_policies);
-
- private Supplier<String> mManagementDialogStringSupplier = () ->
- mContext == null ? null : mContext.getString(
- R.string.monitoring_description_management);
-
- private Supplier<String> mManagementDialogCaCertStringSupplier = () ->
- mContext == null ? null : mContext.getString(
- R.string.monitoring_description_management_ca_certificate);
-
- private Supplier<String> mWorkProfileDialogCaCertStringSupplier = () ->
- mContext == null ? null : mContext.getString(
- R.string.monitoring_description_managed_profile_ca_certificate);
-
- private Supplier<String> mManagementDialogNetworkStringSupplier = () ->
- mContext == null ? null : mContext.getString(
- R.string.monitoring_description_management_network_logging);
-
- private Supplier<String> mWorkProfileDialogNetworkStringSupplier = () ->
- mContext == null ? null : mContext.getString(
- R.string.monitoring_description_managed_profile_network_logging);
-
@Inject
QSSecurityFooter(@Named(QS_SECURITY_FOOTER_VIEW) View rootView,
- UserTracker userTracker, @Main Handler mainHandler,
- ActivityStarter activityStarter, SecurityController securityController,
- DialogLaunchAnimator dialogLaunchAnimator, @Background Looper bgLooper,
- BroadcastDispatcher broadcastDispatcher) {
+ @Main Handler mainHandler, SecurityController securityController,
+ @Background Looper bgLooper, BroadcastDispatcher broadcastDispatcher,
+ QSSecurityFooterUtils qSSecurityFooterUtils) {
super(rootView);
mFooterText = mView.findViewById(R.id.footer_text);
mPrimaryFooterIcon = mView.findViewById(R.id.primary_footer_icon);
- mFooterIconId = R.drawable.ic_info_outline;
+ mFooterIcon = new Icon.Resource(R.drawable.ic_info_outline);
mContext = rootView.getContext();
- mDpm = rootView.getContext().getSystemService(DevicePolicyManager.class);
- mMainHandler = mainHandler;
- mActivityStarter = activityStarter;
mSecurityController = securityController;
+ mMainHandler = mainHandler;
mHandler = new H(bgLooper);
- mUserTracker = userTracker;
- mDialogLaunchAnimator = dialogLaunchAnimator;
mBroadcastDispatcher = broadcastDispatcher;
+ mQSSecurityFooterUtils = qSSecurityFooterUtils;
}
@Override
@@ -287,8 +166,9 @@
.write();
}
+ // TODO(b/242040009): Remove this.
public void showDeviceMonitoringDialog() {
- createDialog();
+ mQSSecurityFooterUtils.showDeviceMonitoringDialog(mContext, mView);
}
public void refreshState() {
@@ -296,590 +176,30 @@
}
private void handleRefreshState() {
- final boolean isDeviceManaged = mSecurityController.isDeviceManaged();
- final UserInfo currentUser = mUserTracker.getUserInfo();
- final boolean isDemoDevice = UserManager.isDeviceInDemoMode(mContext) && currentUser != null
- && currentUser.isDemo();
- final boolean hasWorkProfile = mSecurityController.hasWorkProfile();
- final boolean hasCACerts = mSecurityController.hasCACertInCurrentUser();
- final boolean hasCACertsInWorkProfile = mSecurityController.hasCACertInWorkProfile();
- final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
- final String vpnName = mSecurityController.getPrimaryVpnName();
- final String vpnNameWorkProfile = mSecurityController.getWorkProfileVpnName();
- final CharSequence organizationName = mSecurityController.getDeviceOwnerOrganizationName();
- final CharSequence workProfileOrganizationName =
- mSecurityController.getWorkProfileOrganizationName();
- final boolean isProfileOwnerOfOrganizationOwnedDevice =
- mSecurityController.isProfileOwnerOfOrganizationOwnedDevice();
- final boolean isParentalControlsEnabled = mSecurityController.isParentalControlsEnabled();
- final boolean isWorkProfileOn = mSecurityController.isWorkProfileOn();
- final boolean hasDisclosableWorkProfilePolicy = hasCACertsInWorkProfile
- || vpnNameWorkProfile != null || (hasWorkProfile && isNetworkLoggingEnabled);
- // Update visibility of footer
- mIsVisible = (isDeviceManaged && !isDemoDevice)
- || hasCACerts
- || vpnName != null
- || isProfileOwnerOfOrganizationOwnedDevice
- || isParentalControlsEnabled
- || (hasDisclosableWorkProfilePolicy && isWorkProfileOn);
- // Update the view to be untappable if the device is an organization-owned device with a
- // managed profile and there is either:
- // a) no policy set which requires a privacy disclosure.
- // b) a specific work policy set but the work profile is turned off.
- if (mIsVisible && isProfileOwnerOfOrganizationOwnedDevice
- && (!hasDisclosableWorkProfilePolicy || !isWorkProfileOn)) {
- mView.setClickable(false);
- mView.findViewById(R.id.footer_icon).setVisibility(View.GONE);
+ SecurityModel securityModel = SecurityModel.create(mSecurityController);
+ SecurityButtonConfig buttonConfig = mQSSecurityFooterUtils.getButtonConfig(securityModel);
+
+ if (buttonConfig == null) {
+ mIsVisible = false;
} else {
- mView.setClickable(true);
- mView.findViewById(R.id.footer_icon).setVisibility(View.VISIBLE);
- }
- // Update the string
- mFooterTextContent = getFooterText(isDeviceManaged, hasWorkProfile,
- hasCACerts, hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName,
- vpnNameWorkProfile, organizationName, workProfileOrganizationName,
- isProfileOwnerOfOrganizationOwnedDevice, isParentalControlsEnabled,
- isWorkProfileOn);
- // Update the icon
- int footerIconId = R.drawable.ic_info_outline;
- if (vpnName != null || vpnNameWorkProfile != null) {
- if (mSecurityController.isVpnBranded()) {
- footerIconId = R.drawable.stat_sys_branded_vpn;
- } else {
- footerIconId = R.drawable.stat_sys_vpn_ic;
- }
- }
- if (mFooterIconId != footerIconId) {
- mFooterIconId = footerIconId;
+ mIsVisible = true;
+ mIsClickable = buttonConfig.isClickable();
+ mFooterTextContent = buttonConfig.getText();
+ mFooterIcon = buttonConfig.getIcon();
}
- // Update the primary icon
- if (isParentalControlsEnabled) {
- if (mPrimaryFooterIconDrawable == null) {
- DeviceAdminInfo info = mSecurityController.getDeviceAdminInfo();
- mPrimaryFooterIconDrawable = mSecurityController.getIcon(info);
- }
- } else {
- mPrimaryFooterIconDrawable = null;
- }
+ // Update the UI.
mMainHandler.post(mUpdatePrimaryIcon);
-
mMainHandler.post(mUpdateDisplayState);
}
- @Nullable
- protected CharSequence getFooterText(boolean isDeviceManaged, boolean hasWorkProfile,
- boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
- String vpnName, String vpnNameWorkProfile, CharSequence organizationName,
- CharSequence workProfileOrganizationName,
- boolean isProfileOwnerOfOrganizationOwnedDevice, boolean isParentalControlsEnabled,
- boolean isWorkProfileOn) {
- if (isParentalControlsEnabled) {
- return mContext.getString(R.string.quick_settings_disclosure_parental_controls);
- }
- if (isDeviceManaged || DEBUG_FORCE_VISIBLE) {
- return getManagedDeviceFooterText(hasCACerts, hasCACertsInWorkProfile,
- isNetworkLoggingEnabled, vpnName, vpnNameWorkProfile, organizationName);
- }
- return getManagedAndPersonalProfileFooterText(hasWorkProfile, hasCACerts,
- hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName, vpnNameWorkProfile,
- workProfileOrganizationName, isProfileOwnerOfOrganizationOwnedDevice,
- isWorkProfileOn);
- }
-
- private String getManagedDeviceFooterText(
- boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
- String vpnName, String vpnNameWorkProfile, CharSequence organizationName) {
- if (hasCACerts || hasCACertsInWorkProfile || isNetworkLoggingEnabled) {
- return getManagedDeviceMonitoringText(organizationName);
- }
- if (vpnName != null || vpnNameWorkProfile != null) {
- return getManagedDeviceVpnText(vpnName, vpnNameWorkProfile, organizationName);
- }
- return getMangedDeviceGeneralText(organizationName);
- }
-
- private String getManagedDeviceMonitoringText(CharSequence organizationName) {
- if (organizationName == null) {
- return mDpm.getResources().getString(
- QS_MSG_MANAGEMENT_MONITORING, mManagementMonitoringStringSupplier);
- }
- return mDpm.getResources().getString(
- QS_MSG_NAMED_MANAGEMENT_MONITORING,
- () -> mContext.getString(
- R.string.quick_settings_disclosure_named_management_monitoring,
- organizationName),
- organizationName);
- }
-
- private String getManagedDeviceVpnText(
- String vpnName, String vpnNameWorkProfile, CharSequence organizationName) {
- if (vpnName != null && vpnNameWorkProfile != null) {
- if (organizationName == null) {
- return mDpm.getResources().getString(
- QS_MSG_MANAGEMENT_MULTIPLE_VPNS, mManagementMultipleVpnStringSupplier);
- }
- return mDpm.getResources().getString(
- QS_MSG_NAMED_MANAGEMENT_MULTIPLE_VPNS,
- () -> mContext.getString(
- R.string.quick_settings_disclosure_named_management_vpns,
- organizationName),
- organizationName);
- }
- String name = vpnName != null ? vpnName : vpnNameWorkProfile;
- if (organizationName == null) {
- return mDpm.getResources().getString(
- QS_MSG_MANAGEMENT_NAMED_VPN,
- () -> mContext.getString(
- R.string.quick_settings_disclosure_management_named_vpn,
- name),
- name);
- }
- return mDpm.getResources().getString(
- QS_MSG_NAMED_MANAGEMENT_NAMED_VPN,
- () -> mContext.getString(
- R.string.quick_settings_disclosure_named_management_named_vpn,
- organizationName,
- name),
- organizationName,
- name);
- }
-
- private String getMangedDeviceGeneralText(CharSequence organizationName) {
- if (organizationName == null) {
- return mDpm.getResources().getString(QS_MSG_MANAGEMENT, mManagementMessageSupplier);
- }
- if (isFinancedDevice()) {
- return mContext.getString(
- R.string.quick_settings_financed_disclosure_named_management,
- organizationName);
- } else {
- return mDpm.getResources().getString(
- QS_MSG_NAMED_MANAGEMENT,
- () -> mContext.getString(
- R.string.quick_settings_disclosure_named_management,
- organizationName),
- organizationName);
- }
- }
-
- private String getManagedAndPersonalProfileFooterText(boolean hasWorkProfile,
- boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
- String vpnName, String vpnNameWorkProfile, CharSequence workProfileOrganizationName,
- boolean isProfileOwnerOfOrganizationOwnedDevice, boolean isWorkProfileOn) {
- if (hasCACerts || (hasCACertsInWorkProfile && isWorkProfileOn)) {
- return getMonitoringText(
- hasCACerts, hasCACertsInWorkProfile, workProfileOrganizationName,
- isWorkProfileOn);
- }
- if (vpnName != null || (vpnNameWorkProfile != null && isWorkProfileOn)) {
- return getVpnText(hasWorkProfile, vpnName, vpnNameWorkProfile, isWorkProfileOn);
- }
- if (hasWorkProfile && isNetworkLoggingEnabled && isWorkProfileOn) {
- return getManagedProfileNetworkActivityText();
- }
- if (isProfileOwnerOfOrganizationOwnedDevice) {
- return getMangedDeviceGeneralText(workProfileOrganizationName);
- }
- return null;
- }
-
- private String getMonitoringText(boolean hasCACerts, boolean hasCACertsInWorkProfile,
- CharSequence workProfileOrganizationName, boolean isWorkProfileOn) {
- if (hasCACertsInWorkProfile && isWorkProfileOn) {
- if (workProfileOrganizationName == null) {
- return mDpm.getResources().getString(
- QS_MSG_WORK_PROFILE_MONITORING, mWorkProfileMonitoringStringSupplier);
- }
- return mDpm.getResources().getString(
- QS_MSG_NAMED_WORK_PROFILE_MONITORING,
- () -> mContext.getString(
- R.string.quick_settings_disclosure_named_managed_profile_monitoring,
- workProfileOrganizationName),
- workProfileOrganizationName);
- }
- if (hasCACerts) {
- return mContext.getString(R.string.quick_settings_disclosure_monitoring);
- }
- return null;
- }
-
- private String getVpnText(boolean hasWorkProfile, String vpnName, String vpnNameWorkProfile,
- boolean isWorkProfileOn) {
- if (vpnName != null && vpnNameWorkProfile != null) {
- return mContext.getString(R.string.quick_settings_disclosure_vpns);
- }
- if (vpnNameWorkProfile != null && isWorkProfileOn) {
- return mDpm.getResources().getString(
- QS_MSG_WORK_PROFILE_NAMED_VPN,
- () -> mContext.getString(
- R.string.quick_settings_disclosure_managed_profile_named_vpn,
- vpnNameWorkProfile),
- vpnNameWorkProfile);
- }
- if (vpnName != null) {
- if (hasWorkProfile) {
- return mDpm.getResources().getString(
- QS_MSG_PERSONAL_PROFILE_NAMED_VPN,
- () -> mContext.getString(
- R.string.quick_settings_disclosure_personal_profile_named_vpn,
- vpnName),
- vpnName);
- }
- return mContext.getString(R.string.quick_settings_disclosure_named_vpn,
- vpnName);
- }
- return null;
- }
-
- private String getManagedProfileNetworkActivityText() {
- return mDpm.getResources().getString(
- QS_MSG_WORK_PROFILE_NETWORK, mWorkProfileNetworkStringSupplier);
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_NEGATIVE) {
- final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
- dialog.dismiss();
- // This dismisses the shade on opening the activity
- mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
- }
- }
-
- private void createDialog() {
- mShouldUseSettingsButton.set(false);
- mHandler.post(() -> {
- String settingsButtonText = getSettingsButton();
- final View view = createDialogView();
- mMainHandler.post(() -> {
- mDialog = new SystemUIDialog(mContext, 0); // Use mContext theme
- mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
- mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(), this);
- mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, mShouldUseSettingsButton.get()
- ? settingsButtonText : getNegativeButton(), this);
-
- mDialog.setView(view);
- if (mView.isAggregatedVisible()) {
- mDialogLaunchAnimator.showFromView(mDialog, mView, new DialogCuj(
- InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG));
- } else {
- mDialog.show();
- }
- });
- });
- }
-
- @VisibleForTesting
- Dialog getDialog() {
- return mDialog;
- }
-
- @VisibleForTesting
- View createDialogView() {
- if (mSecurityController.isParentalControlsEnabled()) {
- return createParentalControlsDialogView();
- }
- return createOrganizationDialogView();
- }
-
- private View createOrganizationDialogView() {
- final boolean isDeviceManaged = mSecurityController.isDeviceManaged();
- final boolean hasWorkProfile = mSecurityController.hasWorkProfile();
- final CharSequence deviceOwnerOrganization =
- mSecurityController.getDeviceOwnerOrganizationName();
- final boolean hasCACerts = mSecurityController.hasCACertInCurrentUser();
- final boolean hasCACertsInWorkProfile = mSecurityController.hasCACertInWorkProfile();
- final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
- final String vpnName = mSecurityController.getPrimaryVpnName();
- final String vpnNameWorkProfile = mSecurityController.getWorkProfileVpnName();
-
- View dialogView = LayoutInflater.from(mContext)
- .inflate(R.layout.quick_settings_footer_dialog, null, false);
-
- // device management section
- TextView deviceManagementSubtitle =
- dialogView.findViewById(R.id.device_management_subtitle);
- deviceManagementSubtitle.setText(getManagementTitle(deviceOwnerOrganization));
-
- CharSequence managementMessage = getManagementMessage(isDeviceManaged,
- deviceOwnerOrganization);
- if (managementMessage == null) {
- dialogView.findViewById(R.id.device_management_disclosures).setVisibility(View.GONE);
- } else {
- dialogView.findViewById(R.id.device_management_disclosures).setVisibility(View.VISIBLE);
- TextView deviceManagementWarning =
- (TextView) dialogView.findViewById(R.id.device_management_warning);
- deviceManagementWarning.setText(managementMessage);
- mShouldUseSettingsButton.set(true);
- }
-
- // ca certificate section
- CharSequence caCertsMessage = getCaCertsMessage(isDeviceManaged, hasCACerts,
- hasCACertsInWorkProfile);
- if (caCertsMessage == null) {
- dialogView.findViewById(R.id.ca_certs_disclosures).setVisibility(View.GONE);
- } else {
- dialogView.findViewById(R.id.ca_certs_disclosures).setVisibility(View.VISIBLE);
- TextView caCertsWarning = (TextView) dialogView.findViewById(R.id.ca_certs_warning);
- caCertsWarning.setText(caCertsMessage);
- // Make "Open trusted credentials"-link clickable
- caCertsWarning.setMovementMethod(new LinkMovementMethod());
-
- TextView caCertsSubtitle = (TextView) dialogView.findViewById(R.id.ca_certs_subtitle);
- String caCertsSubtitleMessage = mDpm.getResources().getString(
- QS_DIALOG_MONITORING_CA_CERT_SUBTITLE, mMonitoringSubtitleCaCertStringSupplier);
- caCertsSubtitle.setText(caCertsSubtitleMessage);
-
- }
-
- // network logging section
- CharSequence networkLoggingMessage = getNetworkLoggingMessage(isDeviceManaged,
- isNetworkLoggingEnabled);
- if (networkLoggingMessage == null) {
- dialogView.findViewById(R.id.network_logging_disclosures).setVisibility(View.GONE);
- } else {
- dialogView.findViewById(R.id.network_logging_disclosures).setVisibility(View.VISIBLE);
- TextView networkLoggingWarning =
- (TextView) dialogView.findViewById(R.id.network_logging_warning);
- networkLoggingWarning.setText(networkLoggingMessage);
-
- TextView networkLoggingSubtitle = (TextView) dialogView.findViewById(
- R.id.network_logging_subtitle);
- String networkLoggingSubtitleMessage = mDpm.getResources().getString(
- QS_DIALOG_MONITORING_NETWORK_SUBTITLE,
- mMonitoringSubtitleNetworkStringSupplier);
- networkLoggingSubtitle.setText(networkLoggingSubtitleMessage);
- }
-
- // vpn section
- CharSequence vpnMessage = getVpnMessage(isDeviceManaged, hasWorkProfile, vpnName,
- vpnNameWorkProfile);
- if (vpnMessage == null) {
- dialogView.findViewById(R.id.vpn_disclosures).setVisibility(View.GONE);
- } else {
- dialogView.findViewById(R.id.vpn_disclosures).setVisibility(View.VISIBLE);
- TextView vpnWarning = (TextView) dialogView.findViewById(R.id.vpn_warning);
- vpnWarning.setText(vpnMessage);
- // Make "Open VPN Settings"-link clickable
- vpnWarning.setMovementMethod(new LinkMovementMethod());
-
- TextView vpnSubtitle = (TextView) dialogView.findViewById(R.id.vpn_subtitle);
- String vpnSubtitleMessage = mDpm.getResources().getString(
- QS_DIALOG_MONITORING_VPN_SUBTITLE, mMonitoringSubtitleVpnStringSupplier);
- vpnSubtitle.setText(vpnSubtitleMessage);
- }
-
- // Note: if a new section is added, should update configSubtitleVisibility to include
- // the handling of the subtitle
- configSubtitleVisibility(managementMessage != null,
- caCertsMessage != null,
- networkLoggingMessage != null,
- vpnMessage != null,
- dialogView);
-
- return dialogView;
- }
-
- private View createParentalControlsDialogView() {
- View dialogView = LayoutInflater.from(mContext)
- .inflate(R.layout.quick_settings_footer_dialog_parental_controls, null, false);
-
- DeviceAdminInfo info = mSecurityController.getDeviceAdminInfo();
- Drawable icon = mSecurityController.getIcon(info);
- if (icon != null) {
- ImageView imageView = (ImageView) dialogView.findViewById(R.id.parental_controls_icon);
- imageView.setImageDrawable(icon);
- }
-
- TextView parentalControlsTitle =
- (TextView) dialogView.findViewById(R.id.parental_controls_title);
- parentalControlsTitle.setText(mSecurityController.getLabel(info));
-
- return dialogView;
- }
-
- protected void configSubtitleVisibility(boolean showDeviceManagement, boolean showCaCerts,
- boolean showNetworkLogging, boolean showVpn, View dialogView) {
- // Device Management title should always been shown
- // When there is a Device Management message, all subtitles should be shown
- if (showDeviceManagement) {
- return;
- }
- // Hide the subtitle if there is only 1 message shown
- int mSectionCountExcludingDeviceMgt = 0;
- if (showCaCerts) { mSectionCountExcludingDeviceMgt++; }
- if (showNetworkLogging) { mSectionCountExcludingDeviceMgt++; }
- if (showVpn) { mSectionCountExcludingDeviceMgt++; }
-
- // No work needed if there is no sections or more than 1 section
- if (mSectionCountExcludingDeviceMgt != 1) {
- return;
- }
- if (showCaCerts) {
- dialogView.findViewById(R.id.ca_certs_subtitle).setVisibility(View.GONE);
- }
- if (showNetworkLogging) {
- dialogView.findViewById(R.id.network_logging_subtitle).setVisibility(View.GONE);
- }
- if (showVpn) {
- dialogView.findViewById(R.id.vpn_subtitle).setVisibility(View.GONE);
- }
- }
-
- // This should not be called on the main thread to avoid making an IPC.
- @VisibleForTesting
- String getSettingsButton() {
- return mDpm.getResources().getString(
- QS_DIALOG_VIEW_POLICIES, mViewPoliciesButtonStringSupplier);
- }
-
- private String getPositiveButton() {
- return mContext.getString(R.string.ok);
- }
-
- @Nullable
- private String getNegativeButton() {
- if (mSecurityController.isParentalControlsEnabled()) {
- return mContext.getString(R.string.monitoring_button_view_controls);
- }
- return null;
- }
-
- @Nullable
- protected CharSequence getManagementMessage(boolean isDeviceManaged,
- CharSequence organizationName) {
- if (!isDeviceManaged) {
- return null;
- }
- if (organizationName != null) {
- if (isFinancedDevice()) {
- return mContext.getString(R.string.monitoring_financed_description_named_management,
- organizationName, organizationName);
- } else {
- return mDpm.getResources().getString(
- QS_DIALOG_NAMED_MANAGEMENT,
- () -> mContext.getString(
- R.string.monitoring_description_named_management,
- organizationName),
- organizationName);
- }
- }
- return mDpm.getResources().getString(QS_DIALOG_MANAGEMENT, mManagementDialogStringSupplier);
- }
-
- @Nullable
- protected CharSequence getCaCertsMessage(boolean isDeviceManaged, boolean hasCACerts,
- boolean hasCACertsInWorkProfile) {
- if (!(hasCACerts || hasCACertsInWorkProfile)) return null;
- if (isDeviceManaged) {
- return mDpm.getResources().getString(
- QS_DIALOG_MANAGEMENT_CA_CERT, mManagementDialogCaCertStringSupplier);
- }
- if (hasCACertsInWorkProfile) {
- return mDpm.getResources().getString(
- QS_DIALOG_WORK_PROFILE_CA_CERT, mWorkProfileDialogCaCertStringSupplier);
- }
- return mContext.getString(R.string.monitoring_description_ca_certificate);
- }
-
- @Nullable
- protected CharSequence getNetworkLoggingMessage(boolean isDeviceManaged,
- boolean isNetworkLoggingEnabled) {
- if (!isNetworkLoggingEnabled) return null;
- if (isDeviceManaged) {
- return mDpm.getResources().getString(
- QS_DIALOG_MANAGEMENT_NETWORK, mManagementDialogNetworkStringSupplier);
- } else {
- return mDpm.getResources().getString(
- QS_DIALOG_WORK_PROFILE_NETWORK, mWorkProfileDialogNetworkStringSupplier);
- }
- }
-
- @Nullable
- protected CharSequence getVpnMessage(boolean isDeviceManaged, boolean hasWorkProfile,
- String vpnName, String vpnNameWorkProfile) {
- if (vpnName == null && vpnNameWorkProfile == null) return null;
- final SpannableStringBuilder message = new SpannableStringBuilder();
- if (isDeviceManaged) {
- if (vpnName != null && vpnNameWorkProfile != null) {
- String namedVpns = mDpm.getResources().getString(
- QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN,
- () -> mContext.getString(
- R.string.monitoring_description_two_named_vpns,
- vpnName, vpnNameWorkProfile),
- vpnName, vpnNameWorkProfile);
- message.append(namedVpns);
- } else {
- String name = vpnName != null ? vpnName : vpnNameWorkProfile;
- String namedVp = mDpm.getResources().getString(
- QS_DIALOG_MANAGEMENT_NAMED_VPN,
- () -> mContext.getString(R.string.monitoring_description_named_vpn, name),
- name);
- message.append(namedVp);
- }
- } else {
- if (vpnName != null && vpnNameWorkProfile != null) {
- String namedVpns = mDpm.getResources().getString(
- QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN,
- () -> mContext.getString(
- R.string.monitoring_description_two_named_vpns,
- vpnName, vpnNameWorkProfile),
- vpnName, vpnNameWorkProfile);
- message.append(namedVpns);
- } else if (vpnNameWorkProfile != null) {
- String namedVpn = mDpm.getResources().getString(
- QS_DIALOG_WORK_PROFILE_NAMED_VPN,
- () -> mContext.getString(
- R.string.monitoring_description_managed_profile_named_vpn,
- vpnNameWorkProfile),
- vpnNameWorkProfile);
- message.append(namedVpn);
- } else if (hasWorkProfile) {
- String namedVpn = mDpm.getResources().getString(
- QS_DIALOG_PERSONAL_PROFILE_NAMED_VPN,
- () -> mContext.getString(
- R.string.monitoring_description_personal_profile_named_vpn,
- vpnName),
- vpnName);
- message.append(namedVpn);
- } else {
- message.append(mContext.getString(R.string.monitoring_description_named_vpn,
- vpnName));
- }
- }
- message.append(mContext.getString(R.string.monitoring_description_vpn_settings_separator));
- message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
- new VpnSpan(), 0);
- return message;
- }
-
- @VisibleForTesting
- CharSequence getManagementTitle(CharSequence deviceOwnerOrganization) {
- if (deviceOwnerOrganization != null && isFinancedDevice()) {
- return mContext.getString(R.string.monitoring_title_financed_device,
- deviceOwnerOrganization);
- } else {
- return mDpm.getResources().getString(
- QS_DIALOG_MANAGEMENT_TITLE,
- mManagementTitleSupplier);
- }
- }
-
- private boolean isFinancedDevice() {
- return mSecurityController.isDeviceManaged()
- && mSecurityController.getDeviceOwnerType(
- mSecurityController.getDeviceOwnerComponentOnAnyUser())
- == DEVICE_OWNER_TYPE_FINANCED;
- }
-
private final Runnable mUpdatePrimaryIcon = new Runnable() {
@Override
public void run() {
- if (mPrimaryFooterIconDrawable != null) {
- mPrimaryFooterIcon.setImageDrawable(mPrimaryFooterIconDrawable);
- } else {
- mPrimaryFooterIcon.setImageResource(mFooterIconId);
+ if (mFooterIcon instanceof Icon.Loaded) {
+ mPrimaryFooterIcon.setImageDrawable(((Icon.Loaded) mFooterIcon).getDrawable());
+ } else if (mFooterIcon instanceof Icon.Resource) {
+ mPrimaryFooterIcon.setImageResource(((Icon.Resource) mFooterIcon).getRes());
}
}
};
@@ -890,10 +210,18 @@
if (mFooterTextContent != null) {
mFooterText.setText(mFooterTextContent);
}
- mView.setVisibility(mIsVisible || DEBUG_FORCE_VISIBLE ? View.VISIBLE : View.GONE);
+ mView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
if (mVisibilityChangedListener != null) {
mVisibilityChangedListener.onVisibilityChanged(mView.getVisibility());
}
+
+ if (mIsVisible && mIsClickable) {
+ mView.setClickable(true);
+ mView.findViewById(R.id.footer_icon).setVisibility(View.VISIBLE);
+ } else {
+ mView.setClickable(false);
+ mView.findViewById(R.id.footer_icon).setVisibility(View.GONE);
+ }
}
};
@@ -929,25 +257,4 @@
}
}
}
-
- protected class VpnSpan extends ClickableSpan {
- @Override
- public void onClick(View widget) {
- final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
- mDialog.dismiss();
- // This dismisses the shade on opening the activity
- mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
- }
-
- // for testing, to compare two CharSequences containing VpnSpans
- @Override
- public boolean equals(Object object) {
- return object instanceof VpnSpan;
- }
-
- @Override
- public int hashCode() {
- return 314159257; // prime
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java
new file mode 100644
index 0000000..f632274
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java
@@ -0,0 +1,793 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.qs;
+
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_CA_CERT;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_NAMED_VPN;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_NETWORK;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_TITLE;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MONITORING_CA_CERT_SUBTITLE;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MONITORING_NETWORK_SUBTITLE;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MONITORING_VPN_SUBTITLE;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_NAMED_MANAGEMENT;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_PERSONAL_PROFILE_NAMED_VPN;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_VIEW_POLICIES;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_CA_CERT;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_NAMED_VPN;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_NETWORK;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_MONITORING;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_MULTIPLE_VPNS;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_NAMED_VPN;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_MONITORING;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_MULTIPLE_VPNS;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_NAMED_VPN;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_WORK_PROFILE_MONITORING;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_PERSONAL_PROFILE_NAMED_VPN;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_MONITORING;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_NAMED_VPN;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_NETWORK;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.text.SpannableStringBuilder;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.internal.jank.InteractionJankMonitor;
+import com.android.systemui.R;
+import com.android.systemui.animation.DialogCuj;
+import com.android.systemui.animation.DialogLaunchAnimator;
+import com.android.systemui.common.shared.model.Icon;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Application;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig;
+import com.android.systemui.security.data.model.SecurityModel;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.SecurityController;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
+
+import javax.inject.Inject;
+
+/** Helper class for the configuration of the QS security footer button. */
+@SysUISingleton
+public class QSSecurityFooterUtils implements DialogInterface.OnClickListener {
+ protected static final String TAG = "QSSecurityFooterUtils";
+ protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean DEBUG_FORCE_VISIBLE = false;
+
+ private static final String INTERACTION_JANK_TAG = "managed_device_info";
+
+ @Application private Context mContext;
+ private final DevicePolicyManager mDpm;
+
+ private final SecurityController mSecurityController;
+ private final ActivityStarter mActivityStarter;
+ private final Handler mMainHandler;
+ private final UserTracker mUserTracker;
+ private final DialogLaunchAnimator mDialogLaunchAnimator;
+
+ private final AtomicBoolean mShouldUseSettingsButton = new AtomicBoolean(false);
+
+ protected Handler mBgHandler;
+ private AlertDialog mDialog;
+
+ private Supplier<String> mManagementTitleSupplier = () ->
+ mContext == null ? null : mContext.getString(R.string.monitoring_title_device_owned);
+
+ private Supplier<String> mManagementMessageSupplier = () ->
+ mContext == null ? null : mContext.getString(
+ R.string.quick_settings_disclosure_management);
+
+ private Supplier<String> mManagementMonitoringStringSupplier = () ->
+ mContext == null ? null : mContext.getString(
+ R.string.quick_settings_disclosure_management_monitoring);
+
+ private Supplier<String> mManagementMultipleVpnStringSupplier = () ->
+ mContext == null ? null : mContext.getString(
+ R.string.quick_settings_disclosure_management_vpns);
+
+ private Supplier<String> mWorkProfileMonitoringStringSupplier = () ->
+ mContext == null ? null : mContext.getString(
+ R.string.quick_settings_disclosure_managed_profile_monitoring);
+
+ private Supplier<String> mWorkProfileNetworkStringSupplier = () ->
+ mContext == null ? null : mContext.getString(
+ R.string.quick_settings_disclosure_managed_profile_network_activity);
+
+ private Supplier<String> mMonitoringSubtitleCaCertStringSupplier = () ->
+ mContext == null ? null : mContext.getString(
+ R.string.monitoring_subtitle_ca_certificate);
+
+ private Supplier<String> mMonitoringSubtitleNetworkStringSupplier = () ->
+ mContext == null ? null : mContext.getString(
+ R.string.monitoring_subtitle_network_logging);
+
+ private Supplier<String> mMonitoringSubtitleVpnStringSupplier = () ->
+ mContext == null ? null : mContext.getString(R.string.monitoring_subtitle_vpn);
+
+ private Supplier<String> mViewPoliciesButtonStringSupplier = () ->
+ mContext == null ? null : mContext.getString(R.string.monitoring_button_view_policies);
+
+ private Supplier<String> mManagementDialogStringSupplier = () ->
+ mContext == null ? null : mContext.getString(
+ R.string.monitoring_description_management);
+
+ private Supplier<String> mManagementDialogCaCertStringSupplier = () ->
+ mContext == null ? null : mContext.getString(
+ R.string.monitoring_description_management_ca_certificate);
+
+ private Supplier<String> mWorkProfileDialogCaCertStringSupplier = () ->
+ mContext == null ? null : mContext.getString(
+ R.string.monitoring_description_managed_profile_ca_certificate);
+
+ private Supplier<String> mManagementDialogNetworkStringSupplier = () ->
+ mContext == null ? null : mContext.getString(
+ R.string.monitoring_description_management_network_logging);
+
+ private Supplier<String> mWorkProfileDialogNetworkStringSupplier = () ->
+ mContext == null ? null : mContext.getString(
+ R.string.monitoring_description_managed_profile_network_logging);
+
+ @Inject
+ QSSecurityFooterUtils(
+ @Application Context context, DevicePolicyManager devicePolicyManager,
+ UserTracker userTracker, @Main Handler mainHandler, ActivityStarter activityStarter,
+ SecurityController securityController, @Background Looper bgLooper,
+ DialogLaunchAnimator dialogLaunchAnimator) {
+ mContext = context;
+ mDpm = devicePolicyManager;
+ mUserTracker = userTracker;
+ mMainHandler = mainHandler;
+ mActivityStarter = activityStarter;
+ mSecurityController = securityController;
+ mBgHandler = new Handler(bgLooper);
+ mDialogLaunchAnimator = dialogLaunchAnimator;
+ }
+
+ /** Show the device monitoring dialog. */
+ public void showDeviceMonitoringDialog(Context quickSettingsContext, @Nullable View view) {
+ createDialog(quickSettingsContext, view);
+ }
+
+ /**
+ * Return the {@link SecurityButtonConfig} of the security button, or {@code null} if no
+ * security button should be shown.
+ */
+ @Nullable
+ public SecurityButtonConfig getButtonConfig(SecurityModel securityModel) {
+ final boolean isDeviceManaged = securityModel.isDeviceManaged();
+ final UserInfo currentUser = mUserTracker.getUserInfo();
+ final boolean isDemoDevice = UserManager.isDeviceInDemoMode(mContext) && currentUser != null
+ && currentUser.isDemo();
+ final boolean hasWorkProfile = securityModel.getHasWorkProfile();
+ final boolean hasCACerts = securityModel.getHasCACertInCurrentUser();
+ final boolean hasCACertsInWorkProfile = securityModel.getHasCACertInWorkProfile();
+ final boolean isNetworkLoggingEnabled = securityModel.isNetworkLoggingEnabled();
+ final String vpnName = securityModel.getPrimaryVpnName();
+ final String vpnNameWorkProfile = securityModel.getWorkProfileVpnName();
+ final CharSequence organizationName = securityModel.getDeviceOwnerOrganizationName();
+ final CharSequence workProfileOrganizationName =
+ securityModel.getWorkProfileOrganizationName();
+ final boolean isProfileOwnerOfOrganizationOwnedDevice =
+ securityModel.isProfileOwnerOfOrganizationOwnedDevice();
+ final boolean isParentalControlsEnabled = securityModel.isParentalControlsEnabled();
+ final boolean isWorkProfileOn = securityModel.isWorkProfileOn();
+ final boolean hasDisclosableWorkProfilePolicy = hasCACertsInWorkProfile
+ || vpnNameWorkProfile != null || (hasWorkProfile && isNetworkLoggingEnabled);
+ // Update visibility of footer
+ boolean isVisible = (isDeviceManaged && !isDemoDevice)
+ || hasCACerts
+ || vpnName != null
+ || isProfileOwnerOfOrganizationOwnedDevice
+ || isParentalControlsEnabled
+ || (hasDisclosableWorkProfilePolicy && isWorkProfileOn);
+ if (!isVisible && !DEBUG_FORCE_VISIBLE) {
+ return null;
+ }
+
+ // Update the view to be untappable if the device is an organization-owned device with a
+ // managed profile and there is either:
+ // a) no policy set which requires a privacy disclosure.
+ // b) a specific work policy set but the work profile is turned off.
+ boolean isClickable = !(isProfileOwnerOfOrganizationOwnedDevice
+ && (!hasDisclosableWorkProfilePolicy || !isWorkProfileOn));
+
+ String text = getFooterText(isDeviceManaged, hasWorkProfile,
+ hasCACerts, hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName,
+ vpnNameWorkProfile, organizationName, workProfileOrganizationName,
+ isProfileOwnerOfOrganizationOwnedDevice, isParentalControlsEnabled,
+ isWorkProfileOn).toString();
+
+ Icon icon;
+ if (isParentalControlsEnabled) {
+ icon = new Icon.Loaded(securityModel.getDeviceAdminIcon());
+ } else if (vpnName != null || vpnNameWorkProfile != null) {
+ if (securityModel.isVpnBranded()) {
+ icon = new Icon.Resource(R.drawable.stat_sys_branded_vpn);
+ } else {
+ icon = new Icon.Resource(R.drawable.stat_sys_vpn_ic);
+ }
+ } else {
+ icon = new Icon.Resource(R.drawable.ic_info_outline);
+ }
+
+ return new SecurityButtonConfig(icon, text, isClickable);
+ }
+
+ @Nullable
+ protected CharSequence getFooterText(boolean isDeviceManaged, boolean hasWorkProfile,
+ boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
+ String vpnName, String vpnNameWorkProfile, CharSequence organizationName,
+ CharSequence workProfileOrganizationName,
+ boolean isProfileOwnerOfOrganizationOwnedDevice, boolean isParentalControlsEnabled,
+ boolean isWorkProfileOn) {
+ if (isParentalControlsEnabled) {
+ return mContext.getString(R.string.quick_settings_disclosure_parental_controls);
+ }
+ if (isDeviceManaged || DEBUG_FORCE_VISIBLE) {
+ return getManagedDeviceFooterText(hasCACerts, hasCACertsInWorkProfile,
+ isNetworkLoggingEnabled, vpnName, vpnNameWorkProfile, organizationName);
+ }
+ return getManagedAndPersonalProfileFooterText(hasWorkProfile, hasCACerts,
+ hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName, vpnNameWorkProfile,
+ workProfileOrganizationName, isProfileOwnerOfOrganizationOwnedDevice,
+ isWorkProfileOn);
+ }
+
+ private String getManagedDeviceFooterText(
+ boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
+ String vpnName, String vpnNameWorkProfile, CharSequence organizationName) {
+ if (hasCACerts || hasCACertsInWorkProfile || isNetworkLoggingEnabled) {
+ return getManagedDeviceMonitoringText(organizationName);
+ }
+ if (vpnName != null || vpnNameWorkProfile != null) {
+ return getManagedDeviceVpnText(vpnName, vpnNameWorkProfile, organizationName);
+ }
+ return getMangedDeviceGeneralText(organizationName);
+ }
+
+ private String getManagedDeviceMonitoringText(CharSequence organizationName) {
+ if (organizationName == null) {
+ return mDpm.getResources().getString(
+ QS_MSG_MANAGEMENT_MONITORING, mManagementMonitoringStringSupplier);
+ }
+ return mDpm.getResources().getString(
+ QS_MSG_NAMED_MANAGEMENT_MONITORING,
+ () -> mContext.getString(
+ R.string.quick_settings_disclosure_named_management_monitoring,
+ organizationName),
+ organizationName);
+ }
+
+ private String getManagedDeviceVpnText(
+ String vpnName, String vpnNameWorkProfile, CharSequence organizationName) {
+ if (vpnName != null && vpnNameWorkProfile != null) {
+ if (organizationName == null) {
+ return mDpm.getResources().getString(
+ QS_MSG_MANAGEMENT_MULTIPLE_VPNS, mManagementMultipleVpnStringSupplier);
+ }
+ return mDpm.getResources().getString(
+ QS_MSG_NAMED_MANAGEMENT_MULTIPLE_VPNS,
+ () -> mContext.getString(
+ R.string.quick_settings_disclosure_named_management_vpns,
+ organizationName),
+ organizationName);
+ }
+ String name = vpnName != null ? vpnName : vpnNameWorkProfile;
+ if (organizationName == null) {
+ return mDpm.getResources().getString(
+ QS_MSG_MANAGEMENT_NAMED_VPN,
+ () -> mContext.getString(
+ R.string.quick_settings_disclosure_management_named_vpn,
+ name),
+ name);
+ }
+ return mDpm.getResources().getString(
+ QS_MSG_NAMED_MANAGEMENT_NAMED_VPN,
+ () -> mContext.getString(
+ R.string.quick_settings_disclosure_named_management_named_vpn,
+ organizationName,
+ name),
+ organizationName,
+ name);
+ }
+
+ private String getMangedDeviceGeneralText(CharSequence organizationName) {
+ if (organizationName == null) {
+ return mDpm.getResources().getString(QS_MSG_MANAGEMENT, mManagementMessageSupplier);
+ }
+ if (isFinancedDevice()) {
+ return mContext.getString(
+ R.string.quick_settings_financed_disclosure_named_management,
+ organizationName);
+ } else {
+ return mDpm.getResources().getString(
+ QS_MSG_NAMED_MANAGEMENT,
+ () -> mContext.getString(
+ R.string.quick_settings_disclosure_named_management,
+ organizationName),
+ organizationName);
+ }
+ }
+
+ private String getManagedAndPersonalProfileFooterText(boolean hasWorkProfile,
+ boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
+ String vpnName, String vpnNameWorkProfile, CharSequence workProfileOrganizationName,
+ boolean isProfileOwnerOfOrganizationOwnedDevice, boolean isWorkProfileOn) {
+ if (hasCACerts || (hasCACertsInWorkProfile && isWorkProfileOn)) {
+ return getMonitoringText(
+ hasCACerts, hasCACertsInWorkProfile, workProfileOrganizationName,
+ isWorkProfileOn);
+ }
+ if (vpnName != null || (vpnNameWorkProfile != null && isWorkProfileOn)) {
+ return getVpnText(hasWorkProfile, vpnName, vpnNameWorkProfile, isWorkProfileOn);
+ }
+ if (hasWorkProfile && isNetworkLoggingEnabled && isWorkProfileOn) {
+ return getManagedProfileNetworkActivityText();
+ }
+ if (isProfileOwnerOfOrganizationOwnedDevice) {
+ return getMangedDeviceGeneralText(workProfileOrganizationName);
+ }
+ return null;
+ }
+
+ private String getMonitoringText(boolean hasCACerts, boolean hasCACertsInWorkProfile,
+ CharSequence workProfileOrganizationName, boolean isWorkProfileOn) {
+ if (hasCACertsInWorkProfile && isWorkProfileOn) {
+ if (workProfileOrganizationName == null) {
+ return mDpm.getResources().getString(
+ QS_MSG_WORK_PROFILE_MONITORING, mWorkProfileMonitoringStringSupplier);
+ }
+ return mDpm.getResources().getString(
+ QS_MSG_NAMED_WORK_PROFILE_MONITORING,
+ () -> mContext.getString(
+ R.string.quick_settings_disclosure_named_managed_profile_monitoring,
+ workProfileOrganizationName),
+ workProfileOrganizationName);
+ }
+ if (hasCACerts) {
+ return mContext.getString(R.string.quick_settings_disclosure_monitoring);
+ }
+ return null;
+ }
+
+ private String getVpnText(boolean hasWorkProfile, String vpnName, String vpnNameWorkProfile,
+ boolean isWorkProfileOn) {
+ if (vpnName != null && vpnNameWorkProfile != null) {
+ return mContext.getString(R.string.quick_settings_disclosure_vpns);
+ }
+ if (vpnNameWorkProfile != null && isWorkProfileOn) {
+ return mDpm.getResources().getString(
+ QS_MSG_WORK_PROFILE_NAMED_VPN,
+ () -> mContext.getString(
+ R.string.quick_settings_disclosure_managed_profile_named_vpn,
+ vpnNameWorkProfile),
+ vpnNameWorkProfile);
+ }
+ if (vpnName != null) {
+ if (hasWorkProfile) {
+ return mDpm.getResources().getString(
+ QS_MSG_PERSONAL_PROFILE_NAMED_VPN,
+ () -> mContext.getString(
+ R.string.quick_settings_disclosure_personal_profile_named_vpn,
+ vpnName),
+ vpnName);
+ }
+ return mContext.getString(R.string.quick_settings_disclosure_named_vpn,
+ vpnName);
+ }
+ return null;
+ }
+
+ private String getManagedProfileNetworkActivityText() {
+ return mDpm.getResources().getString(
+ QS_MSG_WORK_PROFILE_NETWORK, mWorkProfileNetworkStringSupplier);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_NEGATIVE) {
+ final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
+ dialog.dismiss();
+ // This dismisses the shade on opening the activity
+ mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
+ }
+ }
+
+ private void createDialog(Context quickSettingsContext, @Nullable View view) {
+ mShouldUseSettingsButton.set(false);
+ mBgHandler.post(() -> {
+ String settingsButtonText = getSettingsButton();
+ final View dialogView = createDialogView();
+ mMainHandler.post(() -> {
+ mDialog = new SystemUIDialog(quickSettingsContext, 0);
+ mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(), this);
+ mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, mShouldUseSettingsButton.get()
+ ? settingsButtonText : getNegativeButton(), this);
+
+ mDialog.setView(dialogView);
+ if (view != null && view.isAggregatedVisible()) {
+ mDialogLaunchAnimator.showFromView(mDialog, view, new DialogCuj(
+ InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG));
+ } else {
+ mDialog.show();
+ }
+ });
+ });
+ }
+
+ @VisibleForTesting
+ Dialog getDialog() {
+ return mDialog;
+ }
+
+ @VisibleForTesting
+ View createDialogView() {
+ if (mSecurityController.isParentalControlsEnabled()) {
+ return createParentalControlsDialogView();
+ }
+ return createOrganizationDialogView();
+ }
+
+ private View createOrganizationDialogView() {
+ final boolean isDeviceManaged = mSecurityController.isDeviceManaged();
+ final boolean hasWorkProfile = mSecurityController.hasWorkProfile();
+ final CharSequence deviceOwnerOrganization =
+ mSecurityController.getDeviceOwnerOrganizationName();
+ final boolean hasCACerts = mSecurityController.hasCACertInCurrentUser();
+ final boolean hasCACertsInWorkProfile = mSecurityController.hasCACertInWorkProfile();
+ final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
+ final String vpnName = mSecurityController.getPrimaryVpnName();
+ final String vpnNameWorkProfile = mSecurityController.getWorkProfileVpnName();
+
+ View dialogView = LayoutInflater.from(mContext)
+ .inflate(R.layout.quick_settings_footer_dialog, null, false);
+
+ // device management section
+ TextView deviceManagementSubtitle =
+ dialogView.findViewById(R.id.device_management_subtitle);
+ deviceManagementSubtitle.setText(getManagementTitle(deviceOwnerOrganization));
+
+ CharSequence managementMessage = getManagementMessage(isDeviceManaged,
+ deviceOwnerOrganization);
+ if (managementMessage == null) {
+ dialogView.findViewById(R.id.device_management_disclosures).setVisibility(View.GONE);
+ } else {
+ dialogView.findViewById(R.id.device_management_disclosures).setVisibility(View.VISIBLE);
+ TextView deviceManagementWarning =
+ (TextView) dialogView.findViewById(R.id.device_management_warning);
+ deviceManagementWarning.setText(managementMessage);
+ mShouldUseSettingsButton.set(true);
+ }
+
+ // ca certificate section
+ CharSequence caCertsMessage = getCaCertsMessage(isDeviceManaged, hasCACerts,
+ hasCACertsInWorkProfile);
+ if (caCertsMessage == null) {
+ dialogView.findViewById(R.id.ca_certs_disclosures).setVisibility(View.GONE);
+ } else {
+ dialogView.findViewById(R.id.ca_certs_disclosures).setVisibility(View.VISIBLE);
+ TextView caCertsWarning = (TextView) dialogView.findViewById(R.id.ca_certs_warning);
+ caCertsWarning.setText(caCertsMessage);
+ // Make "Open trusted credentials"-link clickable
+ caCertsWarning.setMovementMethod(new LinkMovementMethod());
+
+ TextView caCertsSubtitle = (TextView) dialogView.findViewById(R.id.ca_certs_subtitle);
+ String caCertsSubtitleMessage = mDpm.getResources().getString(
+ QS_DIALOG_MONITORING_CA_CERT_SUBTITLE, mMonitoringSubtitleCaCertStringSupplier);
+ caCertsSubtitle.setText(caCertsSubtitleMessage);
+
+ }
+
+ // network logging section
+ CharSequence networkLoggingMessage = getNetworkLoggingMessage(isDeviceManaged,
+ isNetworkLoggingEnabled);
+ if (networkLoggingMessage == null) {
+ dialogView.findViewById(R.id.network_logging_disclosures).setVisibility(View.GONE);
+ } else {
+ dialogView.findViewById(R.id.network_logging_disclosures).setVisibility(View.VISIBLE);
+ TextView networkLoggingWarning =
+ (TextView) dialogView.findViewById(R.id.network_logging_warning);
+ networkLoggingWarning.setText(networkLoggingMessage);
+
+ TextView networkLoggingSubtitle = (TextView) dialogView.findViewById(
+ R.id.network_logging_subtitle);
+ String networkLoggingSubtitleMessage = mDpm.getResources().getString(
+ QS_DIALOG_MONITORING_NETWORK_SUBTITLE,
+ mMonitoringSubtitleNetworkStringSupplier);
+ networkLoggingSubtitle.setText(networkLoggingSubtitleMessage);
+ }
+
+ // vpn section
+ CharSequence vpnMessage = getVpnMessage(isDeviceManaged, hasWorkProfile, vpnName,
+ vpnNameWorkProfile);
+ if (vpnMessage == null) {
+ dialogView.findViewById(R.id.vpn_disclosures).setVisibility(View.GONE);
+ } else {
+ dialogView.findViewById(R.id.vpn_disclosures).setVisibility(View.VISIBLE);
+ TextView vpnWarning = (TextView) dialogView.findViewById(R.id.vpn_warning);
+ vpnWarning.setText(vpnMessage);
+ // Make "Open VPN Settings"-link clickable
+ vpnWarning.setMovementMethod(new LinkMovementMethod());
+
+ TextView vpnSubtitle = (TextView) dialogView.findViewById(R.id.vpn_subtitle);
+ String vpnSubtitleMessage = mDpm.getResources().getString(
+ QS_DIALOG_MONITORING_VPN_SUBTITLE, mMonitoringSubtitleVpnStringSupplier);
+ vpnSubtitle.setText(vpnSubtitleMessage);
+ }
+
+ // Note: if a new section is added, should update configSubtitleVisibility to include
+ // the handling of the subtitle
+ configSubtitleVisibility(managementMessage != null,
+ caCertsMessage != null,
+ networkLoggingMessage != null,
+ vpnMessage != null,
+ dialogView);
+
+ return dialogView;
+ }
+
+ private View createParentalControlsDialogView() {
+ View dialogView = LayoutInflater.from(mContext)
+ .inflate(R.layout.quick_settings_footer_dialog_parental_controls, null, false);
+
+ DeviceAdminInfo info = mSecurityController.getDeviceAdminInfo();
+ Drawable icon = mSecurityController.getIcon(info);
+ if (icon != null) {
+ ImageView imageView = (ImageView) dialogView.findViewById(R.id.parental_controls_icon);
+ imageView.setImageDrawable(icon);
+ }
+
+ TextView parentalControlsTitle =
+ (TextView) dialogView.findViewById(R.id.parental_controls_title);
+ parentalControlsTitle.setText(mSecurityController.getLabel(info));
+
+ return dialogView;
+ }
+
+ protected void configSubtitleVisibility(boolean showDeviceManagement, boolean showCaCerts,
+ boolean showNetworkLogging, boolean showVpn, View dialogView) {
+ // Device Management title should always been shown
+ // When there is a Device Management message, all subtitles should be shown
+ if (showDeviceManagement) {
+ return;
+ }
+ // Hide the subtitle if there is only 1 message shown
+ int mSectionCountExcludingDeviceMgt = 0;
+ if (showCaCerts) {
+ mSectionCountExcludingDeviceMgt++;
+ }
+ if (showNetworkLogging) {
+ mSectionCountExcludingDeviceMgt++;
+ }
+ if (showVpn) {
+ mSectionCountExcludingDeviceMgt++;
+ }
+
+ // No work needed if there is no sections or more than 1 section
+ if (mSectionCountExcludingDeviceMgt != 1) {
+ return;
+ }
+ if (showCaCerts) {
+ dialogView.findViewById(R.id.ca_certs_subtitle).setVisibility(View.GONE);
+ }
+ if (showNetworkLogging) {
+ dialogView.findViewById(R.id.network_logging_subtitle).setVisibility(View.GONE);
+ }
+ if (showVpn) {
+ dialogView.findViewById(R.id.vpn_subtitle).setVisibility(View.GONE);
+ }
+ }
+
+ // This should not be called on the main thread to avoid making an IPC.
+ @VisibleForTesting
+ String getSettingsButton() {
+ return mDpm.getResources().getString(
+ QS_DIALOG_VIEW_POLICIES, mViewPoliciesButtonStringSupplier);
+ }
+
+ private String getPositiveButton() {
+ return mContext.getString(R.string.ok);
+ }
+
+ @Nullable
+ private String getNegativeButton() {
+ if (mSecurityController.isParentalControlsEnabled()) {
+ return mContext.getString(R.string.monitoring_button_view_controls);
+ }
+ return null;
+ }
+
+ @Nullable
+ protected CharSequence getManagementMessage(boolean isDeviceManaged,
+ CharSequence organizationName) {
+ if (!isDeviceManaged) {
+ return null;
+ }
+ if (organizationName != null) {
+ if (isFinancedDevice()) {
+ return mContext.getString(R.string.monitoring_financed_description_named_management,
+ organizationName, organizationName);
+ } else {
+ return mDpm.getResources().getString(
+ QS_DIALOG_NAMED_MANAGEMENT,
+ () -> mContext.getString(
+ R.string.monitoring_description_named_management,
+ organizationName),
+ organizationName);
+ }
+ }
+ return mDpm.getResources().getString(QS_DIALOG_MANAGEMENT, mManagementDialogStringSupplier);
+ }
+
+ @Nullable
+ protected CharSequence getCaCertsMessage(boolean isDeviceManaged, boolean hasCACerts,
+ boolean hasCACertsInWorkProfile) {
+ if (!(hasCACerts || hasCACertsInWorkProfile)) return null;
+ if (isDeviceManaged) {
+ return mDpm.getResources().getString(
+ QS_DIALOG_MANAGEMENT_CA_CERT, mManagementDialogCaCertStringSupplier);
+ }
+ if (hasCACertsInWorkProfile) {
+ return mDpm.getResources().getString(
+ QS_DIALOG_WORK_PROFILE_CA_CERT, mWorkProfileDialogCaCertStringSupplier);
+ }
+ return mContext.getString(R.string.monitoring_description_ca_certificate);
+ }
+
+ @Nullable
+ protected CharSequence getNetworkLoggingMessage(boolean isDeviceManaged,
+ boolean isNetworkLoggingEnabled) {
+ if (!isNetworkLoggingEnabled) return null;
+ if (isDeviceManaged) {
+ return mDpm.getResources().getString(
+ QS_DIALOG_MANAGEMENT_NETWORK, mManagementDialogNetworkStringSupplier);
+ } else {
+ return mDpm.getResources().getString(
+ QS_DIALOG_WORK_PROFILE_NETWORK, mWorkProfileDialogNetworkStringSupplier);
+ }
+ }
+
+ @Nullable
+ protected CharSequence getVpnMessage(boolean isDeviceManaged, boolean hasWorkProfile,
+ String vpnName, String vpnNameWorkProfile) {
+ if (vpnName == null && vpnNameWorkProfile == null) return null;
+ final SpannableStringBuilder message = new SpannableStringBuilder();
+ if (isDeviceManaged) {
+ if (vpnName != null && vpnNameWorkProfile != null) {
+ String namedVpns = mDpm.getResources().getString(
+ QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN,
+ () -> mContext.getString(
+ R.string.monitoring_description_two_named_vpns,
+ vpnName, vpnNameWorkProfile),
+ vpnName, vpnNameWorkProfile);
+ message.append(namedVpns);
+ } else {
+ String name = vpnName != null ? vpnName : vpnNameWorkProfile;
+ String namedVp = mDpm.getResources().getString(
+ QS_DIALOG_MANAGEMENT_NAMED_VPN,
+ () -> mContext.getString(R.string.monitoring_description_named_vpn, name),
+ name);
+ message.append(namedVp);
+ }
+ } else {
+ if (vpnName != null && vpnNameWorkProfile != null) {
+ String namedVpns = mDpm.getResources().getString(
+ QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN,
+ () -> mContext.getString(
+ R.string.monitoring_description_two_named_vpns,
+ vpnName, vpnNameWorkProfile),
+ vpnName, vpnNameWorkProfile);
+ message.append(namedVpns);
+ } else if (vpnNameWorkProfile != null) {
+ String namedVpn = mDpm.getResources().getString(
+ QS_DIALOG_WORK_PROFILE_NAMED_VPN,
+ () -> mContext.getString(
+ R.string.monitoring_description_managed_profile_named_vpn,
+ vpnNameWorkProfile),
+ vpnNameWorkProfile);
+ message.append(namedVpn);
+ } else if (hasWorkProfile) {
+ String namedVpn = mDpm.getResources().getString(
+ QS_DIALOG_PERSONAL_PROFILE_NAMED_VPN,
+ () -> mContext.getString(
+ R.string.monitoring_description_personal_profile_named_vpn,
+ vpnName),
+ vpnName);
+ message.append(namedVpn);
+ } else {
+ message.append(mContext.getString(R.string.monitoring_description_named_vpn,
+ vpnName));
+ }
+ }
+ message.append(mContext.getString(R.string.monitoring_description_vpn_settings_separator));
+ message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
+ new VpnSpan(), 0);
+ return message;
+ }
+
+ @VisibleForTesting
+ CharSequence getManagementTitle(CharSequence deviceOwnerOrganization) {
+ if (deviceOwnerOrganization != null && isFinancedDevice()) {
+ return mContext.getString(R.string.monitoring_title_financed_device,
+ deviceOwnerOrganization);
+ } else {
+ return mDpm.getResources().getString(
+ QS_DIALOG_MANAGEMENT_TITLE,
+ mManagementTitleSupplier);
+ }
+ }
+
+ private boolean isFinancedDevice() {
+ return mSecurityController.isDeviceManaged()
+ && mSecurityController.getDeviceOwnerType(
+ mSecurityController.getDeviceOwnerComponentOnAnyUser())
+ == DEVICE_OWNER_TYPE_FINANCED;
+ }
+
+ protected class VpnSpan extends ClickableSpan {
+ @Override
+ public void onClick(View widget) {
+ final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
+ mDialog.dismiss();
+ // This dismisses the shade on opening the activity
+ mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
+ }
+
+ // for testing, to compare two CharSequences containing VpnSpans
+ @Override
+ public boolean equals(Object object) {
+ return object instanceof VpnSpan;
+ }
+
+ @Override
+ public int hashCode() {
+ return 314159257; // prime
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java
index 3f93108..5da4809 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java
@@ -17,7 +17,14 @@
import javax.inject.Inject;
-/** */
+/**
+ * Plays a animation to reveal newly added QS tiles.
+ *
+ * The aniumation is played when the user fully opens Quick Settings, and is only shown for
+ * <li> tiles added automatically (not through user customization)
+ * <li> tiles not have been revealed before (memoized via {@code QS_TILE_SPECS_REVEALED}
+ * preference)
+ */
public class QSTileRevealController {
private static final long QS_REVEAL_TILES_DELAY = 500L;
@@ -39,6 +46,7 @@
});
}
};
+
QSTileRevealController(Context context, QSPanelController qsPanelController,
PagedTileLayout pagedTileLayout, QSCustomizerController qsCustomizerController) {
mContext = context;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 112b1e8..46724ad 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -54,7 +54,9 @@
@Override
public TileLayout getOrCreateTileLayout() {
- return new QQSSideLabelTileLayout(mContext);
+ QQSSideLabelTileLayout layout = new QQSSideLabelTileLayout(mContext);
+ layout.setId(R.id.qqs_tile_layout);
+ return layout;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index be44202..c86e6e8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -26,6 +26,7 @@
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaCarouselController;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.qs.QSTile;
@@ -63,10 +64,10 @@
@Named(QS_USING_COLLAPSED_LANDSCAPE_MEDIA)
Provider<Boolean> usingCollapsedLandscapeMediaProvider,
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
- DumpManager dumpManager
+ DumpManager dumpManager, MediaCarouselController mediaCarouselController
) {
super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
- uiEventLogger, qsLogger, dumpManager);
+ uiEventLogger, qsLogger, dumpManager, mediaCarouselController);
mUsingCollapsedLandscapeMediaProvider = usingCollapsedLandscapeMediaProvider;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index 2a6cf66..b585961 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -128,6 +128,8 @@
mPrivacyIconsController.setChipVisibilityListener(this);
mIconContainer.addIgnoredSlot(
getResources().getString(com.android.internal.R.string.status_bar_managed_profile));
+ mIconContainer.addIgnoredSlot(
+ getResources().getString(com.android.internal.R.string.status_bar_alarm_clock));
mIconContainer.setShouldRestrictIcons(false);
mStatusBarIconController.addIconGroup(mIconManager);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/dagger/FooterActionsModule.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/dagger/FooterActionsModule.kt
new file mode 100644
index 0000000..38fe34e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/dagger/FooterActionsModule.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.footer.dagger
+
+import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepository
+import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepositoryImpl
+import com.android.systemui.qs.footer.data.repository.UserSwitcherRepository
+import com.android.systemui.qs.footer.data.repository.UserSwitcherRepositoryImpl
+import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
+import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractorImpl
+import dagger.Binds
+import dagger.Module
+
+/** Dagger module to provide/bind footer actions singletons. */
+@Module
+interface FooterActionsModule {
+ @Binds fun userSwitcherRepository(impl: UserSwitcherRepositoryImpl): UserSwitcherRepository
+
+ @Binds
+ fun foregroundServicesRepository(
+ impl: ForegroundServicesRepositoryImpl
+ ): ForegroundServicesRepository
+
+ @Binds fun footerActionsInteractor(impl: FooterActionsInteractorImpl): FooterActionsInteractor
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/data/model/UserSwitcherStatusModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/data/model/UserSwitcherStatusModel.kt
new file mode 100644
index 0000000..4ca229a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/data/model/UserSwitcherStatusModel.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.footer.data.model
+
+import android.graphics.drawable.Drawable
+
+/** The current status of the User Switcher. */
+sealed class UserSwitcherStatusModel {
+ /** The user switcher is disabled. */
+ object Disabled : UserSwitcherStatusModel()
+
+ /** The user switcher is enabled. */
+ data class Enabled(
+ val currentUserName: String?,
+ val currentUserImage: Drawable?,
+ val isGuestUser: Boolean,
+ ) : UserSwitcherStatusModel()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/data/repository/ForegroundServicesRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/data/repository/ForegroundServicesRepository.kt
new file mode 100644
index 0000000..37a9c40
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/data/repository/ForegroundServicesRepository.kt
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.footer.data.repository
+
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.FgsManagerController
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
+
+interface ForegroundServicesRepository {
+ /**
+ * The number of packages with a service running in the foreground.
+ *
+ * Note that this will be equal to 0 if [FgsManagerController.isAvailable] is false.
+ */
+ val foregroundServicesCount: Flow<Int>
+
+ /**
+ * Whether there were new changes to the foreground packages since a dialog was last shown.
+ *
+ * Note that this will be equal to `false` if [FgsManagerController.showFooterDot] is false.
+ */
+ val hasNewChanges: Flow<Boolean>
+}
+
+@SysUISingleton
+class ForegroundServicesRepositoryImpl
+@Inject
+constructor(
+ fgsManagerController: FgsManagerController,
+) : ForegroundServicesRepository {
+ override val foregroundServicesCount: Flow<Int> =
+ fgsManagerController.isAvailable
+ .flatMapLatest { isAvailable ->
+ if (!isAvailable) {
+ return@flatMapLatest flowOf(0)
+ }
+
+ conflatedCallbackFlow {
+ fun updateState(numberOfPackages: Int) {
+ trySendWithFailureLogging(numberOfPackages, TAG)
+ }
+
+ val listener =
+ object : FgsManagerController.OnNumberOfPackagesChangedListener {
+ override fun onNumberOfPackagesChanged(numberOfPackages: Int) {
+ updateState(numberOfPackages)
+ }
+ }
+
+ fgsManagerController.addOnNumberOfPackagesChangedListener(listener)
+ updateState(fgsManagerController.numRunningPackages)
+ awaitClose {
+ fgsManagerController.removeOnNumberOfPackagesChangedListener(listener)
+ }
+ }
+ }
+ .distinctUntilChanged()
+
+ override val hasNewChanges: Flow<Boolean> =
+ fgsManagerController.showFooterDot.flatMapLatest { showFooterDot ->
+ if (!showFooterDot) {
+ return@flatMapLatest flowOf(false)
+ }
+
+ // A flow that emits whenever the FGS dialog is dismissed.
+ val dialogDismissedEvents = conflatedCallbackFlow {
+ fun updateState() {
+ trySendWithFailureLogging(
+ Unit,
+ TAG,
+ )
+ }
+
+ val listener =
+ object : FgsManagerController.OnDialogDismissedListener {
+ override fun onDialogDismissed() {
+ updateState()
+ }
+ }
+
+ fgsManagerController.addOnDialogDismissedListener(listener)
+ awaitClose { fgsManagerController.removeOnDialogDismissedListener(listener) }
+ }
+
+ // Query [fgsManagerController.newChangesSinceDialogWasDismissed] everytime the dialog
+ // is dismissed or when [foregroundServices] is changing.
+ merge(
+ foregroundServicesCount,
+ dialogDismissedEvents,
+ )
+ .map { fgsManagerController.newChangesSinceDialogWasDismissed }
+ .distinctUntilChanged()
+ }
+
+ companion object {
+ private const val TAG = "ForegroundServicesRepositoryImpl"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/data/repository/UserSwitcherRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/data/repository/UserSwitcherRepository.kt
new file mode 100644
index 0000000..e969d4c6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/data/repository/UserSwitcherRepository.kt
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.footer.data.repository
+
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.os.Handler
+import android.os.UserManager
+import android.provider.Settings.Global.USER_SWITCHER_ENABLED
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.R
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.qs.SettingObserver
+import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.policy.UserInfoController
+import com.android.systemui.statusbar.policy.UserSwitcherController
+import com.android.systemui.util.settings.GlobalSettings
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+interface UserSwitcherRepository {
+ /** The current [UserSwitcherStatusModel]. */
+ val userSwitcherStatus: Flow<UserSwitcherStatusModel>
+}
+
+@SysUISingleton
+class UserSwitcherRepositoryImpl
+@Inject
+constructor(
+ @Application private val context: Context,
+ @Background private val bgHandler: Handler,
+ @Background private val bgDispatcher: CoroutineDispatcher,
+ private val userManager: UserManager,
+ private val userTracker: UserTracker,
+ private val userSwitcherController: UserSwitcherController,
+ private val userInfoController: UserInfoController,
+ private val globalSetting: GlobalSettings,
+) : UserSwitcherRepository {
+ private val showUserSwitcherForSingleUser =
+ context.resources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)
+
+ /** Whether the user switcher is currently enabled. */
+ private val isEnabled: Flow<Boolean> = conflatedCallbackFlow {
+ suspend fun updateState() {
+ trySendWithFailureLogging(isUserSwitcherEnabled(), TAG)
+ }
+
+ val observer =
+ object :
+ SettingObserver(
+ globalSetting,
+ bgHandler,
+ USER_SWITCHER_ENABLED,
+ userTracker.userId,
+ ) {
+ override fun handleValueChanged(value: Int, observedChange: Boolean) {
+ if (observedChange) {
+ launch { updateState() }
+ }
+ }
+ }
+
+ observer.isListening = true
+ updateState()
+ awaitClose { observer.isListening = false }
+ }
+
+ /** The current user name. */
+ private val currentUserName: Flow<String?> = conflatedCallbackFlow {
+ suspend fun updateState() {
+ trySendWithFailureLogging(getCurrentUser(), TAG)
+ }
+
+ val callback = UserSwitcherController.UserSwitchCallback { launch { updateState() } }
+
+ userSwitcherController.addUserSwitchCallback(callback)
+ updateState()
+ awaitClose { userSwitcherController.removeUserSwitchCallback(callback) }
+ }
+
+ /** The current (icon, isGuestUser) values. */
+ // TODO(b/242040009): Could we only use this callback to get the user name and remove
+ // currentUsername above?
+ private val currentUserInfo: Flow<Pair<Drawable?, Boolean>> = conflatedCallbackFlow {
+ val listener =
+ UserInfoController.OnUserInfoChangedListener { _, picture, _ ->
+ launch { trySendWithFailureLogging(picture to isGuestUser(), TAG) }
+ }
+
+ // This will automatically call the listener when attached, so no need to update the state
+ // here.
+ userInfoController.addCallback(listener)
+ awaitClose { userInfoController.removeCallback(listener) }
+ }
+
+ override val userSwitcherStatus: Flow<UserSwitcherStatusModel> =
+ isEnabled
+ .flatMapLatest { enabled ->
+ if (enabled) {
+ combine(currentUserName, currentUserInfo) { name, (icon, isGuest) ->
+ UserSwitcherStatusModel.Enabled(name, icon, isGuest)
+ }
+ } else {
+ flowOf(UserSwitcherStatusModel.Disabled)
+ }
+ }
+ .distinctUntilChanged()
+
+ private suspend fun isUserSwitcherEnabled(): Boolean {
+ return withContext(bgDispatcher) {
+ userManager.isUserSwitcherEnabled(showUserSwitcherForSingleUser)
+ }
+ }
+
+ private suspend fun getCurrentUser(): String? {
+ return withContext(bgDispatcher) { userSwitcherController.currentUserName }
+ }
+
+ private suspend fun isGuestUser(): Boolean {
+ return withContext(bgDispatcher) {
+ userManager.isGuestUser(KeyguardUpdateMonitor.getCurrentUser())
+ }
+ }
+
+ companion object {
+ private const val TAG = "UserSwitcherRepositoryImpl"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
new file mode 100644
index 0000000..cf9b41c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.footer.domain.interactor
+
+import android.app.admin.DevicePolicyEventLogger
+import android.app.admin.DevicePolicyManager
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.UserHandle
+import android.provider.Settings
+import android.view.View
+import com.android.internal.jank.InteractionJankMonitor
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.UiEventLogger
+import com.android.internal.logging.nano.MetricsProto
+import com.android.internal.util.FrameworkStatsLog
+import com.android.systemui.animation.ActivityLaunchAnimator
+import com.android.systemui.animation.Expandable
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.qs.FgsManagerController
+import com.android.systemui.qs.QSSecurityFooterUtils
+import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel
+import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepository
+import com.android.systemui.qs.footer.data.repository.UserSwitcherRepository
+import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
+import com.android.systemui.qs.user.UserSwitchDialogController
+import com.android.systemui.security.data.repository.SecurityRepository
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.user.UserSwitcherActivity
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.withContext
+
+/** Interactor for the footer actions business logic. */
+interface FooterActionsInteractor {
+ /** The current [SecurityButtonConfig]. */
+ val securityButtonConfig: Flow<SecurityButtonConfig?>
+
+ /** The number of packages with a service running in the foreground. */
+ val foregroundServicesCount: Flow<Int>
+
+ /** Whether there are new packages with a service running in the foreground. */
+ val hasNewForegroundServices: Flow<Boolean>
+
+ /** The current [UserSwitcherStatusModel]. */
+ val userSwitcherStatus: Flow<UserSwitcherStatusModel>
+
+ /**
+ * The flow emitting `Unit` whenever a request to show the device monitoring dialog is fired.
+ */
+ val deviceMonitoringDialogRequests: Flow<Unit>
+
+ /**
+ * Show the device monitoring dialog, expanded from [view].
+ *
+ * Important: [view] must be associated to the same [Context] as the [Quick Settings fragment]
+ * [com.android.systemui.qs.QSFragment].
+ */
+ // TODO(b/230830644): Replace view by Expandable interface.
+ fun showDeviceMonitoringDialog(view: View)
+
+ /**
+ * Show the device monitoring dialog.
+ *
+ * Important: [quickSettingsContext] *must* be the [Context] associated to the [Quick Settings
+ * fragment][com.android.systemui.qs.QSFragment].
+ */
+ // TODO(b/230830644): Replace view by Expandable interface.
+ fun showDeviceMonitoringDialog(quickSettingsContext: Context)
+
+ /** Show the foreground services dialog. */
+ // TODO(b/230830644): Replace view by Expandable interface.
+ fun showForegroundServicesDialog(view: View)
+
+ /** Show the power menu dialog. */
+ // TODO(b/230830644): Replace view by Expandable interface.
+ fun showPowerMenuDialog(globalActionsDialogLite: GlobalActionsDialogLite, view: View)
+
+ /** Show the settings. */
+ fun showSettings(expandable: Expandable)
+
+ /** Show the user switcher. */
+ // TODO(b/230830644): Replace view by Expandable interface.
+ fun showUserSwitcher(view: View)
+}
+
+@SysUISingleton
+class FooterActionsInteractorImpl
+@Inject
+constructor(
+ private val activityStarter: ActivityStarter,
+ private val featureFlags: FeatureFlags,
+ private val metricsLogger: MetricsLogger,
+ private val uiEventLogger: UiEventLogger,
+ private val deviceProvisionedController: DeviceProvisionedController,
+ private val qsSecurityFooterUtils: QSSecurityFooterUtils,
+ private val fgsManagerController: FgsManagerController,
+ private val userSwitchDialogController: UserSwitchDialogController,
+ securityRepository: SecurityRepository,
+ foregroundServicesRepository: ForegroundServicesRepository,
+ userSwitcherRepository: UserSwitcherRepository,
+ broadcastDispatcher: BroadcastDispatcher,
+ @Background bgDispatcher: CoroutineDispatcher,
+) : FooterActionsInteractor {
+ override val securityButtonConfig: Flow<SecurityButtonConfig?> =
+ securityRepository.security.map { security ->
+ withContext(bgDispatcher) { qsSecurityFooterUtils.getButtonConfig(security) }
+ }
+
+ override val foregroundServicesCount: Flow<Int> =
+ foregroundServicesRepository.foregroundServicesCount
+
+ override val hasNewForegroundServices: Flow<Boolean> =
+ foregroundServicesRepository.hasNewChanges
+
+ override val userSwitcherStatus: Flow<UserSwitcherStatusModel> =
+ userSwitcherRepository.userSwitcherStatus
+
+ override val deviceMonitoringDialogRequests: Flow<Unit> =
+ broadcastDispatcher.broadcastFlow(
+ IntentFilter(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG),
+ UserHandle.ALL,
+ Context.RECEIVER_EXPORTED,
+ null,
+ )
+
+ override fun showDeviceMonitoringDialog(view: View) {
+ qsSecurityFooterUtils.showDeviceMonitoringDialog(view.context, view)
+ DevicePolicyEventLogger.createEvent(
+ FrameworkStatsLog.DEVICE_POLICY_EVENT__EVENT_ID__DO_USER_INFO_CLICKED
+ )
+ .write()
+ }
+
+ override fun showDeviceMonitoringDialog(quickSettingsContext: Context) {
+ qsSecurityFooterUtils.showDeviceMonitoringDialog(quickSettingsContext, /* view= */ null)
+ }
+
+ override fun showForegroundServicesDialog(view: View) {
+ fgsManagerController.showDialog(view)
+ }
+
+ override fun showPowerMenuDialog(globalActionsDialogLite: GlobalActionsDialogLite, view: View) {
+ uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)
+ globalActionsDialogLite.showOrHideDialog(
+ /* keyguardShowing= */ false,
+ /* isDeviceProvisioned= */ true,
+ view,
+ )
+ }
+
+ override fun showSettings(expandable: Expandable) {
+ if (!deviceProvisionedController.isCurrentUserSetup) {
+ // If user isn't setup just unlock the device and dump them back at SUW.
+ activityStarter.postQSRunnableDismissingKeyguard {}
+ return
+ }
+
+ metricsLogger.action(MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH)
+ activityStarter.startActivity(
+ Intent(Settings.ACTION_SETTINGS),
+ true /* dismissShade */,
+ expandable.activityLaunchController(
+ InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON
+ ),
+ )
+ }
+
+ override fun showUserSwitcher(view: View) {
+ if (!featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)) {
+ userSwitchDialogController.showDialog(view)
+ return
+ }
+
+ val intent =
+ Intent(view.context, UserSwitcherActivity::class.java).apply {
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+
+ activityStarter.startActivity(
+ intent,
+ true /* dismissShade */,
+ ActivityLaunchAnimator.Controller.fromView(view, null),
+ true /* showOverlockscreenwhenlocked */,
+ UserHandle.SYSTEM,
+ )
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/model/SecurityButtonConfig.kt
similarity index 61%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
copy to packages/SystemUI/src/com/android/systemui/qs/footer/domain/model/SecurityButtonConfig.kt
index e62a63a..be9c0c1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/model/SecurityButtonConfig.kt
@@ -14,18 +14,13 @@
* limitations under the License.
*/
-package com.android.wm.shell.desktopmode;
+package com.android.systemui.qs.footer.domain.model
-import android.os.SystemProperties;
+import com.android.systemui.common.shared.model.Icon
-/**
- * Constants for desktop mode feature
- */
-public class DesktopModeConstants {
-
- /**
- * Flag to indicate whether desktop mode is available on the device
- */
- public static final boolean IS_FEATURE_ENABLED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode", false);
-}
+/** The config for the security button. */
+data class SecurityButtonConfig(
+ val icon: Icon,
+ val text: String,
+ val isClickable: Boolean,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt
new file mode 100644
index 0000000..8dd506e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.footer.ui.binder
+
+import android.content.Context
+import android.graphics.PorterDuff
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.core.view.isInvisible
+import androidx.core.view.isVisible
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.R
+import com.android.systemui.common.ui.binder.ContentDescriptionViewBinder
+import com.android.systemui.common.ui.binder.IconViewBinder
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.people.ui.view.PeopleViewBinder.bind
+import com.android.systemui.qs.FooterActionsView
+import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsButtonViewModel
+import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsForegroundServicesButtonViewModel
+import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsSecurityButtonViewModel
+import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
+
+/** A ViewBinder for [FooterActionsViewBinder]. */
+object FooterActionsViewBinder {
+ /**
+ * Create a [FooterActionsView] that can later be [bound][bind] to a [FooterActionsViewModel].
+ */
+ @JvmStatic
+ fun create(context: Context): FooterActionsView {
+ return LayoutInflater.from(context).inflate(R.layout.footer_actions, /* root= */ null)
+ as FooterActionsView
+ }
+
+ /** Bind [view] to [viewModel]. */
+ @JvmStatic
+ fun bind(
+ view: FooterActionsView,
+ viewModel: FooterActionsViewModel,
+ qsVisibilityLifecycleOwner: LifecycleOwner,
+ ) {
+ // Remove all children of the FooterActionsView that are used by the old implementation.
+ // TODO(b/242040009): Clean up the XML once the old implementation is removed.
+ view.removeAllViews()
+
+ // Add the views used by this new implementation.
+ val context = view.context
+ val inflater = LayoutInflater.from(context)
+
+ val securityHolder = TextButtonViewHolder.createAndAdd(inflater, view)
+ val foregroundServicesWithTextHolder = TextButtonViewHolder.createAndAdd(inflater, view)
+ val foregroundServicesWithNumberHolder = NumberButtonViewHolder.createAndAdd(inflater, view)
+ val userSwitcherHolder = IconButtonViewHolder.createAndAdd(inflater, view, isLast = false)
+ val settingsHolder =
+ IconButtonViewHolder.createAndAdd(inflater, view, isLast = viewModel.power == null)
+
+ // Bind the static power and settings buttons.
+ bindButton(settingsHolder, viewModel.settings)
+
+ if (viewModel.power != null) {
+ val powerHolder = IconButtonViewHolder.createAndAdd(inflater, view, isLast = true)
+ bindButton(powerHolder, viewModel.power)
+ }
+
+ // There are 2 lifecycle scopes we are using here:
+ // 1) The scope created by [repeatWhenAttached] when [view] is attached, and destroyed
+ // when the [view] is detached. We use this as the parent scope for all our [viewModel]
+ // state collection, given that we don't want to do any work when [view] is detached.
+ // 2) The scope owned by [lifecycleOwner], which should be RESUMED only when Quick
+ // Settings are visible. We use this to make sure we collect UI state only when the
+ // View is visible.
+ //
+ // Given that we start our collection when the Quick Settings become visible, which happens
+ // every time the user swipes down the shade, we remember our previous UI state already
+ // bound to the UI to avoid binding the same values over and over for nothing.
+
+ // TODO(b/242040009): Look into using only a single scope.
+
+ var previousSecurity: FooterActionsSecurityButtonViewModel? = null
+ var previousForegroundServices: FooterActionsForegroundServicesButtonViewModel? = null
+ var previousUserSwitcher: FooterActionsButtonViewModel? = null
+
+ view.repeatWhenAttached {
+ val attachedScope = this.lifecycleScope
+
+ attachedScope.launch {
+ // Listen for dialog requests as soon as we are attached, even when not visible.
+ // TODO(b/242040009): Should this move somewhere else?
+ launch { viewModel.observeDeviceMonitoringDialogRequests(view.context) }
+
+ // Make sure we set the correct visibility and alpha even when QS are not currently
+ // shown.
+ launch {
+ viewModel.isVisible.collect { isVisible -> view.isInvisible = !isVisible }
+ }
+
+ launch { viewModel.alpha.collect { view.alpha = it } }
+ launch { viewModel.backgroundAlpha.collect { view.backgroundAlpha = it } }
+ }
+
+ // Listen for model changes only when QS are visible.
+ qsVisibilityLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
+ // Security.
+ launch {
+ viewModel.security.collect { security ->
+ if (previousSecurity != security) {
+ bindSecurity(securityHolder, security)
+ previousSecurity = security
+ }
+ }
+ }
+
+ // Foreground services.
+ launch {
+ viewModel.foregroundServices.collect { foregroundServices ->
+ if (previousForegroundServices != foregroundServices) {
+ bindForegroundService(
+ foregroundServicesWithNumberHolder,
+ foregroundServicesWithTextHolder,
+ foregroundServices,
+ )
+ previousForegroundServices = foregroundServices
+ }
+ }
+ }
+
+ // User switcher.
+ launch {
+ viewModel.userSwitcher.collect { userSwitcher ->
+ if (previousUserSwitcher != userSwitcher) {
+ bindButton(userSwitcherHolder, userSwitcher)
+ previousUserSwitcher = userSwitcher
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private fun bindSecurity(
+ securityHolder: TextButtonViewHolder,
+ security: FooterActionsSecurityButtonViewModel?,
+ ) {
+ val securityView = securityHolder.view
+ securityView.isVisible = security != null
+ if (security == null) {
+ return
+ }
+
+ // Make sure that the chevron is visible and that the button is clickable if there is a
+ // listener.
+ val chevron = securityHolder.chevron
+ if (security.onClick != null) {
+ securityView.isClickable = true
+ securityView.setOnClickListener(security.onClick)
+ chevron.isVisible = true
+ } else {
+ securityView.isClickable = false
+ securityView.setOnClickListener(null)
+ chevron.isVisible = false
+ }
+
+ securityHolder.text.text = security.text
+ securityHolder.newDot.isVisible = false
+ IconViewBinder.bind(security.icon, securityHolder.icon)
+ }
+
+ private fun bindForegroundService(
+ foregroundServicesWithNumberHolder: NumberButtonViewHolder,
+ foregroundServicesWithTextHolder: TextButtonViewHolder,
+ foregroundServices: FooterActionsForegroundServicesButtonViewModel?,
+ ) {
+ val foregroundServicesWithNumberView = foregroundServicesWithNumberHolder.view
+ val foregroundServicesWithTextView = foregroundServicesWithTextHolder.view
+ if (foregroundServices == null) {
+ foregroundServicesWithNumberView.isVisible = false
+ foregroundServicesWithTextView.isVisible = false
+ return
+ }
+
+ val foregroundServicesCount = foregroundServices.foregroundServicesCount
+ if (foregroundServices.displayText) {
+ // Button with text, icon and chevron.
+ foregroundServicesWithNumberView.isVisible = false
+
+ foregroundServicesWithTextView.isVisible = true
+ foregroundServicesWithTextView.setOnClickListener(foregroundServices.onClick)
+ foregroundServicesWithTextHolder.text.text = foregroundServices.text
+ foregroundServicesWithTextHolder.newDot.isVisible = foregroundServices.hasNewChanges
+ } else {
+ // Small button with the number only.
+ foregroundServicesWithTextView.isVisible = false
+
+ foregroundServicesWithNumberView.visibility = View.VISIBLE
+ foregroundServicesWithNumberView.setOnClickListener(foregroundServices.onClick)
+ foregroundServicesWithNumberHolder.number.text = foregroundServicesCount.toString()
+ foregroundServicesWithNumberHolder.number.contentDescription = foregroundServices.text
+ foregroundServicesWithNumberHolder.newDot.isVisible = foregroundServices.hasNewChanges
+ }
+ }
+
+ private fun bindButton(button: IconButtonViewHolder, model: FooterActionsButtonViewModel?) {
+ val buttonView = button.view
+ buttonView.isVisible = model != null
+ if (model == null) {
+ return
+ }
+
+ buttonView.setBackgroundResource(model.background)
+ buttonView.setOnClickListener(model.onClick)
+
+ val icon = model.icon
+ val iconView = button.icon
+ val contentDescription = model.contentDescription
+
+ IconViewBinder.bind(icon, iconView)
+ ContentDescriptionViewBinder.bind(contentDescription, iconView)
+ if (model.iconTint != null) {
+ iconView.setColorFilter(model.iconTint, PorterDuff.Mode.SRC_IN)
+ } else {
+ iconView.clearColorFilter()
+ }
+ }
+}
+
+private class TextButtonViewHolder(val view: View) {
+ val icon = view.requireViewById<ImageView>(R.id.icon)
+ val text = view.requireViewById<TextView>(R.id.text)
+ val newDot = view.requireViewById<ImageView>(R.id.new_dot)
+ val chevron = view.requireViewById<ImageView>(R.id.chevron_icon)
+
+ companion object {
+ fun createAndAdd(inflater: LayoutInflater, root: ViewGroup): TextButtonViewHolder {
+ val view =
+ inflater.inflate(
+ R.layout.footer_actions_text_button,
+ /* root= */ root,
+ /* attachToRoot= */ false,
+ )
+ root.addView(view)
+ return TextButtonViewHolder(view)
+ }
+ }
+}
+
+private class NumberButtonViewHolder(val view: View) {
+ val number = view.requireViewById<TextView>(R.id.number)
+ val newDot = view.requireViewById<ImageView>(R.id.new_dot)
+
+ companion object {
+ fun createAndAdd(inflater: LayoutInflater, root: ViewGroup): NumberButtonViewHolder {
+ val view =
+ inflater.inflate(
+ R.layout.footer_actions_number_button,
+ /* root= */ root,
+ /* attachToRoot= */ false,
+ )
+ root.addView(view)
+ return NumberButtonViewHolder(view)
+ }
+ }
+}
+
+private class IconButtonViewHolder(val view: View) {
+ val icon = view.requireViewById<ImageView>(R.id.icon)
+
+ companion object {
+ fun createAndAdd(
+ inflater: LayoutInflater,
+ root: ViewGroup,
+ isLast: Boolean,
+ ): IconButtonViewHolder {
+ val view =
+ inflater.inflate(
+ R.layout.footer_actions_icon_button,
+ /* root= */ root,
+ /* attachToRoot= */ false,
+ )
+
+ // All buttons have a background with an inset of qs_footer_action_inset, so the last
+ // button must have a negative inset of -qs_footer_action_inset to compensate and be
+ // aligned with its parent.
+ val marginEnd =
+ if (isLast) {
+ -view.context.resources.getDimensionPixelSize(R.dimen.qs_footer_action_inset)
+ } else {
+ 0
+ }
+
+ val size =
+ view.context.resources.getDimensionPixelSize(R.dimen.qs_footer_action_button_size)
+ root.addView(
+ view,
+ LinearLayout.LayoutParams(size, size).apply { this.marginEnd = marginEnd },
+ )
+ return IconButtonViewHolder(view)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsButtonViewModel.kt
new file mode 100644
index 0000000..4c0879e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsButtonViewModel.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.footer.ui.viewmodel
+
+import android.annotation.DrawableRes
+import android.view.View
+import com.android.systemui.common.shared.model.ContentDescription
+import com.android.systemui.common.shared.model.Icon
+
+/**
+ * A ViewModel for a simple footer actions button. This is used for the user switcher, settings and
+ * power buttons.
+ */
+data class FooterActionsButtonViewModel(
+ val icon: Icon,
+ val iconTint: Int?,
+ @DrawableRes val background: Int,
+ val contentDescription: ContentDescription,
+ // TODO(b/230830644): Replace View by an Expandable interface that can expand in either dialog
+ // or activity.
+ val onClick: (View) -> Unit,
+)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsForegroundServicesButtonViewModel.kt
similarity index 61%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
copy to packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsForegroundServicesButtonViewModel.kt
index e62a63a..98b53cb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsForegroundServicesButtonViewModel.kt
@@ -14,18 +14,15 @@
* limitations under the License.
*/
-package com.android.wm.shell.desktopmode;
+package com.android.systemui.qs.footer.ui.viewmodel
-import android.os.SystemProperties;
+import android.view.View
-/**
- * Constants for desktop mode feature
- */
-public class DesktopModeConstants {
-
- /**
- * Flag to indicate whether desktop mode is available on the device
- */
- public static final boolean IS_FEATURE_ENABLED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode", false);
-}
+/** A ViewModel for the foreground services button. */
+data class FooterActionsForegroundServicesButtonViewModel(
+ val foregroundServicesCount: Int,
+ val text: String,
+ val displayText: Boolean,
+ val hasNewChanges: Boolean,
+ val onClick: (View) -> Unit,
+)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsSecurityButtonViewModel.kt
similarity index 61%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
copy to packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsSecurityButtonViewModel.kt
index e62a63a..98ab129 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsSecurityButtonViewModel.kt
@@ -14,18 +14,14 @@
* limitations under the License.
*/
-package com.android.wm.shell.desktopmode;
+package com.android.systemui.qs.footer.ui.viewmodel
-import android.os.SystemProperties;
+import android.view.View
+import com.android.systemui.common.shared.model.Icon
-/**
- * Constants for desktop mode feature
- */
-public class DesktopModeConstants {
-
- /**
- * Flag to indicate whether desktop mode is available on the device
- */
- public static final boolean IS_FEATURE_ENABLED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode", false);
-}
+/** A ViewModel for the security button. */
+data class FooterActionsSecurityButtonViewModel(
+ val icon: Icon,
+ val text: String,
+ val onClick: ((View) -> Unit)?,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
new file mode 100644
index 0000000..b556a3e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.footer.ui.viewmodel
+
+import android.content.Context
+import android.util.Log
+import android.view.View
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import com.android.settingslib.Utils
+import com.android.settingslib.drawable.UserIconDrawable
+import com.android.systemui.R
+import com.android.systemui.animation.Expandable
+import com.android.systemui.common.shared.model.ContentDescription
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED
+import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel
+import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
+import com.android.systemui.util.icuMessageFormat
+import javax.inject.Inject
+import javax.inject.Named
+import javax.inject.Provider
+import kotlin.math.max
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+
+/** A ViewModel for the footer actions. */
+class FooterActionsViewModel(
+ @Application private val context: Context,
+ private val footerActionsInteractor: FooterActionsInteractor,
+ private val falsingManager: FalsingManager,
+ private val globalActionsDialogLite: GlobalActionsDialogLite,
+ showPowerButton: Boolean,
+) {
+ /**
+ * Whether the UI rendering this ViewModel should be visible. Note that even when this is false,
+ * the UI should still participate to the layout it is included in (i.e. in the View world it
+ * should be INVISIBLE, not GONE).
+ */
+ private val _isVisible = MutableStateFlow(true)
+ val isVisible: StateFlow<Boolean> = _isVisible.asStateFlow()
+
+ /** The alpha the UI rendering this ViewModel should have. */
+ private val _alpha = MutableStateFlow(1f)
+ val alpha: StateFlow<Float> = _alpha.asStateFlow()
+
+ /** The alpha the background of the UI rendering this ViewModel should have. */
+ private val _backgroundAlpha = MutableStateFlow(1f)
+ val backgroundAlpha: StateFlow<Float> = _backgroundAlpha.asStateFlow()
+
+ /** The model for the security button. */
+ val security: Flow<FooterActionsSecurityButtonViewModel?> =
+ footerActionsInteractor.securityButtonConfig
+ .map { config ->
+ val (icon, text, isClickable) = config ?: return@map null
+ FooterActionsSecurityButtonViewModel(
+ icon,
+ text,
+ if (isClickable) this::onSecurityButtonClicked else null,
+ )
+ }
+ .distinctUntilChanged()
+
+ /** The model for the foreground services button. */
+ val foregroundServices: Flow<FooterActionsForegroundServicesButtonViewModel?> =
+ combine(
+ footerActionsInteractor.foregroundServicesCount,
+ footerActionsInteractor.hasNewForegroundServices,
+ security,
+ ) { foregroundServicesCount, hasNewChanges, securityModel ->
+ if (foregroundServicesCount <= 0) {
+ return@combine null
+ }
+
+ val text =
+ icuMessageFormat(
+ context.resources,
+ R.string.fgs_manager_footer_label,
+ foregroundServicesCount,
+ )
+ FooterActionsForegroundServicesButtonViewModel(
+ foregroundServicesCount,
+ text = text,
+ displayText = securityModel == null,
+ hasNewChanges = hasNewChanges,
+ this::onForegroundServiceButtonClicked,
+ )
+ }
+ .distinctUntilChanged()
+
+ /** The model for the user switcher button. */
+ val userSwitcher: Flow<FooterActionsButtonViewModel?> =
+ footerActionsInteractor.userSwitcherStatus
+ .map { userSwitcherStatus ->
+ when (userSwitcherStatus) {
+ UserSwitcherStatusModel.Disabled -> null
+ is UserSwitcherStatusModel.Enabled -> {
+ if (userSwitcherStatus.currentUserImage == null) {
+ Log.e(
+ TAG,
+ "Skipped the addition of user switcher button because " +
+ "currentUserImage is missing",
+ )
+ return@map null
+ }
+
+ userSwitcherButton(userSwitcherStatus)
+ }
+ }
+ }
+ .distinctUntilChanged()
+
+ /** The model for the settings button. */
+ val settings: FooterActionsButtonViewModel =
+ FooterActionsButtonViewModel(
+ Icon.Resource(R.drawable.ic_settings),
+ iconTint = null,
+ R.drawable.qs_footer_action_circle,
+ ContentDescription.Resource(R.string.accessibility_quick_settings_settings),
+ this::onSettingsButtonClicked,
+ )
+
+ /** The model for the power button. */
+ val power: FooterActionsButtonViewModel? =
+ if (showPowerButton) {
+ FooterActionsButtonViewModel(
+ Icon.Resource(android.R.drawable.ic_lock_power_off),
+ iconTint =
+ Utils.getColorAttrDefaultColor(
+ context,
+ com.android.internal.R.attr.textColorOnAccent,
+ ),
+ R.drawable.qs_footer_action_circle_color,
+ ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu),
+ this::onPowerButtonClicked,
+ )
+ } else {
+ null
+ }
+
+ /** Called when the visibility of the UI rendering this model should be changed. */
+ fun onVisibilityChangeRequested(visible: Boolean) {
+ _isVisible.value = visible
+ }
+
+ /** Called when the expansion of the Quick Settings changed. */
+ fun onQuickSettingsExpansionChanged(expansion: Float, isInSplitShade: Boolean) {
+ if (isInSplitShade) {
+ // In split shade, we want to fade in the background only at the very end (see
+ // b/240563302).
+ val delay = 0.99f
+ _alpha.value = expansion
+ _backgroundAlpha.value = max(0f, expansion - delay) / (1f - delay)
+ } else {
+ // Only start fading in the footer actions when we are at least 90% expanded.
+ val delay = 0.9f
+ _alpha.value = max(0f, expansion - delay) / (1 - delay)
+ _backgroundAlpha.value = 1f
+ }
+ }
+
+ /**
+ * Observe the device monitoring dialog requests and show the dialog accordingly. This function
+ * will suspend indefinitely and will need to be cancelled to stop observing.
+ *
+ * Important: [quickSettingsContext] must be the [Context] associated to the [Quick Settings
+ * fragment][com.android.systemui.qs.QSFragment], and the call to this function must be
+ * cancelled when that fragment is destroyed.
+ */
+ suspend fun observeDeviceMonitoringDialogRequests(quickSettingsContext: Context) {
+ footerActionsInteractor.deviceMonitoringDialogRequests.collect {
+ footerActionsInteractor.showDeviceMonitoringDialog(quickSettingsContext)
+ }
+ }
+
+ private fun onSecurityButtonClicked(view: View) {
+ if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ return
+ }
+
+ footerActionsInteractor.showDeviceMonitoringDialog(view)
+ }
+
+ private fun onForegroundServiceButtonClicked(view: View) {
+ if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ return
+ }
+
+ footerActionsInteractor.showForegroundServicesDialog(view)
+ }
+
+ private fun onUserSwitcherClicked(view: View) {
+ if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ return
+ }
+
+ footerActionsInteractor.showUserSwitcher(view)
+ }
+
+ // TODO(b/230830644): Replace View by an Expandable interface that can expand in either dialog
+ // or activity.
+ private fun onSettingsButtonClicked(view: View) {
+ if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ return
+ }
+
+ footerActionsInteractor.showSettings(Expandable.fromView(view))
+ }
+
+ private fun onPowerButtonClicked(view: View) {
+ if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ return
+ }
+
+ footerActionsInteractor.showPowerMenuDialog(globalActionsDialogLite, view)
+ }
+
+ private fun userSwitcherButton(
+ status: UserSwitcherStatusModel.Enabled
+ ): FooterActionsButtonViewModel {
+ val icon = status.currentUserImage!!
+ val iconTint =
+ if (status.isGuestUser && icon !is UserIconDrawable) {
+ Utils.getColorAttrDefaultColor(context, android.R.attr.colorForeground)
+ } else {
+ null
+ }
+
+ return FooterActionsButtonViewModel(
+ Icon.Loaded(icon),
+ iconTint,
+ R.drawable.qs_footer_action_circle,
+ ContentDescription.Loaded(userSwitcherContentDescription(status.currentUserName)),
+ this::onUserSwitcherClicked,
+ )
+ }
+
+ private fun userSwitcherContentDescription(currentUser: String?): String? {
+ return currentUser?.let { user ->
+ context.getString(R.string.accessibility_quick_settings_user, user)
+ }
+ }
+
+ @SysUISingleton
+ class Factory
+ @Inject
+ constructor(
+ @Application private val context: Context,
+ private val falsingManager: FalsingManager,
+ private val footerActionsInteractor: FooterActionsInteractor,
+ private val globalActionsDialogLiteProvider: Provider<GlobalActionsDialogLite>,
+ @Named(PM_LITE_ENABLED) private val showPowerButton: Boolean,
+ ) {
+ /** Create a [FooterActionsViewModel] bound to the lifecycle of [lifecycleOwner]. */
+ fun create(lifecycleOwner: LifecycleOwner): FooterActionsViewModel {
+ val globalActionsDialogLite = globalActionsDialogLiteProvider.get()
+ if (lifecycleOwner.lifecycle.currentState == Lifecycle.State.DESTROYED) {
+ // This should usually not happen, but let's make sure we already destroy
+ // globalActionsDialogLite.
+ globalActionsDialogLite.destroy()
+ } else {
+ // Destroy globalActionsDialogLite when the lifecycle is destroyed.
+ lifecycleOwner.lifecycle.addObserver(
+ object : DefaultLifecycleObserver {
+ override fun onDestroy(owner: LifecycleOwner) {
+ globalActionsDialogLite.destroy()
+ }
+ }
+ )
+ }
+
+ return FooterActionsViewModel(
+ context,
+ footerActionsInteractor,
+ falsingManager,
+ globalActionsDialogLite,
+ showPowerButton,
+ )
+ }
+ }
+
+ companion object {
+ private const val TAG = "FooterActionsViewModel"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
index 948fb14..6038006 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
@@ -129,6 +129,15 @@
})
}
+ fun logInternetTileUpdate(lastType: Int, callback: String) {
+ log(VERBOSE, {
+ int1 = lastType
+ str1 = callback
+ }, {
+ "mLastTileState=$int1, Callback=$str1."
+ })
+ }
+
fun logTileUpdated(tileSpec: String, state: QSTile.State) {
log(VERBOSE, {
str1 = tileSpec
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 5147d59..2731d64 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -44,6 +44,7 @@
import com.android.systemui.FontSizeUtils
import com.android.systemui.R
import com.android.systemui.animation.LaunchableView
+import com.android.systemui.animation.LaunchableViewDelegate
import com.android.systemui.plugins.qs.QSIconView
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.qs.QSTile.BooleanState
@@ -138,8 +139,11 @@
private var lastStateDescription: CharSequence? = null
private var tileState = false
private var lastState = INVALID
- private var blockVisibilityChanges = false
- private var lastVisibility = View.VISIBLE
+ private val launchableViewDelegate = LaunchableViewDelegate(
+ this,
+ superSetVisibility = { super.setVisibility(it) },
+ superSetTransitionVisibility = { super.setTransitionVisibility(it) },
+ )
private val locInScreen = IntArray(2)
@@ -343,33 +347,15 @@
}
override fun setShouldBlockVisibilityChanges(block: Boolean) {
- blockVisibilityChanges = block
-
- if (block) {
- lastVisibility = visibility
- } else {
- visibility = lastVisibility
- }
+ launchableViewDelegate.setShouldBlockVisibilityChanges(block)
}
override fun setVisibility(visibility: Int) {
- if (blockVisibilityChanges) {
- lastVisibility = visibility
- return
- }
-
- super.setVisibility(visibility)
+ launchableViewDelegate.setVisibility(visibility)
}
override fun setTransitionVisibility(visibility: Int) {
- if (blockVisibilityChanges) {
- // View.setTransitionVisibility just sets the visibility flag, so we don't have to save
- // the transition visibility separately from the normal visibility.
- lastVisibility = visibility
- return
- }
-
- super.setTransitionVisibility(visibility)
+ launchableViewDelegate.setTransitionVisibility(visibility)
}
// Accessibility
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index e040ad0..d304024 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -365,6 +365,9 @@
mWifiInfo.mNoDefaultNetwork = noDefaultNetwork;
mWifiInfo.mNoValidatedNetwork = noValidatedNetwork;
mWifiInfo.mNoNetworksAvailable = noNetworksAvailable;
+ if (!noDefaultNetwork) {
+ return;
+ }
refreshState(mWifiInfo);
}
@@ -380,6 +383,7 @@
@Override
protected void handleUpdateState(SignalState state, Object arg) {
+ mQSLogger.logInternetTileUpdate(mLastTileState, arg == null ? "null" : arg.toString());
if (arg instanceof CellularCallbackInfo) {
mLastTileState = 0;
handleUpdateCellularState(state, arg);
@@ -597,4 +601,9 @@
pw.print(" "); pw.println("mLastTileState=" + mLastTileState);
pw.print(" "); pw.println("mSignalCallback=" + mSignalCallback.toString());
}
+
+ // For testing usage only.
+ protected int getLastTileState() {
+ return mLastTileState;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index ce6aaae..0ec4eef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -43,6 +43,7 @@
import com.android.systemui.qs.user.UserSwitchDialogController;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.user.data.source.UserRecord;
import javax.inject.Inject;
@@ -95,7 +96,7 @@
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- UserSwitcherController.UserRecord item = getItem(position);
+ UserRecord item = getItem(position);
return createUserDetailItemView(convertView, parent, item);
}
@@ -113,7 +114,7 @@
}
public UserDetailItemView createUserDetailItemView(View convertView, ViewGroup parent,
- UserSwitcherController.UserRecord item) {
+ UserRecord item) {
UserDetailItemView v = UserDetailItemView.convertOrInflate(
parent.getContext(), convertView, parent);
if (!item.isCurrent || item.isGuest) {
@@ -134,7 +135,7 @@
v.bind(name, drawable, item.info.id);
}
v.setActivated(item.isCurrent);
- v.setDisabledByAdmin(item.isDisabledByAdmin);
+ v.setDisabledByAdmin(mController.isDisabledByAdmin(item));
v.setEnabled(item.isSwitchToEnabled);
v.setAlpha(v.isEnabled() ? USER_SWITCH_ENABLED_ALPHA : USER_SWITCH_DISABLED_ALPHA);
@@ -146,7 +147,7 @@
}
private static Drawable getDrawable(Context context,
- UserSwitcherController.UserRecord item) {
+ UserRecord item) {
Drawable icon = getIconDrawable(context, item);
int iconColorRes;
if (item.isCurrent) {
@@ -171,22 +172,24 @@
}
Trace.beginSection("UserDetailView.Adapter#onClick");
- UserSwitcherController.UserRecord tag =
- (UserSwitcherController.UserRecord) view.getTag();
- if (tag.isDisabledByAdmin) {
+ UserRecord userRecord =
+ (UserRecord) view.getTag();
+ if (mController.isDisabledByAdmin(userRecord)) {
final Intent intent = RestrictedLockUtils.getShowAdminSupportDetailsIntent(
- mContext, tag.enforcedAdmin);
+ mContext, mController.getEnforcedAdmin(userRecord));
mController.startActivity(intent);
- } else if (tag.isSwitchToEnabled) {
+ } else if (userRecord.isSwitchToEnabled) {
MetricsLogger.action(mContext, MetricsEvent.QS_SWITCH_USER);
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_SWITCH);
- if (!tag.isAddUser && !tag.isRestricted && !tag.isDisabledByAdmin) {
+ if (!userRecord.isAddUser
+ && !userRecord.isRestricted
+ && !mController.isDisabledByAdmin(userRecord)) {
if (mCurrentUserView != null) {
mCurrentUserView.setActivated(false);
}
view.setActivated(true);
}
- onUserListItemClicked(tag, mDialogShower);
+ onUserListItemClicked(userRecord, mDialogShower);
}
Trace.endSection();
}
diff --git a/packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt b/packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
index db7c1fd..d2f3a6a 100644
--- a/packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
+++ b/packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
@@ -68,7 +68,7 @@
float rippleInsideAlpha = (1.-inside) * in_fadeFill;
float rippleRingAlpha = (1.-sparkleRing) * in_fadeRing;
float rippleAlpha = max(rippleInsideAlpha, rippleRingAlpha) * in_color.a;
- vec4 ripple = in_color * rippleAlpha;
+ vec4 ripple = vec4(in_color.rgb, 1.0) * rippleAlpha;
return mix(ripple, vec4(sparkle), sparkle * in_sparkle_strength);
}
"""
@@ -84,7 +84,7 @@
float rippleInsideAlpha = (1.-inside) * in_fadeFill;
float rippleRingAlpha = (1.-sparkleRing) * in_fadeRing;
float rippleAlpha = max(rippleInsideAlpha, rippleRingAlpha) * in_color.a;
- vec4 ripple = in_color * rippleAlpha;
+ vec4 ripple = vec4(in_color.rgb, 1.0) * rippleAlpha;
return mix(ripple, vec4(sparkle), sparkle * in_sparkle_strength);
}
"""
@@ -100,7 +100,7 @@
float rippleInsideAlpha = (1.-inside) * in_fadeFill;
float rippleRingAlpha = (1.-sparkleRing) * in_fadeRing;
float rippleAlpha = max(rippleInsideAlpha, rippleRingAlpha) * in_color.a;
- vec4 ripple = in_color * rippleAlpha;
+ vec4 ripple = vec4(in_color.rgb, 1.0) * rippleAlpha;
return mix(ripple, vec4(sparkle), sparkle * in_sparkle_strength);
}
"""
diff --git a/packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt b/packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
index 60c8f37..1e51ffa 100644
--- a/packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
@@ -25,10 +25,12 @@
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
+import androidx.core.graphics.ColorUtils
import com.android.systemui.ripple.RippleShader.RippleShape
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
private const val RIPPLE_DEFAULT_COLOR: Int = 0xffffffff.toInt()
+const val RIPPLE_DEFAULT_ALPHA: Int = 45
/**
* A generic expanding ripple effect.
@@ -111,9 +113,12 @@
rippleInProgress = true
}
- /** Set the color to be used for the ripple. */
- fun setColor(color: Int) {
- rippleShader.color = color
+ /** Set the color to be used for the ripple.
+ *
+ * The alpha value of the color will be applied to the ripple. The alpha range is [0-100].
+ */
+ fun setColor(color: Int, alpha: Int = RIPPLE_DEFAULT_ALPHA) {
+ rippleShader.color = ColorUtils.setAlphaComponent(color, alpha)
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
index a918e5d..309059f 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
@@ -17,6 +17,7 @@
package com.android.systemui.screenshot
import android.graphics.Insets
+import android.util.Log
import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
import com.android.internal.util.ScreenshotHelper.HardwareBitmapBundler
import com.android.internal.util.ScreenshotHelper.ScreenshotRequest
@@ -61,8 +62,9 @@
) {
val info = policy.findPrimaryContent(policy.getDefaultDisplayId())
+ Log.d(TAG, "findPrimaryContent: $info")
- result = if (policy.isManagedProfile(info.userId)) {
+ result = if (policy.isManagedProfile(info.user.identifier)) {
val image = capture.captureTask(info.taskId)
?: error("Task snapshot returned a null Bitmap!")
@@ -70,7 +72,7 @@
ScreenshotRequest(
TAKE_SCREENSHOT_PROVIDED_IMAGE, request.source,
HardwareBitmapBundler.hardwareBitmapToBundle(image),
- info.bounds, Insets.NONE, info.taskId, info.userId, info.component
+ info.bounds, Insets.NONE, info.taskId, info.user.identifier, info.component
)
} else {
// Create a new request of the same type which includes the top component
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
index 3580010..f73d204 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
@@ -19,6 +19,7 @@
import android.annotation.UserIdInt
import android.content.ComponentName
import android.graphics.Rect
+import android.os.UserHandle
import android.view.Display
/**
@@ -42,7 +43,7 @@
data class DisplayContentInfo(
val component: ComponentName,
val bounds: Rect,
- @UserIdInt val userId: Int,
+ val user: UserHandle,
val taskId: Int,
)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt
index ba809f6..c2a5060 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt
@@ -29,9 +29,11 @@
import android.graphics.Rect
import android.os.Process
import android.os.RemoteException
+import android.os.UserHandle
import android.os.UserManager
import android.util.Log
import android.view.Display.DEFAULT_DISPLAY
+import com.android.internal.annotations.VisibleForTesting
import com.android.internal.infra.ServiceConnector
import com.android.systemui.SystemUIService
import com.android.systemui.dagger.SysUISingleton
@@ -45,21 +47,13 @@
import kotlinx.coroutines.withContext
@SysUISingleton
-internal class ScreenshotPolicyImpl @Inject constructor(
+internal open class ScreenshotPolicyImpl @Inject constructor(
context: Context,
private val userMgr: UserManager,
private val atmService: IActivityTaskManager,
@Background val bgDispatcher: CoroutineDispatcher,
) : ScreenshotPolicy {
- private val systemUiContent =
- DisplayContentInfo(
- ComponentName(context, SystemUIService::class.java),
- Rect(),
- ActivityTaskManager.INVALID_TASK_ID,
- Process.myUserHandle().identifier,
- )
-
private val proxyConnector: ServiceConnector<IScreenshotProxy> =
ServiceConnector.Impl(
context,
@@ -78,6 +72,9 @@
}
private fun nonPipVisibleTask(info: RootTaskInfo): Boolean {
+ if (DEBUG) {
+ debugLogRootTaskInfo(info)
+ }
return info.windowingMode != WindowConfiguration.WINDOWING_MODE_PINNED &&
info.isVisible &&
info.isRunning &&
@@ -99,58 +96,46 @@
}
val taskInfoList = getAllRootTaskInfosOnDisplay(displayId)
- if (DEBUG) {
- debugLogRootTaskInfos(taskInfoList)
- }
// If no visible task is located, then report SystemUI as the foreground content
val target = taskInfoList.firstOrNull(::nonPipVisibleTask) ?: return systemUiContent
-
- val topActivity: ComponentName = target.topActivity ?: error("should not be null")
- val topChildTask = target.childTaskIds.size - 1
- val childTaskId = target.childTaskIds[topChildTask]
- val childTaskUserId = target.childTaskUserIds[topChildTask]
- val childTaskBounds = target.childTaskBounds[topChildTask]
-
- return DisplayContentInfo(topActivity, childTaskBounds, childTaskId, childTaskUserId)
+ return target.toDisplayContentInfo()
}
- private fun debugLogRootTaskInfos(taskInfoList: List<RootTaskInfo>) {
- for (info in taskInfoList) {
- Log.d(
- TAG,
- "[root task info] " +
- "taskId=${info.taskId} " +
- "parentTaskId=${info.parentTaskId} " +
- "position=${info.position} " +
- "positionInParent=${info.positionInParent} " +
- "isVisible=${info.isVisible()} " +
- "visible=${info.visible} " +
- "isFocused=${info.isFocused} " +
- "isSleeping=${info.isSleeping} " +
- "isRunning=${info.isRunning} " +
- "windowMode=${windowingModeToString(info.windowingMode)} " +
- "activityType=${activityTypeToString(info.activityType)} " +
- "topActivity=${info.topActivity} " +
- "topActivityInfo=${info.topActivityInfo} " +
- "numActivities=${info.numActivities} " +
- "childTaskIds=${Arrays.toString(info.childTaskIds)} " +
- "childUserIds=${Arrays.toString(info.childTaskUserIds)} " +
- "childTaskBounds=${Arrays.toString(info.childTaskBounds)} " +
- "childTaskNames=${Arrays.toString(info.childTaskNames)}"
- )
+ private fun debugLogRootTaskInfo(info: RootTaskInfo) {
+ Log.d(TAG, "RootTaskInfo={" +
+ "taskId=${info.taskId} " +
+ "parentTaskId=${info.parentTaskId} " +
+ "position=${info.position} " +
+ "positionInParent=${info.positionInParent} " +
+ "isVisible=${info.isVisible()} " +
+ "visible=${info.visible} " +
+ "isFocused=${info.isFocused} " +
+ "isSleeping=${info.isSleeping} " +
+ "isRunning=${info.isRunning} " +
+ "windowMode=${windowingModeToString(info.windowingMode)} " +
+ "activityType=${activityTypeToString(info.activityType)} " +
+ "topActivity=${info.topActivity} " +
+ "topActivityInfo=${info.topActivityInfo} " +
+ "numActivities=${info.numActivities} " +
+ "childTaskIds=${Arrays.toString(info.childTaskIds)} " +
+ "childUserIds=${Arrays.toString(info.childTaskUserIds)} " +
+ "childTaskBounds=${Arrays.toString(info.childTaskBounds)} " +
+ "childTaskNames=${Arrays.toString(info.childTaskNames)}" +
+ "}"
+ )
- for (j in 0 until info.childTaskIds.size) {
- Log.d(TAG, " *** [$j] ******")
- Log.d(TAG, " *** childTaskIds[$j]: ${info.childTaskIds[j]}")
- Log.d(TAG, " *** childTaskUserIds[$j]: ${info.childTaskUserIds[j]}")
- Log.d(TAG, " *** childTaskBounds[$j]: ${info.childTaskBounds[j]}")
- Log.d(TAG, " *** childTaskNames[$j]: ${info.childTaskNames[j]}")
- }
+ for (j in 0 until info.childTaskIds.size) {
+ Log.d(TAG, " *** [$j] ******")
+ Log.d(TAG, " *** childTaskIds[$j]: ${info.childTaskIds[j]}")
+ Log.d(TAG, " *** childTaskUserIds[$j]: ${info.childTaskUserIds[j]}")
+ Log.d(TAG, " *** childTaskBounds[$j]: ${info.childTaskBounds[j]}")
+ Log.d(TAG, " *** childTaskNames[$j]: ${info.childTaskNames[j]}")
}
}
- private suspend fun getAllRootTaskInfosOnDisplay(displayId: Int): List<RootTaskInfo> =
+ @VisibleForTesting
+ open suspend fun getAllRootTaskInfosOnDisplay(displayId: Int): List<RootTaskInfo> =
withContext(bgDispatcher) {
try {
atmService.getAllRootTaskInfosOnDisplay(displayId)
@@ -160,7 +145,8 @@
}
}
- private suspend fun isNotificationShadeExpanded(): Boolean = suspendCoroutine { k ->
+ @VisibleForTesting
+ open suspend fun isNotificationShadeExpanded(): Boolean = suspendCoroutine { k ->
proxyConnector
.postForResult { it.isNotificationShadeExpanded }
.whenComplete { expanded, error ->
@@ -171,8 +157,30 @@
}
}
- companion object {
- const val TAG: String = "ScreenshotPolicyImpl"
- const val DEBUG: Boolean = false
- }
+ @VisibleForTesting
+ internal val systemUiContent =
+ DisplayContentInfo(
+ ComponentName(context, SystemUIService::class.java),
+ Rect(),
+ Process.myUserHandle(),
+ ActivityTaskManager.INVALID_TASK_ID
+ )
+}
+
+private const val TAG: String = "ScreenshotPolicyImpl"
+private const val DEBUG: Boolean = false
+
+@VisibleForTesting
+internal fun RootTaskInfo.toDisplayContentInfo(): DisplayContentInfo {
+ val topActivity: ComponentName = topActivity ?: error("should not be null")
+ val topChildTask = childTaskIds.size - 1
+ val childTaskId = childTaskIds[topChildTask]
+ val childTaskUserId = childTaskUserIds[topChildTask]
+ val childTaskBounds = childTaskBounds[topChildTask]
+
+ return DisplayContentInfo(
+ topActivity,
+ childTaskBounds,
+ UserHandle.of(childTaskUserId),
+ childTaskId)
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 8b37aab..695a80b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -53,8 +53,7 @@
import android.view.WindowManager;
import android.widget.Toast;
-import androidx.annotation.NonNull;
-
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.ScreenshotHelper;
import com.android.systemui.R;
@@ -137,7 +136,7 @@
}
@Override
- public IBinder onBind(@NonNull Intent intent) {
+ public IBinder onBind(Intent intent) {
registerReceiver(mCloseSystemDialogs, new IntentFilter(ACTION_CLOSE_SYSTEM_DIALOGS),
Context.RECEIVER_EXPORTED);
final Messenger m = new Messenger(mHandler);
@@ -184,13 +183,23 @@
}
}
- /** Respond to incoming Message via Binder (Messenger) */
@MainThread
private boolean handleMessage(Message msg) {
final Messenger replyTo = msg.replyTo;
- final Consumer<Uri> uriConsumer = (uri) -> reportUri(replyTo, uri);
- RequestCallback requestCallback = new RequestCallbackImpl(replyTo);
+ final Consumer<Uri> onSaved = (uri) -> reportUri(replyTo, uri);
+ RequestCallback callback = new RequestCallbackImpl(replyTo);
+ ScreenshotHelper.ScreenshotRequest request =
+ (ScreenshotHelper.ScreenshotRequest) msg.obj;
+
+ handleRequest(request, onSaved, callback);
+ return true;
+ }
+
+ @MainThread
+ @VisibleForTesting
+ void handleRequest(ScreenshotHelper.ScreenshotRequest request, Consumer<Uri> onSaved,
+ RequestCallback callback) {
// If the storage for this user is locked, we have no place to store
// the screenshot, so skip taking it instead of showing a misleading
// animation and error notification.
@@ -198,8 +207,8 @@
Log.w(TAG, "Skipping screenshot because storage is locked!");
mNotificationsController.notifyScreenshotError(
R.string.screenshot_failed_to_save_user_locked_text);
- requestCallback.reportError();
- return true;
+ callback.reportError();
+ return;
}
if (mDevicePolicyManager.getScreenCaptureDisabled(null, UserHandle.USER_ALL)) {
@@ -211,33 +220,27 @@
() -> mContext.getString(R.string.screenshot_blocked_by_admin));
mHandler.post(() ->
Toast.makeText(mContext, blockedByAdminText, Toast.LENGTH_SHORT).show());
- requestCallback.reportError();
+ callback.reportError();
});
- return true;
+ return;
}
- ScreenshotHelper.ScreenshotRequest screenshotRequest =
- (ScreenshotHelper.ScreenshotRequest) msg.obj;
-
- ComponentName topComponent = screenshotRequest.getTopComponent();
- mUiEventLogger.log(ScreenshotEvent.getScreenshotSource(screenshotRequest.getSource()), 0,
- topComponent == null ? "" : topComponent.getPackageName());
-
if (mFeatureFlags.isEnabled(SCREENSHOT_REQUEST_PROCESSOR)) {
Log.d(TAG, "handleMessage: Using request processor");
- mProcessor.processAsync(screenshotRequest,
- (request) -> dispatchToController(request, uriConsumer, requestCallback));
- return true;
+ mProcessor.processAsync(request,
+ (r) -> dispatchToController(r, onSaved, callback));
+ return;
}
- dispatchToController(screenshotRequest, uriConsumer, requestCallback);
- return true;
+ dispatchToController(request, onSaved, callback);
}
private void dispatchToController(ScreenshotHelper.ScreenshotRequest request,
Consumer<Uri> uriConsumer, RequestCallback callback) {
ComponentName topComponent = request.getTopComponent();
+ mUiEventLogger.log(ScreenshotEvent.getScreenshotSource(request.getSource()), 0,
+ topComponent == null ? "" : topComponent.getPackageName());
switch (request.getType()) {
case WindowManager.TAKE_SCREENSHOT_FULLSCREEN:
diff --git a/packages/SystemUI/src/com/android/systemui/security/data/model/SecurityModel.kt b/packages/SystemUI/src/com/android/systemui/security/data/model/SecurityModel.kt
new file mode 100644
index 0000000..50af260
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/security/data/model/SecurityModel.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.security.data.model
+
+import android.graphics.drawable.Drawable
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.statusbar.policy.SecurityController
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.withContext
+
+/** The security info exposed by [com.android.systemui.statusbar.policy.SecurityController]. */
+// TODO(b/242040009): Consider splitting this model into smaller submodels.
+data class SecurityModel(
+ val isDeviceManaged: Boolean,
+ val hasWorkProfile: Boolean,
+ val isWorkProfileOn: Boolean,
+ val isProfileOwnerOfOrganizationOwnedDevice: Boolean,
+ val deviceOwnerOrganizationName: String?,
+ val workProfileOrganizationName: String?,
+ val isNetworkLoggingEnabled: Boolean,
+ val isVpnBranded: Boolean,
+ val primaryVpnName: String?,
+ val workProfileVpnName: String?,
+ val hasCACertInCurrentUser: Boolean,
+ val hasCACertInWorkProfile: Boolean,
+ val isParentalControlsEnabled: Boolean,
+ val deviceAdminIcon: Drawable?,
+) {
+ companion object {
+ /** Create a [SecurityModel] from the current [securityController] state. */
+ suspend fun create(
+ securityController: SecurityController,
+ @Background bgDispatcher: CoroutineDispatcher,
+ ): SecurityModel {
+ return withContext(bgDispatcher) { create(securityController) }
+ }
+
+ /**
+ * Create a [SecurityModel] from the current [securityController] state.
+ *
+ * Important: This method should be called from a background thread as this will do a lot of
+ * binder calls.
+ */
+ // TODO(b/242040009): Remove this.
+ @JvmStatic
+ fun create(securityController: SecurityController): SecurityModel {
+ val deviceAdminInfo =
+ if (securityController.isParentalControlsEnabled) {
+ securityController.deviceAdminInfo
+ } else {
+ null
+ }
+
+ return SecurityModel(
+ isDeviceManaged = securityController.isDeviceManaged,
+ hasWorkProfile = securityController.hasWorkProfile(),
+ isWorkProfileOn = securityController.isWorkProfileOn,
+ isProfileOwnerOfOrganizationOwnedDevice =
+ securityController.isProfileOwnerOfOrganizationOwnedDevice,
+ deviceOwnerOrganizationName =
+ securityController.deviceOwnerOrganizationName?.toString(),
+ workProfileOrganizationName =
+ securityController.workProfileOrganizationName?.toString(),
+ isNetworkLoggingEnabled = securityController.isNetworkLoggingEnabled,
+ isVpnBranded = securityController.isVpnBranded,
+ primaryVpnName = securityController.primaryVpnName,
+ workProfileVpnName = securityController.workProfileVpnName,
+ hasCACertInCurrentUser = securityController.hasCACertInCurrentUser(),
+ hasCACertInWorkProfile = securityController.hasCACertInWorkProfile(),
+ isParentalControlsEnabled = securityController.isParentalControlsEnabled,
+ deviceAdminIcon = securityController.getIcon(deviceAdminInfo),
+ )
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/security/data/repository/SecurityRepository.kt b/packages/SystemUI/src/com/android/systemui/security/data/repository/SecurityRepository.kt
new file mode 100644
index 0000000..8f4402e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/security/data/repository/SecurityRepository.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.security.data.repository
+
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.security.data.model.SecurityModel
+import com.android.systemui.statusbar.policy.SecurityController
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.launch
+
+interface SecurityRepository {
+ /** The current [SecurityModel]. */
+ val security: Flow<SecurityModel>
+}
+
+@SysUISingleton
+class SecurityRepositoryImpl
+@Inject
+constructor(
+ private val securityController: SecurityController,
+ @Background private val bgDispatcher: CoroutineDispatcher,
+) : SecurityRepository {
+ override val security: Flow<SecurityModel> = conflatedCallbackFlow {
+ suspend fun updateState() {
+ trySendWithFailureLogging(SecurityModel.create(securityController, bgDispatcher), TAG)
+ }
+
+ val callback = SecurityController.SecurityControllerCallback { launch { updateState() } }
+
+ securityController.addCallback(callback)
+ updateState()
+ awaitClose { securityController.removeCallback(callback) }
+ }
+
+ companion object {
+ private const val TAG = "SecurityRepositoryImpl"
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java b/packages/SystemUI/src/com/android/systemui/security/data/repository/SecurityRepositoryModule.kt
similarity index 61%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
copy to packages/SystemUI/src/com/android/systemui/security/data/repository/SecurityRepositoryModule.kt
index e62a63a..39a57ca 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/security/data/repository/SecurityRepositoryModule.kt
@@ -14,18 +14,13 @@
* limitations under the License.
*/
-package com.android.wm.shell.desktopmode;
+package com.android.systemui.security.data.repository
-import android.os.SystemProperties;
+import dagger.Binds
+import dagger.Module
-/**
- * Constants for desktop mode feature
- */
-public class DesktopModeConstants {
-
- /**
- * Flag to indicate whether desktop mode is available on the device
- */
- public static final boolean IS_FEATURE_ENABLED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode", false);
+/** Dagger module to provide/bind security repositories. */
+@Module
+interface SecurityRepositoryModule {
+ @Binds fun securityRepository(impl: SecurityRepositoryImpl): SecurityRepository
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
index fab70fc..6b32daf 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
@@ -270,6 +270,14 @@
qsCarrierGroupController = qsCarrierGroupControllerBuilder
.setQSCarrierGroup(qsCarrierGroup)
.build()
+
+ if (!combinedHeaders) {
+ // In the new header, we display alarm icon but we ignore it when not using the new
+ // headers.
+ iconContainer.addIgnoredSlot(
+ context.getString(com.android.internal.R.string.status_bar_alarm_clock)
+ )
+ }
}
override fun onViewAttached() {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java
index 9818af3..1cdacb9 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java
@@ -17,32 +17,30 @@
package com.android.systemui.shade;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.TapAgainView;
-public class NotificationPanelView extends PanelView {
+/** The shade view. */
+public final class NotificationPanelView extends FrameLayout {
+ static final boolean DEBUG = false;
- private static final boolean DEBUG = false;
-
- /**
- * Fling expanding QS.
- */
- public static final int FLING_EXPAND = 0;
-
- public static final String COUNTER_PANEL_OPEN = "panel_open";
- public static final String COUNTER_PANEL_OPEN_QS = "panel_open_qs";
+ private final Paint mAlphaPaint = new Paint();
private int mCurrentPanelAlpha;
- private final Paint mAlphaPaint = new Paint();
private boolean mDozing;
private RtlChangeListener mRtlChangeListener;
+ private NotificationPanelViewController.TouchHandler mTouchHandler;
+ private OnConfigurationChangedListener mOnConfigurationChangedListener;
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -99,7 +97,36 @@
return findViewById(R.id.shade_falsing_tap_again);
}
+ /** Sets the touch handler for this view. */
+ public void setOnTouchListener(NotificationPanelViewController.TouchHandler touchHandler) {
+ super.setOnTouchListener(touchHandler);
+ mTouchHandler = touchHandler;
+ }
+
+ void setOnConfigurationChangedListener(OnConfigurationChangedListener listener) {
+ mOnConfigurationChangedListener = listener;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ return mTouchHandler.onInterceptTouchEvent(event);
+ }
+
+ @Override
+ public void dispatchConfigurationChanged(Configuration newConfig) {
+ super.dispatchConfigurationChanged(newConfig);
+ mOnConfigurationChangedListener.onConfigurationChanged(newConfig);
+ }
+
+ /** Callback for right-to-left setting changes. */
interface RtlChangeListener {
+ /** Called when right-to-left setting changes. */
void onRtlPropertielsChanged(int layoutDirection);
}
+
+ /** Callback for config changes. */
+ interface OnConfigurationChangedListener {
+ /** Called when configuration changes. */
+ void onConfigurationChanged(Configuration newConfig);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index e6d10228..d5ba07a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -161,7 +161,6 @@
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.ConversationNotificationManager;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
@@ -247,7 +246,7 @@
/**
* Fling expanding QS.
*/
- private static final int FLING_EXPAND = 0;
+ public static final int FLING_EXPAND = 0;
/**
* Fling collapsing QS, potentially stopping when QS becomes QQS.
@@ -290,11 +289,6 @@
private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
private final NotificationIconAreaController mNotificationIconAreaController;
- // Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is
- // changed.
- private static final int CAP_HEIGHT = 1456;
- private static final int FONT_HEIGHT = 2163;
-
/**
* Maximum time before which we will expand the panel even for slow motions when getting a
* touch passed over from launcher.
@@ -371,12 +365,13 @@
private final ScreenOffAnimationController mScreenOffAnimationController;
private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
- private int mTrackingPointer;
+ private int mQsTrackingPointer;
private VelocityTracker mQsVelocityTracker;
private boolean mQsTracking;
/**
- * If set, the ongoing touch gesture might both trigger the expansion in {@link PanelView} and
+ * If set, the ongoing touch gesture might both trigger the expansion in {@link
+ * NotificationPanelView} and
* the expansion for quick settings.
*/
private boolean mConflictingQsExpansionGesture;
@@ -522,7 +517,6 @@
}
}).setCustomInterpolator(
mPanelAlphaAnimator.getProperty(), Interpolators.ALPHA_IN);
- private final NotificationEntryManager mEntryManager;
private final CommandQueue mCommandQueue;
private final UserManager mUserManager;
@@ -713,7 +707,6 @@
DynamicPrivacyController dynamicPrivacyController,
KeyguardBypassController bypassController, FalsingManager falsingManager,
FalsingCollector falsingCollector,
- NotificationEntryManager notificationEntryManager,
KeyguardStateController keyguardStateController,
StatusBarStateController statusBarStateController,
StatusBarWindowStateController statusBarWindowStateController,
@@ -871,7 +864,6 @@
});
mBottomAreaShadeAlphaAnimator.setDuration(160);
mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
- mEntryManager = notificationEntryManager;
mConversationNotificationManager = conversationNotificationManager;
mAuthController = authController;
mLockIconViewController = lockIconViewController;
@@ -1111,13 +1103,6 @@
}
}
- /**
- * Returns if there's a custom clock being presented.
- */
- public boolean hasCustomClock() {
- return mKeyguardStatusViewController.hasCustomClock();
- }
-
private void setCentralSurfaces(CentralSurfaces centralSurfaces) {
// TODO: this can be injected.
mCentralSurfaces = centralSurfaces;
@@ -1864,10 +1849,10 @@
private boolean onQsIntercept(MotionEvent event) {
if (DEBUG_LOGCAT) Log.d(TAG, "onQsIntercept");
- int pointerIndex = event.findPointerIndex(mTrackingPointer);
+ int pointerIndex = event.findPointerIndex(mQsTrackingPointer);
if (pointerIndex < 0) {
pointerIndex = 0;
- mTrackingPointer = event.getPointerId(pointerIndex);
+ mQsTrackingPointer = event.getPointerId(pointerIndex);
}
final float x = event.getX(pointerIndex);
final float y = event.getY(pointerIndex);
@@ -1896,10 +1881,10 @@
break;
case MotionEvent.ACTION_POINTER_UP:
final int upPointer = event.getPointerId(event.getActionIndex());
- if (mTrackingPointer == upPointer) {
+ if (mQsTrackingPointer == upPointer) {
// gesture is ongoing, find a new pointer to track
final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
- mTrackingPointer = event.getPointerId(newIndex);
+ mQsTrackingPointer = event.getPointerId(newIndex);
mInitialTouchX = event.getX(newIndex);
mInitialTouchY = event.getY(newIndex);
}
@@ -2273,10 +2258,10 @@
}
private void onQsTouch(MotionEvent event) {
- int pointerIndex = event.findPointerIndex(mTrackingPointer);
+ int pointerIndex = event.findPointerIndex(mQsTrackingPointer);
if (pointerIndex < 0) {
pointerIndex = 0;
- mTrackingPointer = event.getPointerId(pointerIndex);
+ mQsTrackingPointer = event.getPointerId(pointerIndex);
}
final float y = event.getY(pointerIndex);
final float x = event.getX(pointerIndex);
@@ -2297,12 +2282,12 @@
case MotionEvent.ACTION_POINTER_UP:
final int upPointer = event.getPointerId(event.getActionIndex());
- if (mTrackingPointer == upPointer) {
+ if (mQsTrackingPointer == upPointer) {
// gesture is ongoing, find a new pointer to track
final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
final float newY = event.getY(newIndex);
final float newX = event.getX(newIndex);
- mTrackingPointer = event.getPointerId(newIndex);
+ mQsTrackingPointer = event.getPointerId(newIndex);
mInitialHeightOnTouch = mQsExpansionHeight;
mInitialTouchY = newY;
mInitialTouchX = newX;
@@ -2324,7 +2309,7 @@
mShadeLog.logMotionEvent(event,
"onQsTouch: up/cancel action, QS tracking disabled");
mQsTracking = false;
- mTrackingPointer = -1;
+ mQsTrackingPointer = -1;
trackMovement(event);
float fraction = computeQsExpansionFraction();
if (fraction != 0f || y >= mInitialTouchY) {
@@ -2342,7 +2327,7 @@
}
}
- private int getFalsingThreshold() {
+ protected int getFalsingThreshold() {
float factor = mCentralSurfaces.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
return (int) (mQsFalsingThreshold * factor);
}
@@ -3973,9 +3958,9 @@
public void onAnimationEnd(Animator animation) {
endAction.run();
}
+ }).setUpdateListener(anim -> {
+ mKeyguardStatusViewController.animateFoldToAod(anim.getAnimatedFraction());
}).start();
-
- mKeyguardStatusViewController.animateFoldToAod();
}
/**
@@ -4145,8 +4130,8 @@
}
@Override
- public OnLayoutChangeListener createLayoutChangeListener() {
- return new OnLayoutChangeListener();
+ protected OnLayoutChangeListener createLayoutChangeListener() {
+ return new OnLayoutChangeListenerImpl();
}
@Override
@@ -4685,7 +4670,6 @@
public void onDozeAmountChanged(float linearAmount, float amount) {
mInterpolatedDarkAmount = amount;
mLinearDarkAmount = linearAmount;
- mKeyguardStatusViewController.setDarkAmount(mInterpolatedDarkAmount);
mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount);
positionClockAndNotifications();
}
@@ -4741,7 +4725,6 @@
public void showAodUi() {
setDozing(true /* dozing */, false /* animate */);
mStatusBarStateController.setUpcomingState(KEYGUARD);
- mEntryManager.updateNotifications("showAodUi");
mStatusBarStateListener.onStateChanged(KEYGUARD);
mStatusBarStateListener.onDozeAmountChanged(1f, 1f);
setExpandedFraction(1f);
@@ -4785,7 +4768,7 @@
}
}
- private class OnLayoutChangeListener extends PanelViewController.OnLayoutChangeListener {
+ private class OnLayoutChangeListenerImpl extends OnLayoutChangeListener {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
@@ -4795,11 +4778,8 @@
updateMaxDisplayedNotifications(!shouldAvoidChangingNotificationsCount());
setIsFullWidth(mNotificationStackScrollLayoutController.getWidth() == mView.getWidth());
- // Update Clock Pivot
- mKeyguardStatusViewController.setPivotX(((float) mView.getWidth()) / 2f);
- mKeyguardStatusViewController.setPivotY(
- (FONT_HEIGHT - CAP_HEIGHT) / 2048f
- * mKeyguardStatusViewController.getClockTextSize());
+ // Update Clock Pivot (used by anti-burnin transformations)
+ mKeyguardStatusViewController.updatePivot(mView.getWidth(), mView.getHeight());
// Calculate quick setting heights.
int oldMaxHeight = mQsMaxExpansionHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index b8546df..fec76b6 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -17,12 +17,9 @@
package com.android.systemui.shade;
import android.app.StatusBarManager;
-import android.hardware.display.AmbientDisplayConfiguration;
import android.media.AudioManager;
import android.media.session.MediaSessionLegacyHelper;
import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
import android.util.Log;
import android.view.GestureDetector;
import android.view.InputDevice;
@@ -52,7 +49,6 @@
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
-import com.android.systemui.tuner.TunerService;
import java.io.PrintWriter;
import java.util.Optional;
@@ -66,7 +62,6 @@
public class NotificationShadeWindowViewController {
private static final String TAG = "NotifShadeWindowVC";
private final FalsingCollector mFalsingCollector;
- private final TunerService mTunerService;
private final SysuiStatusBarStateController mStatusBarStateController;
private final NotificationShadeWindowView mView;
private final NotificationShadeDepthController mDepthController;
@@ -77,6 +72,7 @@
private final StatusBarWindowStateController mStatusBarWindowStateController;
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private final AmbientState mAmbientState;
+ private final PulsingGestureListener mPulsingGestureListener;
private GestureDetector mGestureDetector;
private View mBrightnessMirror;
@@ -88,8 +84,6 @@
private final CentralSurfaces mService;
private final NotificationShadeWindowController mNotificationShadeWindowController;
private DragDownHelper mDragDownHelper;
- private boolean mDoubleTapEnabled;
- private boolean mSingleTapEnabled;
private boolean mExpandingBelowNotch;
private final DockManager mDockManager;
private final NotificationPanelViewController mNotificationPanelViewController;
@@ -102,7 +96,6 @@
public NotificationShadeWindowViewController(
LockscreenShadeTransitionController transitionController,
FalsingCollector falsingCollector,
- TunerService tunerService,
SysuiStatusBarStateController statusBarStateController,
DockManager dockManager,
NotificationShadeDepthController depthController,
@@ -117,10 +110,11 @@
CentralSurfaces centralSurfaces,
NotificationShadeWindowController controller,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
- AmbientState ambientState) {
+ AmbientState ambientState,
+ PulsingGestureListener pulsingGestureListener
+ ) {
mLockscreenShadeTransitionController = transitionController;
mFalsingCollector = falsingCollector;
- mTunerService = tunerService;
mStatusBarStateController = statusBarStateController;
mView = notificationShadeWindowView;
mDockManager = dockManager;
@@ -136,6 +130,7 @@
mNotificationShadeWindowController = controller;
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
mAmbientState = ambientState;
+ mPulsingGestureListener = pulsingGestureListener;
// This view is not part of the newly inflated expanded status bar.
mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
@@ -151,46 +146,7 @@
/** Inflates the {@link R.layout#status_bar_expanded} layout and sets it up. */
public void setupExpandedStatusBar() {
mStackScrollLayout = mView.findViewById(R.id.notification_stack_scroller);
-
- TunerService.Tunable tunable = (key, newValue) -> {
- AmbientDisplayConfiguration configuration =
- new AmbientDisplayConfiguration(mView.getContext());
- switch (key) {
- case Settings.Secure.DOZE_DOUBLE_TAP_GESTURE:
- mDoubleTapEnabled = configuration.doubleTapGestureEnabled(
- UserHandle.USER_CURRENT);
- break;
- case Settings.Secure.DOZE_TAP_SCREEN_GESTURE:
- mSingleTapEnabled = configuration.tapGestureEnabled(UserHandle.USER_CURRENT);
- }
- };
- mTunerService.addTunable(tunable,
- Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
- Settings.Secure.DOZE_TAP_SCREEN_GESTURE);
-
- GestureDetector.SimpleOnGestureListener gestureListener =
- new GestureDetector.SimpleOnGestureListener() {
- @Override
- public boolean onSingleTapConfirmed(MotionEvent e) {
- if (mSingleTapEnabled && !mDockManager.isDocked()) {
- mService.wakeUpIfDozing(
- SystemClock.uptimeMillis(), mView, "SINGLE_TAP");
- return true;
- }
- return false;
- }
-
- @Override
- public boolean onDoubleTap(MotionEvent e) {
- if (mDoubleTapEnabled || mSingleTapEnabled) {
- mService.wakeUpIfDozing(
- SystemClock.uptimeMillis(), mView, "DOUBLE_TAP");
- return true;
- }
- return false;
- }
- };
- mGestureDetector = new GestureDetector(mView.getContext(), gestureListener);
+ mGestureDetector = new GestureDetector(mView.getContext(), mPulsingGestureListener);
mLowLightClockController.ifPresent(controller -> controller.attachLowLightClockView(mView));
diff --git a/packages/SystemUI/src/com/android/systemui/shade/PanelView.java b/packages/SystemUI/src/com/android/systemui/shade/PanelView.java
deleted file mode 100644
index efff0db..0000000
--- a/packages/SystemUI/src/com/android/systemui/shade/PanelView.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.shade;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.widget.FrameLayout;
-
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
-
-public abstract class PanelView extends FrameLayout {
- public static final boolean DEBUG = false;
- public static final String TAG = PanelView.class.getSimpleName();
- private PanelViewController.TouchHandler mTouchHandler;
-
- protected CentralSurfaces mCentralSurfaces;
- protected HeadsUpManagerPhone mHeadsUpManager;
-
- protected KeyguardBottomAreaView mKeyguardBottomArea;
- private OnConfigurationChangedListener mOnConfigurationChangedListener;
-
- public PanelView(Context context) {
- super(context);
- }
-
- public PanelView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public PanelView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public void setOnTouchListener(PanelViewController.TouchHandler touchHandler) {
- super.setOnTouchListener(touchHandler);
- mTouchHandler = touchHandler;
- }
-
- public void setOnConfigurationChangedListener(OnConfigurationChangedListener listener) {
- mOnConfigurationChangedListener = listener;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent event) {
- return mTouchHandler.onInterceptTouchEvent(event);
- }
-
- @Override
- public void dispatchConfigurationChanged(Configuration newConfig) {
- super.dispatchConfigurationChanged(newConfig);
- mOnConfigurationChangedListener.onConfigurationChanged(newConfig);
- }
-
- interface OnConfigurationChangedListener {
- void onConfigurationChanged(Configuration newConfig);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/PanelViewController.java
index 73eaa85..a0076937 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/PanelViewController.java
@@ -23,7 +23,7 @@
import static com.android.systemui.classifier.Classifier.GENERIC;
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
import static com.android.systemui.classifier.Classifier.UNLOCK;
-import static com.android.systemui.shade.PanelView.DEBUG;
+import static com.android.systemui.shade.NotificationPanelView.DEBUG;
import static java.lang.Float.isNaN;
@@ -76,7 +76,7 @@
import java.util.List;
public abstract class PanelViewController {
- public static final String TAG = PanelView.class.getSimpleName();
+ public static final String TAG = NotificationPanelView.class.getSimpleName();
public static final float FLING_MAX_LENGTH_SECONDS = 0.6f;
public static final float FLING_SPEED_UP_FACTOR = 0.6f;
public static final float FLING_CLOSING_MAX_LENGTH_SECONDS = 0.6f;
@@ -143,7 +143,6 @@
private float mSlopMultiplier;
protected boolean mHintAnimationRunning;
private boolean mTouchAboveFalsingThreshold;
- private int mUnlockFalsingThreshold;
private boolean mTouchStartedInEmptyArea;
private boolean mMotionAborted;
private boolean mUpwardsWhenThresholdReached;
@@ -168,13 +167,13 @@
private boolean mIsFlinging;
private String mViewName;
- private float mInitialTouchY;
- private float mInitialTouchX;
+ private float mInitialExpandY;
+ private float mInitialExpandX;
private boolean mTouchDisabled;
private boolean mInitialTouchFromKeyguard;
/**
- * Whether or not the PanelView can be expanded or collapsed with a drag.
+ * Whether or not the NotificationPanelView can be expanded or collapsed with a drag.
*/
private final boolean mNotificationsDragEnabled;
@@ -190,7 +189,7 @@
private boolean mGestureWaitForTouchSlop;
private boolean mIgnoreXTouchSlop;
private boolean mExpandLatencyTracking;
- private final PanelView mView;
+ private final NotificationPanelView mView;
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private final NotificationShadeWindowController mNotificationShadeWindowController;
protected final Resources mResources;
@@ -229,7 +228,7 @@
}
public PanelViewController(
- PanelView view,
+ NotificationPanelView view,
FalsingManager falsingManager,
DozeLog dozeLog,
KeyguardStateController keyguardStateController,
@@ -314,8 +313,6 @@
mSlopMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
mHintDistance = mResources.getDimension(R.dimen.hint_move_distance);
mPanelFlingOvershootAmount = mResources.getDimension(R.dimen.panel_overshoot_amount);
- mUnlockFalsingThreshold =
- mResources.getDimensionPixelSize(R.dimen.unlock_falsing_threshold);
mInSplitShade = mResources.getBoolean(R.bool.config_use_split_notification_shade);
}
@@ -384,8 +381,8 @@
* horizontal direction
*/
private boolean isDirectionUpwards(float x, float y) {
- float xDiff = x - mInitialTouchX;
- float yDiff = y - mInitialTouchY;
+ float xDiff = x - mInitialExpandX;
+ float yDiff = y - mInitialExpandY;
if (yDiff >= 0) {
return false;
}
@@ -398,9 +395,9 @@
beginJankMonitoring();
}
mInitialOffsetOnTouch = expandedHeight;
- mInitialTouchY = newY;
- mInitialTouchX = newX;
- mInitialTouchFromKeyguard = mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
+ mInitialExpandY = newY;
+ mInitialExpandX = newX;
+ mInitialTouchFromKeyguard = mKeyguardStateController.isShowing();
if (startTracking) {
mTouchSlopExceeded = true;
setExpandedHeight(mInitialOffsetOnTouch);
@@ -411,17 +408,15 @@
private void endMotionEvent(MotionEvent event, float x, float y, boolean forceCancel) {
mTrackingPointer = -1;
mAmbientState.setSwipingUp(false);
- if ((mTracking && mTouchSlopExceeded) || Math.abs(x - mInitialTouchX) > mTouchSlop
- || Math.abs(y - mInitialTouchY) > mTouchSlop
+ if ((mTracking && mTouchSlopExceeded) || Math.abs(x - mInitialExpandX) > mTouchSlop
+ || Math.abs(y - mInitialExpandY) > mTouchSlop
|| event.getActionMasked() == MotionEvent.ACTION_CANCEL || forceCancel) {
mVelocityTracker.computeCurrentVelocity(1000);
float vel = mVelocityTracker.getYVelocity();
float vectorVel = (float) Math.hypot(
mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
- final boolean onKeyguard =
- mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
-
+ final boolean onKeyguard = mKeyguardStateController.isShowing();
final boolean expand;
if (mKeyguardStateController.isKeyguardFadingAway()
|| (mInitialTouchFromKeyguard && !onKeyguard)) {
@@ -448,13 +443,13 @@
// Log collapse gesture if on lock screen.
if (!expand && onKeyguard) {
float displayDensity = mCentralSurfaces.getDisplayDensity();
- int heightDp = (int) Math.abs((y - mInitialTouchY) / displayDensity);
+ int heightDp = (int) Math.abs((y - mInitialExpandY) / displayDensity);
int velocityDp = (int) Math.abs(vel / displayDensity);
mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_UNLOCK, heightDp, velocityDp);
mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_UNLOCK);
}
@Classifier.InteractionType int interactionType = vel == 0 ? GENERIC
- : y - mInitialTouchY > 0 ? QUICK_SETTINGS
+ : y - mInitialExpandY > 0 ? QUICK_SETTINGS
: (mKeyguardStateController.canDismissLockScreen()
? UNLOCK : BOUNCER_UNLOCK);
@@ -478,10 +473,7 @@
return mVelocityTracker.getYVelocity();
}
- private int getFalsingThreshold() {
- float factor = mCentralSurfaces.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
- return (int) (mUnlockFalsingThreshold * factor);
- }
+ protected abstract int getFalsingThreshold();
protected abstract boolean shouldGestureWaitForTouchSlop();
@@ -521,9 +513,7 @@
}
}
- protected boolean canCollapsePanelOnTouch() {
- return true;
- }
+ protected abstract boolean canCollapsePanelOnTouch();
protected float getContentHeight() {
return mExpandedHeight;
@@ -539,7 +529,7 @@
return true;
}
- @Classifier.InteractionType int interactionType = y - mInitialTouchY > 0
+ @Classifier.InteractionType int interactionType = y - mInitialExpandY > 0
? QUICK_SETTINGS : (
mKeyguardStateController.canDismissLockScreen() ? UNLOCK : BOUNCER_UNLOCK);
@@ -1092,16 +1082,16 @@
return animator;
}
- /** Update the visibility of {@link PanelView} if necessary. */
+ /** Update the visibility of {@link NotificationPanelView} if necessary. */
public void updateVisibility() {
mView.setVisibility(shouldPanelBeVisible() ? VISIBLE : INVISIBLE);
}
- /** Returns true if {@link PanelView} should be visible. */
+ /** Returns true if {@link NotificationPanelView} should be visible. */
abstract protected boolean shouldPanelBeVisible();
/**
- * Updates the panel expansion and {@link PanelView} visibility if necessary.
+ * Updates the panel expansion and {@link NotificationPanelView} visibility if necessary.
*
* TODO(b/200063118): Could public calls to this method be replaced with calls to
* {@link #updateVisibility()}? That would allow us to make this method private.
@@ -1176,9 +1166,7 @@
return mView;
}
- public OnLayoutChangeListener createLayoutChangeListener() {
- return new OnLayoutChangeListener();
- }
+ protected abstract OnLayoutChangeListener createLayoutChangeListener();
protected abstract TouchHandler createTouchHandler();
@@ -1223,8 +1211,8 @@
mTouchSlopExceeded = true;
return true;
}
- mInitialTouchY = y;
- mInitialTouchX = x;
+ mInitialExpandY = y;
+ mInitialExpandX = x;
mTouchStartedInEmptyArea = !isInContentBounds(x, y);
mTouchSlopExceeded = mTouchSlopExceededBeforeDown;
mMotionAborted = false;
@@ -1241,8 +1229,8 @@
// gesture is ongoing, find a new pointer to track
final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
mTrackingPointer = event.getPointerId(newIndex);
- mInitialTouchX = event.getX(newIndex);
- mInitialTouchY = event.getY(newIndex);
+ mInitialExpandX = event.getX(newIndex);
+ mInitialExpandY = event.getY(newIndex);
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
@@ -1252,7 +1240,7 @@
}
break;
case MotionEvent.ACTION_MOVE:
- final float h = y - mInitialTouchY;
+ final float h = y - mInitialExpandY;
addMovement(event);
final boolean openShadeWithoutHun =
mPanelClosedOnDown && !mCollapsedAndHeadsUpOnDown;
@@ -1262,7 +1250,7 @@
float touchSlop = getTouchSlop(event);
if ((h < -touchSlop
|| ((openShadeWithoutHun || mAnimatingOnDown) && hAbs > touchSlop))
- && hAbs > Math.abs(x - mInitialTouchX)) {
+ && hAbs > Math.abs(x - mInitialExpandX)) {
cancelHeightAnimator();
startExpandMotion(x, y, true /* startTracking */, mExpandedHeight);
return true;
@@ -1379,12 +1367,12 @@
break;
case MotionEvent.ACTION_MOVE:
addMovement(event);
- float h = y - mInitialTouchY;
+ float h = y - mInitialExpandY;
// If the panel was collapsed when touching, we only need to check for the
// y-component of the gesture, as we have no conflicting horizontal gesture.
if (Math.abs(h) > getTouchSlop(event)
- && (Math.abs(h) > Math.abs(x - mInitialTouchX)
+ && (Math.abs(h) > Math.abs(x - mInitialExpandX)
|| mIgnoreXTouchSlop)) {
mTouchSlopExceeded = true;
if (mGestureWaitForTouchSlop && !mTracking && !mCollapsedAndHeadsUpOnDown) {
@@ -1429,7 +1417,7 @@
}
}
- public class OnLayoutChangeListener implements View.OnLayoutChangeListener {
+ protected abstract class OnLayoutChangeListener implements View.OnLayoutChangeListener {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
int oldTop, int oldRight, int oldBottom) {
@@ -1444,7 +1432,7 @@
}
public class OnConfigurationChangedListener implements
- PanelView.OnConfigurationChangedListener {
+ NotificationPanelView.OnConfigurationChangedListener {
@Override
public void onConfigurationChanged(Configuration newConfig) {
loadDimens();
diff --git a/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
new file mode 100644
index 0000000..621a609
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade
+
+import android.hardware.display.AmbientDisplayConfiguration
+import android.os.SystemClock
+import android.os.UserHandle
+import android.provider.Settings
+import android.view.GestureDetector
+import android.view.MotionEvent
+import com.android.systemui.Dumpable
+import com.android.systemui.dock.DockManager
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.statusbar.phone.CentralSurfaces
+import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent
+import com.android.systemui.tuner.TunerService
+import com.android.systemui.tuner.TunerService.Tunable
+import java.io.PrintWriter
+import javax.inject.Inject
+
+/**
+ * If tap and/or double tap to wake is enabled, this gestureListener will wake the display on
+ * tap/double tap when the device is pulsing (AoD 2). Taps are gated by the proximity sensor and
+ * falsing manager.
+ *
+ * Touches go through the [NotificationShadeWindowViewController] when the device is pulsing.
+ * Otherwise, if the device is dozing and NOT pulsing, wake-ups are handled by
+ * [com.android.systemui.doze.DozeSensors].
+ */
+@CentralSurfacesComponent.CentralSurfacesScope
+class PulsingGestureListener @Inject constructor(
+ private val notificationShadeWindowView: NotificationShadeWindowView,
+ private val falsingManager: FalsingManager,
+ private val dockManager: DockManager,
+ private val centralSurfaces: CentralSurfaces,
+ private val ambientDisplayConfiguration: AmbientDisplayConfiguration,
+ tunerService: TunerService,
+ dumpManager: DumpManager
+) : GestureDetector.SimpleOnGestureListener(), Dumpable {
+ private var doubleTapEnabled = false
+ private var singleTapEnabled = false
+
+ init {
+ val tunable = Tunable { key: String?, _: String? ->
+ when (key) {
+ Settings.Secure.DOZE_DOUBLE_TAP_GESTURE ->
+ doubleTapEnabled = ambientDisplayConfiguration.doubleTapGestureEnabled(
+ UserHandle.USER_CURRENT)
+ Settings.Secure.DOZE_TAP_SCREEN_GESTURE ->
+ singleTapEnabled = ambientDisplayConfiguration.tapGestureEnabled(
+ UserHandle.USER_CURRENT)
+ }
+ }
+ tunerService.addTunable(tunable,
+ Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
+ Settings.Secure.DOZE_TAP_SCREEN_GESTURE)
+
+ dumpManager.registerDumpable(this)
+ }
+
+ override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
+ if (singleTapEnabled &&
+ !dockManager.isDocked &&
+ !falsingManager.isProximityNear &&
+ !falsingManager.isFalseTap(FalsingManager.MODERATE_PENALTY)
+ ) {
+ centralSurfaces.wakeUpIfDozing(
+ SystemClock.uptimeMillis(),
+ notificationShadeWindowView,
+ "PULSING_SINGLE_TAP")
+ return true
+ }
+ return false
+ }
+
+ override fun onDoubleTap(e: MotionEvent): Boolean {
+ if ((doubleTapEnabled || singleTapEnabled) &&
+ !falsingManager.isProximityNear &&
+ !falsingManager.isFalseDoubleTap
+ ) {
+ centralSurfaces.wakeUpIfDozing(
+ SystemClock.uptimeMillis(),
+ notificationShadeWindowView,
+ "PULSING_DOUBLE_TAP")
+ return true
+ }
+ return false
+ }
+
+ override fun dump(pw: PrintWriter, args: Array<out String>) {
+ pw.println("singleTapEnabled=$singleTapEnabled")
+ pw.println("doubleTapEnabled=$doubleTapEnabled")
+ pw.println("isDocked=${dockManager.isDocked}")
+ pw.println("isProxCovered=${falsingManager.isProximityNear}")
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index 15c75ff..a72b7f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -19,13 +19,13 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Handler;
-import android.os.Looper;
import android.os.SystemClock;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.view.accessibility.AccessibilityEvent;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.policy.HeadsUpManagerLogger;
@@ -43,14 +43,15 @@
protected final ArrayMap<String, AlertEntry> mAlertEntries = new ArrayMap<>();
protected final HeadsUpManagerLogger mLogger;
- public AlertingNotificationManager(HeadsUpManagerLogger logger) {
+ public AlertingNotificationManager(HeadsUpManagerLogger logger, @Main Handler handler) {
mLogger = logger;
+ mHandler = handler;
}
protected int mMinimumDisplayTime;
protected int mAutoDismissNotificationDecay;
@VisibleForTesting
- public Handler mHandler = new Handler(Looper.getMainLooper());
+ public Handler mHandler;
/**
* Called when posting a new notification that should alert the user and appear on screen.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedFrameLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedFrameLayout.java
index 359272e..662f70e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedFrameLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedFrameLayout.java
@@ -20,12 +20,28 @@
import android.util.AttributeSet;
import android.widget.FrameLayout;
+import com.android.systemui.animation.LaunchableView;
+import com.android.systemui.animation.LaunchableViewDelegate;
+
+import kotlin.Unit;
+
/**
* A frame layout which does not have overlapping renderings commands and therefore does not need a
* layer when alpha is changed.
*/
-public class AlphaOptimizedFrameLayout extends FrameLayout
+public class AlphaOptimizedFrameLayout extends FrameLayout implements LaunchableView
{
+ private final LaunchableViewDelegate mLaunchableViewDelegate = new LaunchableViewDelegate(
+ this,
+ visibility -> {
+ super.setVisibility(visibility);
+ return Unit.INSTANCE;
+ },
+ visibility -> {
+ super.setTransitionVisibility(visibility);
+ return Unit.INSTANCE;
+ });
+
public AlphaOptimizedFrameLayout(Context context) {
super(context);
}
@@ -47,4 +63,19 @@
public boolean hasOverlappingRendering() {
return false;
}
+
+ @Override
+ public void setShouldBlockVisibilityChanges(boolean block) {
+ mLaunchableViewDelegate.setShouldBlockVisibilityChanges(block);
+ }
+
+ @Override
+ public void setVisibility(int visibility) {
+ mLaunchableViewDelegate.setVisibility(visibility);
+ }
+
+ @Override
+ public void setTransitionVisibility(int visibility) {
+ mLaunchableViewDelegate.setTransitionVisibility(visibility);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index e992440..04621168 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -52,7 +52,6 @@
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.view.InsetsState.InternalInsetsType;
@@ -76,7 +75,6 @@
import com.android.systemui.tracing.ProtoTracer;
import java.io.FileOutputStream;
-import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -152,7 +150,6 @@
private static final int MSG_TRACING_STATE_CHANGED = 54 << MSG_SHIFT;
private static final int MSG_SUPPRESS_AMBIENT_DISPLAY = 55 << MSG_SHIFT;
private static final int MSG_REQUEST_WINDOW_MAGNIFICATION_CONNECTION = 56 << MSG_SHIFT;
- private static final int MSG_HANDLE_WINDOW_MANAGER_LOGGING_COMMAND = 57 << MSG_SHIFT;
//TODO(b/169175022) Update name and when feature name is locked.
private static final int MSG_EMERGENCY_ACTION_LAUNCH_GESTURE = 58 << MSG_SHIFT;
private static final int MSG_SET_NAVIGATION_BAR_LUMA_SAMPLING_ENABLED = 59 << MSG_SHIFT;
@@ -425,11 +422,6 @@
default void requestWindowMagnificationConnection(boolean connect) { }
/**
- * Handles a window manager shell logging command.
- */
- default void handleWindowManagerLoggingCommand(String[] args, ParcelFileDescriptor outFd) {}
-
- /**
* @see IStatusBar#setNavigationBarLumaSamplingEnabled(int, boolean)
*/
default void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {}
@@ -1143,17 +1135,6 @@
}
@Override
- public void handleWindowManagerLoggingCommand(String[] args, ParcelFileDescriptor outFd) {
- synchronized (mLock) {
- SomeArgs internalArgs = SomeArgs.obtain();
- internalArgs.arg1 = args;
- internalArgs.arg2 = outFd;
- mHandler.obtainMessage(MSG_HANDLE_WINDOW_MANAGER_LOGGING_COMMAND, internalArgs)
- .sendToTarget();
- }
- }
-
- @Override
public void suppressAmbientDisplay(boolean suppress) {
synchronized (mLock) {
mHandler.obtainMessage(MSG_SUPPRESS_AMBIENT_DISPLAY, suppress).sendToTarget();
@@ -1637,18 +1618,6 @@
mCallbacks.get(i).requestWindowMagnificationConnection((Boolean) msg.obj);
}
break;
- case MSG_HANDLE_WINDOW_MANAGER_LOGGING_COMMAND:
- args = (SomeArgs) msg.obj;
- try (ParcelFileDescriptor pfd = (ParcelFileDescriptor) args.arg2) {
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).handleWindowManagerLoggingCommand(
- (String[]) args.arg1, pfd);
- }
- } catch (IOException e) {
- Log.e(TAG, "Failed to handle logging command", e);
- }
- args.recycle();
- break;
case MSG_SET_NAVIGATION_BAR_LUMA_SAMPLING_ENABLED:
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).setNavigationBarLumaSamplingEnabled(msg.arg1,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
index b9684fc..3d161d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
@@ -24,6 +24,8 @@
import android.view.View;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
@@ -73,6 +75,7 @@
}
@Override
+ @NonNull
public ExpandableViewState createExpandableViewState() {
return new EmptyShadeViewState();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index c983644..47dc5c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -19,9 +19,12 @@
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_MANAGEMENT_DISCLOSURE;
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_NAMED_MANAGEMENT_DISCLOSURE;
+import static android.hardware.biometrics.BiometricSourceType.FACE;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
+import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
+import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.IMPORTANT_MSG_MIN_DURATION;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
@@ -122,6 +125,7 @@
private static final int MSG_HIDE_TRANSIENT = 1;
private static final int MSG_SHOW_ACTION_TO_UNLOCK = 2;
private static final int MSG_HIDE_BIOMETRIC_MESSAGE = 3;
+ private static final int MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON = 4;
private static final long TRANSIENT_BIOMETRIC_ERROR_TIMEOUT = 1300;
public static final long DEFAULT_HIDE_DELAY_MS =
3500 + KeyguardIndicationTextView.Y_IN_DURATION;
@@ -188,9 +192,11 @@
}
};
private ScreenLifecycle mScreenLifecycle;
- private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
+ private final ScreenLifecycle.Observer mScreenObserver =
+ new ScreenLifecycle.Observer() {
@Override
public void onScreenTurnedOn() {
+ mHandler.removeMessages(MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON);
if (mBiometricErrorMessageToShowOnScreenOn != null) {
showBiometricMessage(mBiometricErrorMessageToShowOnScreenOn);
// We want to keep this message around in case the screen was off
@@ -259,6 +265,8 @@
showActionToUnlock();
} else if (msg.what == MSG_HIDE_BIOMETRIC_MESSAGE) {
hideBiometricMessage();
+ } else if (msg.what == MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON) {
+ mBiometricErrorMessageToShowOnScreenOn = null;
}
}
};
@@ -423,9 +431,9 @@
if (info == null) {
// Use the current user owner information if enabled.
final boolean ownerInfoEnabled = mLockPatternUtils.isOwnerInfoEnabled(
- KeyguardUpdateMonitor.getCurrentUser());
+ getCurrentUser());
if (ownerInfoEnabled) {
- info = mLockPatternUtils.getOwnerInfo(KeyguardUpdateMonitor.getCurrentUser());
+ info = mLockPatternUtils.getOwnerInfo(getCurrentUser());
}
}
@@ -590,7 +598,7 @@
private void updateLockScreenLogoutView() {
final boolean shouldShowLogout = mKeyguardUpdateMonitor.isLogoutEnabled()
- && KeyguardUpdateMonitor.getCurrentUser() != UserHandle.USER_SYSTEM;
+ && getCurrentUser() != UserHandle.USER_SYSTEM;
if (shouldShowLogout) {
mRotateTextViewController.updateIndication(
INDICATION_TYPE_LOGOUT,
@@ -605,7 +613,7 @@
if (mFalsingManager.isFalseTap(LOW_PENALTY)) {
return;
}
- int currentUserId = KeyguardUpdateMonitor.getCurrentUser();
+ int currentUserId = getCurrentUser();
mDevicePolicyManager.logoutUser();
})
.build(),
@@ -762,7 +770,7 @@
mHandler.removeMessages(MSG_HIDE_BIOMETRIC_MESSAGE);
hideBiometricMessageDelayed(
mBiometricMessageFollowUp != null
- ? DEFAULT_HIDE_DELAY_MS * 2
+ ? IMPORTANT_MSG_MIN_DURATION * 2
: DEFAULT_HIDE_DELAY_MS
);
@@ -842,7 +850,7 @@
mTopIndicationView.setVisibility(GONE);
mTopIndicationView.setText(null);
mLockScreenIndicationView.setVisibility(View.VISIBLE);
- updateLockScreenIndications(animate, KeyguardUpdateMonitor.getCurrentUser());
+ updateLockScreenIndications(animate, getCurrentUser());
}
protected String computePowerIndication() {
@@ -910,7 +918,7 @@
public void showActionToUnlock() {
if (mDozing
&& !mKeyguardUpdateMonitor.getUserCanSkipBouncer(
- KeyguardUpdateMonitor.getCurrentUser())) {
+ getCurrentUser())) {
return;
}
@@ -923,7 +931,7 @@
}
} else {
final boolean canSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer(
- KeyguardUpdateMonitor.getCurrentUser());
+ getCurrentUser());
if (canSkipBouncer) {
final boolean faceAuthenticated = mKeyguardUpdateMonitor.getIsFaceAuthenticated();
final boolean udfpsSupported = mKeyguardUpdateMonitor.isUdfpsSupported();
@@ -1040,12 +1048,15 @@
return;
}
- boolean showActionToUnlock =
- msgId == KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
- if (biometricSourceType == BiometricSourceType.FACE
- && !showActionToUnlock
- && mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
- KeyguardUpdateMonitor.getCurrentUser())
+ final boolean faceAuthSoftError = biometricSourceType == FACE
+ && msgId != BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
+ final boolean faceAuthFailed = biometricSourceType == FACE
+ && msgId == BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; // ran through matcher & failed
+ final boolean isUnlockWithFingerprintPossible =
+ mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
+ getCurrentUser());
+ if (faceAuthSoftError
+ && isUnlockWithFingerprintPossible
&& !mCoExFaceHelpMsgIdsToShow.contains(msgId)) {
if (DEBUG) {
Log.d(TAG, "skip showing msgId=" + msgId + " helpString=" + helpString
@@ -1056,10 +1067,23 @@
mStatusBarKeyguardViewManager.showBouncerMessage(helpString,
mInitialTextColorState);
} else if (mScreenLifecycle.getScreenState() == SCREEN_ON) {
- showBiometricMessage(helpString);
- } else if (showActionToUnlock) {
+ if (faceAuthFailed && isUnlockWithFingerprintPossible) {
+ showBiometricMessage(
+ mContext.getString(R.string.keyguard_face_failed),
+ mContext.getString(R.string.keyguard_suggest_fingerprint)
+ );
+ } else {
+ showBiometricMessage(helpString);
+ }
+ } else if (faceAuthFailed) {
+ // show action to unlock
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SHOW_ACTION_TO_UNLOCK),
TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
+ } else {
+ mBiometricErrorMessageToShowOnScreenOn = helpString;
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON),
+ 1000);
}
}
@@ -1070,17 +1094,17 @@
return;
}
- if (biometricSourceType == BiometricSourceType.FACE
+ if (biometricSourceType == FACE
&& msgId == FaceManager.FACE_ERROR_UNABLE_TO_PROCESS) {
// suppress all face UNABLE_TO_PROCESS errors
if (DEBUG) {
Log.d(TAG, "skip showing FACE_ERROR_UNABLE_TO_PROCESS errString="
+ errString);
}
- } else if (biometricSourceType == BiometricSourceType.FACE
+ } else if (biometricSourceType == FACE
&& msgId == FaceManager.FACE_ERROR_TIMEOUT) {
if (mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
- KeyguardUpdateMonitor.getCurrentUser())) {
+ getCurrentUser())) {
// no message if fingerprint is also enrolled
if (DEBUG) {
Log.d(TAG, "skip showing FACE_ERROR_TIMEOUT due to co-ex logic");
@@ -1112,8 +1136,9 @@
BiometricSourceType biometricSourceType, KeyguardUpdateMonitor updateMonitor) {
if (biometricSourceType == BiometricSourceType.FINGERPRINT)
return shouldSuppressFingerprintError(msgId, updateMonitor);
- if (biometricSourceType == BiometricSourceType.FACE)
+ if (biometricSourceType == FACE) {
return shouldSuppressFaceError(msgId, updateMonitor);
+ }
return false;
}
@@ -1142,7 +1167,7 @@
@Override
public void onTrustChanged(int userId) {
- if (KeyguardUpdateMonitor.getCurrentUser() != userId) {
+ if (getCurrentUser() != userId) {
return;
}
updateDeviceEntryIndication(false);
@@ -1162,7 +1187,7 @@
@Override
public void onBiometricRunningStateChanged(boolean running,
BiometricSourceType biometricSourceType) {
- if (running && biometricSourceType == BiometricSourceType.FACE) {
+ if (running && biometricSourceType == FACE) {
// Let's hide any previous messages when authentication starts, otherwise
// multiple auth attempts would overlap.
hideBiometricMessage();
@@ -1176,7 +1201,7 @@
super.onBiometricAuthenticated(userId, biometricSourceType, isStrongBiometric);
hideBiometricMessage();
- if (biometricSourceType == BiometricSourceType.FACE
+ if (biometricSourceType == FACE
&& !mKeyguardBypassController.canBypass()) {
showActionToUnlock();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
index 0a616c0..9d2750f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
@@ -143,13 +143,13 @@
class CircleReveal(
/** X-value of the circle center of the reveal. */
- val centerX: Float,
+ val centerX: Int,
/** Y-value of the circle center of the reveal. */
- val centerY: Float,
+ val centerY: Int,
/** Radius of initial state of circle reveal */
- val startRadius: Float,
+ val startRadius: Int,
/** Radius of end state of circle reveal */
- val endRadius: Float
+ val endRadius: Int
) : LightRevealEffect {
override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {
// reveal amount updates already have an interpolator, so we intentionally use the
@@ -350,7 +350,7 @@
* This method does not call [invalidate] - you should do so once you're done changing
* properties.
*/
- public fun setRevealGradientBounds(left: Float, top: Float, right: Float, bottom: Float) {
+ fun setRevealGradientBounds(left: Float, top: Float, right: Float, bottom: Float) {
revealGradientWidth = right - left
revealGradientHeight = bottom - top
@@ -387,4 +387,4 @@
getColorWithAlpha(revealGradientEndColor, revealGradientEndColorAlpha),
PorterDuff.Mode.MULTIPLY)
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
index 2ca1beb..7b49ecd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
@@ -1,7 +1,6 @@
package com.android.systemui.statusbar
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import javax.inject.Inject
@@ -12,14 +11,12 @@
*/
@SysUISingleton
class NotificationInteractionTracker @Inject constructor(
- private val clicker: NotificationClickNotifier,
- private val entryManager: NotificationEntryManager
+ clicker: NotificationClickNotifier,
) : NotifCollectionListener, NotificationInteractionListener {
private val interactions = mutableMapOf<String, Boolean>()
init {
clicker.addNotificationInteractionListener(this)
- entryManager.addCollectionListener(this)
}
fun hasUserInteractedWith(key: String): Boolean {
@@ -38,5 +35,3 @@
interactions[key] = true
}
}
-
-private const val TAG = "NotificationInteractionTracker"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
index d1bc14f..d908243 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
@@ -50,12 +50,6 @@
void addUserChangedListener(UserChangedListener listener);
/**
- * Registers a [KeyguardNotificationSuppressor] that will be consulted during
- * {@link #shouldShowOnKeyguard(NotificationEntry)}
- */
- void addKeyguardNotificationSuppressor(KeyguardNotificationSuppressor suppressor);
-
- /**
* Removes a listener previously registered with
* {@link #addUserChangedListener(UserChangedListener)}
*/
@@ -63,14 +57,8 @@
SparseArray<UserInfo> getCurrentProfiles();
- void setLockscreenPublicMode(boolean isProfilePublic, int userId);
-
boolean shouldShowLockscreenNotifications();
- boolean shouldHideNotifications(int userId);
- boolean shouldHideNotifications(String key);
- boolean shouldShowOnKeyguard(NotificationEntry entry);
-
boolean isAnyProfilePublicMode();
void updatePublicMode();
@@ -108,11 +96,6 @@
default void onUserRemoved(int userId) {}
}
- /** Used to hide notifications on the lockscreen */
- interface KeyguardNotificationSuppressor {
- boolean shouldSuppressOnKeyguard(NotificationEntry entry);
- }
-
/**
* Notified when any state pertaining to Notifications has changed; any methods pertaining to
* notifications should be re-queried.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index f4ca7ed..8699441 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -15,17 +15,13 @@
*/
package com.android.systemui.statusbar;
-import static android.app.Notification.VISIBILITY_SECRET;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
import static com.android.systemui.DejankUtils.whitelistIpcs;
-import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_MEDIA_CONTROLS;
-import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -42,9 +38,10 @@
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -54,7 +51,6 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.recents.OverviewProxyService;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
@@ -88,9 +84,6 @@
private final SecureSettings mSecureSettings;
private final Object mLock = new Object();
- // Lazy
- private NotificationEntryManager mEntryManager;
-
private final Lazy<NotificationVisibilityProvider> mVisibilityProviderLazy;
private final Lazy<CommonNotifCollection> mCommonNotifCollectionLazy;
private final DevicePolicyManager mDevicePolicyManager;
@@ -110,7 +103,6 @@
private LockPatternUtils mLockPatternUtils;
protected KeyguardManager mKeyguardManager;
private int mState = StatusBarState.SHADE;
- private List<KeyguardNotificationSuppressor> mKeyguardSuppressors = new ArrayList<>();
private final ListenerSet<NotificationStateChangedListener> mNotifStateChangedListeners =
new ListenerSet<>();
@@ -123,7 +115,6 @@
isCurrentProfile(getSendingUserId())) {
mUsersAllowingPrivateNotifications.clear();
updateLockscreenNotificationSetting();
- getEntryManager().updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED");
// TODO(b/231976036): Consolidate pipeline invalidations related to this event
// notifyNotificationStateChanged();
}
@@ -144,10 +135,6 @@
updateLockscreenNotificationSetting();
updatePublicMode();
- // The filtering needs to happen before the update call below in order to
- // make sure
- // the presenter has the updated notifications from the new user
- getEntryManager().reapplyFilterAndSort("user switched");
mPresenter.onUserSwitched(mCurrentUserId);
for (UserChangedListener listener : mListeners) {
@@ -204,13 +191,6 @@
protected ContentObserver mSettingsObserver;
private boolean mHideSilentNotificationsOnLockscreen;
- private NotificationEntryManager getEntryManager() {
- if (mEntryManager == null) {
- mEntryManager = Dependency.get(NotificationEntryManager.class);
- }
- return mEntryManager;
- }
-
@Inject
public NotificationLockscreenUserManagerImpl(Context context,
BroadcastDispatcher broadcastDispatcher,
@@ -257,8 +237,6 @@
mUsersAllowingNotifications.clear();
// ... and refresh all the notifications
updateLockscreenNotificationSetting();
- getEntryManager().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS,"
- + " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change");
notifyNotificationStateChanged();
}
};
@@ -268,8 +246,6 @@
public void onChange(boolean selfChange) {
updateLockscreenNotificationSetting();
if (mDeviceProvisionedController.isDeviceProvisioned()) {
- getEntryManager().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT"
- + " or ZEN_MODE change");
// TODO(b/231976036): Consolidate pipeline invalidations related to this event
// notifyNotificationStateChanged();
}
@@ -344,67 +320,6 @@
}
}
- /**
- * Returns true if notifications are temporarily disabled for this user for security reasons,
- * regardless of the normal settings for that user.
- */
- private boolean shouldTemporarilyHideNotifications(int userId) {
- if (userId == UserHandle.USER_ALL) {
- userId = mCurrentUserId;
- }
- boolean inLockdown = Dependency.get(KeyguardUpdateMonitor.class).isUserInLockdown(userId);
- mUsersInLockdownLatestResult.put(userId, inLockdown);
- return inLockdown;
- }
-
- /**
- * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
- * If so, notifications should be hidden.
- */
- public boolean shouldHideNotifications(int userId) {
- boolean hide = isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId)
- || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId))
- || shouldTemporarilyHideNotifications(userId);
- mShouldHideNotifsLatestResult.put(userId, hide);
- return hide;
- }
-
- /**
- * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
- * package-specific override.
- */
- public boolean shouldHideNotifications(String key) {
- if (mCommonNotifCollectionLazy.get() == null) {
- Log.wtf(TAG, "mCommonNotifCollectionLazy was null!", new Throwable());
- return true;
- }
- NotificationEntry visibleEntry = mCommonNotifCollectionLazy.get().getEntry(key);
- return isLockscreenPublicMode(mCurrentUserId) && visibleEntry != null
- && visibleEntry.getRanking().getLockscreenVisibilityOverride() == VISIBILITY_SECRET;
- }
-
- public boolean shouldShowOnKeyguard(NotificationEntry entry) {
- if (mCommonNotifCollectionLazy.get() == null) {
- Log.wtf(TAG, "mCommonNotifCollectionLazy was null!", new Throwable());
- return false;
- }
- for (int i = 0; i < mKeyguardSuppressors.size(); i++) {
- if (mKeyguardSuppressors.get(i).shouldSuppressOnKeyguard(entry)) {
- return false;
- }
- }
- boolean exceedsPriorityThreshold;
- if (mHideSilentNotificationsOnLockscreen) {
- exceedsPriorityThreshold =
- entry.getBucket() == BUCKET_MEDIA_CONTROLS
- || (entry.getBucket() != BUCKET_SILENT
- && entry.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT);
- } else {
- exceedsPriorityThreshold = !entry.getRanking().isAmbient();
- }
- return mShowLockscreenNotifications && exceedsPriorityThreshold;
- }
-
private void setShowLockscreenNotifications(boolean show) {
mShowLockscreenNotifications = show;
}
@@ -491,7 +406,8 @@
/**
* Save the current "public" (locked and secure) state of the lockscreen.
*/
- public void setLockscreenPublicMode(boolean publicMode, int userId) {
+ @VisibleForTesting
+ void setLockscreenPublicMode(boolean publicMode, int userId) {
mLockscreenPublicMode.put(userId, publicMode);
}
@@ -660,7 +576,6 @@
setLockscreenPublicMode(isProfilePublic, userId);
mUsersWithSeparateWorkChallenge.put(userId, needsSeparateChallenge);
}
- getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode");
// TODO(b/234738798): Migrate KeyguardNotificationVisibilityProvider to use this listener
if (!mLockscreenPublicMode.equals(oldPublicModes)
|| !mUsersWithSeparateWorkChallenge.equals(oldWorkChallenges)) {
@@ -674,11 +589,6 @@
}
@Override
- public void addKeyguardNotificationSuppressor(KeyguardNotificationSuppressor suppressor) {
- mKeyguardSuppressors.add(suppressor);
- }
-
- @Override
public void removeUserChangedListener(UserChangedListener listener) {
mListeners.remove(listener);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index d74d408..f668528 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -53,8 +53,6 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.dagger.CentralSurfacesDependenciesModule;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
-import com.android.systemui.statusbar.notification.NotificationEntryListener;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
@@ -256,7 +254,6 @@
NotificationLockscreenUserManager lockscreenUserManager,
SmartReplyController smartReplyController,
NotificationVisibilityProvider visibilityProvider,
- NotificationEntryManager notificationEntryManager,
Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy,
StatusBarStateController statusBarStateController,
RemoteInputUriController remoteInputUriController,
@@ -279,25 +276,6 @@
mClickNotifier = clickNotifier;
dumpManager.registerDumpable(this);
-
- notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
- @Override
- public void onPreEntryUpdated(NotificationEntry entry) {
- // Mark smart replies as sent whenever a notification is updated - otherwise the
- // smart replies are never marked as sent.
- mSmartReplyController.stopSending(entry);
- }
-
- @Override
- public void onEntryRemoved(
- @Nullable NotificationEntry entry,
- NotificationVisibility visibility,
- boolean removedByUser,
- int reason) {
- // We're removing the notification, the smart controller can forget about it.
- mSmartReplyController.stopSending(entry);
- }
- });
}
/** Add a listener for various remote input events. Works with NEW pipeline only. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 2214287..cea3deb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -29,6 +29,8 @@
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
+import androidx.annotation.NonNull;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R;
@@ -153,6 +155,7 @@
}
@Override
+ @NonNull
public ExpandableViewState createExpandableViewState() {
return new ShelfState();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java
index 7097568..e582a01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java
@@ -31,7 +31,7 @@
com.android.internal.R.drawable.ic_wifi_signal_4
};
- private static final int[] WIFI_NO_INTERNET_ICONS = {
+ public static final int[] WIFI_NO_INTERNET_ICONS = {
R.drawable.ic_no_internet_wifi_signal_0,
R.drawable.ic_no_internet_wifi_signal_1,
R.drawable.ic_no_internet_wifi_signal_2,
@@ -48,7 +48,7 @@
public static final int QS_WIFI_DISABLED = com.android.internal.R.drawable.ic_wifi_signal_0;
public static final int QS_WIFI_NO_NETWORK = com.android.internal.R.drawable.ic_wifi_signal_0;
- static final int WIFI_NO_NETWORK = QS_WIFI_NO_NETWORK;
+ public static final int WIFI_NO_NETWORK = QS_WIFI_NO_NETWORK;
static final int WIFI_LEVEL_COUNT = WIFI_SIGNAL_STRENGTH[0].length;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
index 8752f92..7cd79ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
@@ -18,7 +18,6 @@
import android.app.IActivityManager;
import android.content.Context;
-import android.os.Handler;
import android.os.RemoteException;
import android.service.dreams.IDreamManager;
import android.util.Log;
@@ -42,14 +41,12 @@
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.RemoteInputNotificationRebuilder;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.commandline.CommandRegistry;
import com.android.systemui.statusbar.gesture.SwipeStatusBarAwayGestureHandler;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
@@ -99,11 +96,8 @@
NotificationLockscreenUserManager lockscreenUserManager,
SmartReplyController smartReplyController,
NotificationVisibilityProvider visibilityProvider,
- NotificationEntryManager notificationEntryManager,
- RemoteInputNotificationRebuilder rebuilder,
Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy,
StatusBarStateController statusBarStateController,
- Handler mainHandler,
RemoteInputUriController remoteInputUriController,
NotificationClickNotifier clickNotifier,
ActionClickLogger actionClickLogger,
@@ -114,7 +108,6 @@
lockscreenUserManager,
smartReplyController,
visibilityProvider,
- notificationEntryManager,
centralSurfacesOptionalLazy,
statusBarStateController,
remoteInputUriController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/DisableStateTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/DisableStateTracker.kt
new file mode 100644
index 0000000..562f585
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/DisableStateTracker.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.disableflags
+
+import com.android.systemui.statusbar.CommandQueue
+
+/**
+ * Tracks the relevant DISABLE_* flags provided in [mask1] and [mask2] and sets [isDisabled] based
+ * on those masks. [callback] will be notified whenever [isDisabled] changes.
+ *
+ * Users are responsible for adding and removing this tracker from [CommandQueue] callbacks.
+ */
+class DisableStateTracker(
+ private val mask1: Int,
+ private val mask2: Int,
+ private val callback: Callback,
+) : CommandQueue.Callbacks {
+ /**
+ * True if any of the bits in [mask1] or [mask2] are on for the current disable flags, and false
+ * otherwise.
+ */
+ var isDisabled = false
+ private set(value) {
+ if (field == value) return
+ field = value
+ callback.onDisabledChanged()
+ }
+
+ private var displayId: Int? = null
+
+ /** Start tracking the disable flags and updating [isDisabled] accordingly. */
+ fun startTracking(commandQueue: CommandQueue, displayId: Int) {
+ // A view will only have its displayId once it's attached to a window, so we can only
+ // provide the displayId when we start tracking.
+ this.displayId = displayId
+ commandQueue.addCallback(this)
+ }
+
+ /**
+ * Stop tracking the disable flags.
+ *
+ * [isDisabled] will stay at the same value until we start tracking again.
+ */
+ fun stopTracking(commandQueue: CommandQueue) {
+ this.displayId = null
+ commandQueue.removeCallback(this)
+ }
+
+ override fun disable(displayId: Int, state1: Int, state2: Int, animate: Boolean) {
+ if (this.displayId == null || displayId != this.displayId) {
+ return
+ }
+ isDisabled = state1 and mask1 != 0 || state2 and mask2 != 0
+ }
+
+ /** Callback triggered whenever the value of [isDisabled] changes. */
+ fun interface Callback {
+ fun onDisabledChanged()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 8cb18a0..59022c0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -50,7 +50,6 @@
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.CoreStartable;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.UiBackground;
@@ -76,20 +75,22 @@
private final Executor mUiBgExecutor;
private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
private final CommandQueue mCommandQueue;
- private KeyguardStateController mKeyguardStateController;
+ private final KeyguardStateController mKeyguardStateController;
@Inject
- public InstantAppNotifier(Context context, CommandQueue commandQueue,
- @UiBackground Executor uiBgExecutor) {
+ public InstantAppNotifier(
+ Context context,
+ CommandQueue commandQueue,
+ @UiBackground Executor uiBgExecutor,
+ KeyguardStateController keyguardStateController) {
super(context);
mCommandQueue = commandQueue;
mUiBgExecutor = uiBgExecutor;
+ mKeyguardStateController = keyguardStateController;
}
@Override
public void start() {
- mKeyguardStateController = Dependency.get(KeyguardStateController.class);
-
// listen for user / profile change.
try {
ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
deleted file mode 100644
index e2f87b6..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2017 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.statusbar.notification;
-
-import android.service.notification.NotificationListenerService;
-import android.service.notification.StatusBarNotification;
-import android.util.ArrayMap;
-
-import androidx.annotation.NonNull;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * NotificationEntryManager is responsible for the adding, removing, and updating of
- * {@link NotificationEntry}s. It also handles tasks such as their inflation and their interaction
- * with other Notification.*Manager objects.
- *
- * We track notification entries through this lifecycle:
- * 1. Pending
- * 2. Active
- * 3. Sorted / filtered (visible)
- *
- * Every entry spends some amount of time in the pending state, while it is being inflated. Once
- * inflated, an entry moves into the active state, where it _could_ potentially be shown to the
- * user. After an entry makes its way into the active state, we sort and filter the entire set to
- * repopulate the visible set.
- */
-public class NotificationEntryManager implements VisualStabilityManager.Callback {
-
- private final NotificationEntryManagerLogger mLogger;
-
- /** Pending notifications are ones awaiting inflation */
- @VisibleForTesting
- protected final HashMap<String, NotificationEntry> mPendingNotifications = new HashMap<>();
- /**
- * Active notifications have been inflated / prepared and could become visible, but may get
- * filtered out if for instance they are not for the current user
- */
- private final ArrayMap<String, NotificationEntry> mActiveNotifications = new ArrayMap<>();
- /** This is the list of "active notifications for this user in this context" */
- @VisibleForTesting
- protected final ArrayList<NotificationEntry> mSortedAndFiltered = new ArrayList<>();
- private final List<NotifCollectionListener> mNotifCollectionListeners = new ArrayList<>();
- private final List<NotificationEntryListener> mNotificationEntryListeners = new ArrayList<>();
-
- /**
- * Injected constructor. See {@link NotificationsModule}.
- */
- public NotificationEntryManager(NotificationEntryManagerLogger logger) {
- mLogger = logger;
- }
-
- /** Adds a {@link NotificationEntryListener}. */
- public void addNotificationEntryListener(NotificationEntryListener listener) {
- mNotificationEntryListeners.add(listener);
- }
-
- /**
- * Removes a {@link NotificationEntryListener} previously registered via
- * {@link #addNotificationEntryListener(NotificationEntryListener)}.
- */
- public void removeNotificationEntryListener(NotificationEntryListener listener) {
- mNotificationEntryListeners.remove(listener);
- }
-
- @Override
- public void onChangeAllowed() {
- updateNotifications("reordering is now allowed");
- }
-
- /**
- * Update the notifications
- * @param reason why the notifications are updating
- */
- public void updateNotifications(String reason) {
- mLogger.logUseWhileNewPipelineActive("updateNotifications", reason);
- }
-
- /*
- * -----
- * Annexed from NotificationData below:
- * Some of these methods may be redundant but require some reworking to remove. For now
- * we'll try to keep the behavior the same and can simplify these interfaces in another pass
- */
-
- /** Resorts / filters the current notification set with the current RankingMap */
- public void reapplyFilterAndSort(String reason) {
- mLogger.logUseWhileNewPipelineActive("reapplyFilterAndSort", reason);
- }
-
- /** dump the current active notification list. Called from CentralSurfaces */
- public void dump(PrintWriter pw, String indent) {
- pw.println("NotificationEntryManager (Legacy)");
- int filteredLen = mSortedAndFiltered.size();
- pw.print(indent);
- pw.println("active notifications: " + filteredLen);
- int active;
- for (active = 0; active < filteredLen; active++) {
- NotificationEntry e = mSortedAndFiltered.get(active);
- dumpEntry(pw, indent, active, e);
- }
- synchronized (mActiveNotifications) {
- int totalLen = mActiveNotifications.size();
- pw.print(indent);
- pw.println("inactive notifications: " + (totalLen - active));
- int inactiveCount = 0;
- for (int i = 0; i < totalLen; i++) {
- NotificationEntry entry = mActiveNotifications.valueAt(i);
- if (!mSortedAndFiltered.contains(entry)) {
- dumpEntry(pw, indent, inactiveCount, entry);
- inactiveCount++;
- }
- }
- }
- }
-
- private void dumpEntry(PrintWriter pw, String indent, int i, NotificationEntry e) {
- pw.print(indent);
- pw.println(" [" + i + "] key=" + e.getKey() + " icon=" + e.getIcons().getStatusBarIcon());
- StatusBarNotification n = e.getSbn();
- pw.print(indent);
- pw.println(" pkg=" + n.getPackageName() + " id=" + n.getId() + " importance="
- + e.getRanking().getImportance());
- pw.print(indent);
- pw.println(" notification=" + n.getNotification());
- }
-
- public void addCollectionListener(@NonNull NotifCollectionListener listener) {
- mNotifCollectionListeners.add(listener);
- }
-
- public void removeCollectionListener(@NonNull NotifCollectionListener listener) {
- mNotifCollectionListeners.remove(listener);
- }
-
- /*
- * End annexation
- * -----
- */
-
-
- /**
- * Provides access to keyguard state and user settings dependent data.
- */
- public interface KeyguardEnvironment {
- /** true if the device is provisioned (should always be true in practice) */
- boolean isDeviceProvisioned();
- /** true if the notification is for the current profiles */
- boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
- }
-
- /**
- * Used when a notification is removed and it doesn't have a reason that maps to one of the
- * reasons defined in NotificationListenerService
- * (e.g. {@link NotificationListenerService#REASON_CANCEL})
- */
- public static final int UNDEFINED_DISMISS_REASON = 0;
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManagerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManagerLogger.kt
deleted file mode 100644
index 52dcf02..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManagerLogger.kt
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2020 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.statusbar.notification
-
-import com.android.systemui.log.LogBuffer
-import com.android.systemui.log.LogLevel
-import com.android.systemui.log.LogLevel.DEBUG
-import com.android.systemui.log.LogLevel.INFO
-import com.android.systemui.log.LogLevel.WARNING
-import com.android.systemui.log.LogMessage
-import com.android.systemui.log.dagger.NotificationLog
-import com.android.systemui.util.Compile
-import javax.inject.Inject
-
-/** Logger for [NotificationEntryManager]. */
-class NotificationEntryManagerLogger @Inject constructor(
- notifPipelineFlags: NotifPipelineFlags,
- @NotificationLog private val buffer: LogBuffer
-) {
- private val devLoggingEnabled by lazy { notifPipelineFlags.isDevLoggingEnabled() }
-
- private inline fun devLog(
- level: LogLevel,
- initializer: LogMessage.() -> Unit,
- noinline printer: LogMessage.() -> String
- ) {
- if (Compile.IS_DEBUG && devLoggingEnabled) buffer.log(TAG, level, initializer, printer)
- }
-
- fun logNotifAdded(key: String) {
- devLog(INFO, {
- str1 = key
- }, {
- "NOTIF ADDED $str1"
- })
- }
-
- fun logNotifUpdated(key: String) {
- devLog(INFO, {
- str1 = key
- }, {
- "NOTIF UPDATED $str1"
- })
- }
-
- fun logInflationAborted(key: String, status: String, reason: String) {
- devLog(DEBUG, {
- str1 = key
- str2 = status
- str3 = reason
- }, {
- "NOTIF INFLATION ABORTED $str1 notifStatus=$str2 reason=$str3"
- })
- }
-
- fun logNotifInflated(key: String, isNew: Boolean) {
- devLog(DEBUG, {
- str1 = key
- bool1 = isNew
- }, {
- "NOTIF INFLATED $str1 isNew=$bool1}"
- })
- }
-
- fun logRemovalIntercepted(key: String) {
- devLog(INFO, {
- str1 = key
- }, {
- "NOTIF REMOVE INTERCEPTED for $str1"
- })
- }
-
- fun logLifetimeExtended(key: String, extenderName: String, status: String) {
- devLog(INFO, {
- str1 = key
- str2 = extenderName
- str3 = status
- }, {
- "NOTIF LIFETIME EXTENDED $str1 extender=$str2 status=$str3"
- })
- }
-
- fun logNotifRemoved(key: String, removedByUser: Boolean) {
- devLog(INFO, {
- str1 = key
- bool1 = removedByUser
- }, {
- "NOTIF REMOVED $str1 removedByUser=$bool1"
- })
- }
-
- fun logFilterAndSort(reason: String) {
- devLog(INFO, {
- str1 = reason
- }, {
- "FILTER AND SORT reason=$str1"
- })
- }
-
- fun logUseWhileNewPipelineActive(method: String, reason: String) {
- buffer.log(TAG, WARNING, {
- str1 = method
- str2 = reason
- }, {
- "While running New Pipeline: $str1(reason=$str2)"
- })
- }
-}
-
-private const val TAG = "NotificationEntryMgr"
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
deleted file mode 100644
index c9c6f28..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2019 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.statusbar.notification;
-
-import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-
-import java.util.Objects;
-
-/**
- * Root controller for the list of notifications in the shade.
- *
- * TODO: Much of the code in NotificationPresenter should eventually move in here. It will proxy
- * domain-specific behavior (ARC, etc) to subcontrollers.
- */
-public class NotificationListController {
- private final NotificationEntryManager mEntryManager;
- private final NotificationListContainer mListContainer;
- private final DeviceProvisionedController mDeviceProvisionedController;
-
- public NotificationListController(
- NotificationEntryManager entryManager,
- NotificationListContainer listContainer,
- DeviceProvisionedController deviceProvisionedController) {
- mEntryManager = Objects.requireNonNull(entryManager);
- mListContainer = Objects.requireNonNull(listContainer);
- mDeviceProvisionedController = Objects.requireNonNull(deviceProvisionedController);
- }
-
- /**
- * Causes the controller to register listeners on its dependencies. This method must be called
- * before the controller is ready to perform its duties.
- */
- public void bind() {
- mEntryManager.addNotificationEntryListener(mEntryListener);
- mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
- }
-
- @SuppressWarnings("FieldCanBeLocal")
- private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
- @Override
- public void onEntryRemoved(
- NotificationEntry entry,
- NotificationVisibility visibility,
- boolean removedByUser,
- int reason) {
- mListContainer.cleanUpViewStateForEntry(entry);
- }
- };
-
- // TODO: (b/145659174) remove after moving to NewNotifPipeline. Replaced by
- // DeviceProvisionedCoordinator
- private final DeviceProvisionedListener mDeviceProvisionedListener =
- new DeviceProvisionedListener() {
- @Override
- public void onDeviceProvisionedChanged() {
- mEntryManager.updateNotifications("device provisioned changed");
- }
- };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index dbf4810..126a986 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -18,10 +18,8 @@
import android.animation.ObjectAnimator
import android.util.FloatProperty
-import com.android.systemui.Dumpable
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -34,20 +32,17 @@
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionListener
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener
-import java.io.PrintWriter
import javax.inject.Inject
import kotlin.math.min
@SysUISingleton
class NotificationWakeUpCoordinator @Inject constructor(
- dumpManager: DumpManager,
private val mHeadsUpManager: HeadsUpManager,
private val statusBarStateController: StatusBarStateController,
private val bypassController: KeyguardBypassController,
private val dozeParameters: DozeParameters,
private val screenOffAnimationController: ScreenOffAnimationController
-) : OnHeadsUpChangedListener, StatusBarStateController.StateListener, PanelExpansionListener,
- Dumpable {
+) : OnHeadsUpChangedListener, StatusBarStateController.StateListener, PanelExpansionListener {
private val mNotificationVisibility = object : FloatProperty<NotificationWakeUpCoordinator>(
"notificationVisibility") {
@@ -65,7 +60,6 @@
private var mLinearDozeAmount: Float = 0.0f
private var mDozeAmount: Float = 0.0f
- private var mDozeAmountSource: String = "init"
private var mNotificationVisibleAmount = 0.0f
private var mNotificationsVisible = false
private var mNotificationsVisibleForExpansion = false
@@ -148,7 +142,6 @@
}
init {
- dumpManager.registerDumpable(this)
mHeadsUpManager.addListener(this)
statusBarStateController.addCallback(this)
addListener(object : WakeUpListener {
@@ -255,14 +248,13 @@
// Let's notify the scroller that an animation started
notifyAnimationStart(mLinearDozeAmount == 1.0f)
}
- setDozeAmount(linear, eased, source = "StatusBar")
+ setDozeAmount(linear, eased)
}
- fun setDozeAmount(linear: Float, eased: Float, source: String) {
+ fun setDozeAmount(linear: Float, eased: Float) {
val changed = linear != mLinearDozeAmount
mLinearDozeAmount = linear
mDozeAmount = eased
- mDozeAmountSource = source
mStackScrollerController.setDozeAmount(mDozeAmount)
updateHideAmount()
if (changed && linear == 0.0f) {
@@ -279,7 +271,7 @@
// undefined state, so it's an indication that we should do state cleanup. We override
// the doze amount to 0f (not dozing) so that the notifications are no longer hidden.
// See: UnlockedScreenOffAnimationController.onFinishedWakingUp()
- setDozeAmount(0f, 0f, source = "Override: Shade->Shade (lock cancelled by unlock)")
+ setDozeAmount(0f, 0f)
}
if (overrideDozeAmountIfAnimatingScreenOff(mLinearDozeAmount)) {
@@ -319,11 +311,12 @@
*/
private fun overrideDozeAmountIfBypass(): Boolean {
if (bypassController.bypassEnabled) {
- if (statusBarStateController.state == StatusBarState.KEYGUARD) {
- setDozeAmount(1f, 1f, source = "Override: bypass (keyguard)")
- } else {
- setDozeAmount(0f, 0f, source = "Override: bypass (shade)")
+ var amount = 1.0f
+ if (statusBarStateController.state == StatusBarState.SHADE ||
+ statusBarStateController.state == StatusBarState.SHADE_LOCKED) {
+ amount = 0.0f
}
+ setDozeAmount(amount, amount)
return true
}
return false
@@ -339,7 +332,7 @@
*/
private fun overrideDozeAmountIfAnimatingScreenOff(linearDozeAmount: Float): Boolean {
if (screenOffAnimationController.overrideNotificationsFullyDozingOnKeyguard()) {
- setDozeAmount(1f, 1f, source = "Override: animating screen off")
+ setDozeAmount(1f, 1f)
return true
}
@@ -433,24 +426,4 @@
*/
@JvmDefault fun onPulseExpansionChanged(expandingChanged: Boolean) {}
}
-
- override fun dump(pw: PrintWriter, args: Array<out String>) {
- pw.println("mLinearDozeAmount: $mLinearDozeAmount")
- pw.println("mDozeAmount: $mDozeAmount")
- pw.println("mDozeAmountSource: $mDozeAmountSource")
- pw.println("mNotificationVisibleAmount: $mNotificationVisibleAmount")
- pw.println("mNotificationsVisible: $mNotificationsVisible")
- pw.println("mNotificationsVisibleForExpansion: $mNotificationsVisibleForExpansion")
- pw.println("mVisibilityAmount: $mVisibilityAmount")
- pw.println("mLinearVisibilityAmount: $mLinearVisibilityAmount")
- pw.println("pulseExpanding: $pulseExpanding")
- pw.println("state: ${StatusBarState.toString(state)}")
- pw.println("fullyAwake: $fullyAwake")
- pw.println("wakingUp: $wakingUp")
- pw.println("willWakeUp: $willWakeUp")
- pw.println("collapsedEnoughToHide: $collapsedEnoughToHide")
- pw.println("pulsing: $pulsing")
- pw.println("notificationsFullyHidden: $notificationsFullyHidden")
- pw.println("canShowPulsingHuns: $canShowPulsingHuns")
- }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt
index 9e5dab1..f8449ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt
@@ -90,6 +90,18 @@
stableIndex = -1
}
+ /**
+ * Erases bookkeeping traces stored on an entry when it is removed from the notif list.
+ * This can happen if the entry is removed from a group that was broken up or if the entry was
+ * filtered out during any of the filtering steps.
+ */
+ fun detach() {
+ parent = null
+ section = null
+ promoter = null
+ // stableIndex = -1 // TODO(b/241229236): Clear this once we fix the stability fragility
+ }
+
companion object {
@JvmStatic
fun create(): ListAttachState {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 68bf69a..2887f97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -88,9 +88,9 @@
import com.android.systemui.statusbar.notification.collection.notifcollection.EntryUpdatedEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.InitEntryEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.InternalNotifUpdater;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionInconsistencyTracker;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLogger;
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLoggerKt;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
@@ -112,7 +112,6 @@
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
-import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -151,6 +150,7 @@
private final Executor mBgExecutor;
private final LogBufferEulogizer mEulogizer;
private final DumpManager mDumpManager;
+ private final NotifCollectionInconsistencyTracker mInconsistencyTracker;
private final Map<String, NotificationEntry> mNotificationSet = new ArrayMap<>();
private final Collection<NotificationEntry> mReadOnlyNotificationSet =
@@ -162,7 +162,6 @@
private final List<NotifLifetimeExtender> mLifetimeExtenders = new ArrayList<>();
private final List<NotifDismissInterceptor> mDismissInterceptors = new ArrayList<>();
- private Set<String> mNotificationsWithoutRankings = Collections.emptySet();
private Queue<NotifEvent> mEventQueue = new ArrayDeque<>();
@@ -188,6 +187,7 @@
mBgExecutor = bgExecutor;
mEulogizer = logBufferEulogizer;
mDumpManager = dumpManager;
+ mInconsistencyTracker = new NotifCollectionInconsistencyTracker(mLogger);
}
/** Initializes the NotifCollection and registers it to receive notification events. */
@@ -199,6 +199,7 @@
mAttached = true;
mDumpManager.registerDumpable(TAG, this);
groupCoalescer.setNotificationHandler(mNotifHandler);
+ mInconsistencyTracker.attach(mNotificationSet::keySet, groupCoalescer::getCoalescedKeySet);
}
/**
@@ -598,14 +599,9 @@
}
}
}
- NotifCollectionLoggerKt.maybeLogInconsistentRankings(
- mLogger,
- mNotificationsWithoutRankings,
- currentEntriesWithoutRankings,
- rankingMap
- );
- mNotificationsWithoutRankings = currentEntriesWithoutRankings == null
- ? Collections.emptySet() : currentEntriesWithoutRankings.keySet();
+
+ mInconsistencyTracker.logNewMissingNotifications(rankingMap);
+ mInconsistencyTracker.logNewInconsistentRankings(currentEntriesWithoutRankings, rankingMap);
if (currentEntriesWithoutRankings != null && mNotifPipelineFlags.removeUnrankedNotifs()) {
for (NotificationEntry entry : currentEntriesWithoutRankings.values()) {
entry.mCancellationReason = REASON_UNKNOWN;
@@ -864,10 +860,7 @@
true,
"\t\t"));
- pw.println("\n\tmNotificationsWithoutRankings: " + mNotificationsWithoutRankings.size());
- for (String key : mNotificationsWithoutRankings) {
- pw.println("\t * : " + key);
- }
+ mInconsistencyTracker.dump(pw);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 14cc6bf..3eaa988 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -958,9 +958,7 @@
* filtered out during any of the filtering steps.
*/
private void annulAddition(ListEntry entry) {
- entry.setParent(null);
- entry.getAttachState().setSection(null);
- entry.getAttachState().setPromoter(null);
+ entry.getAttachState().detach();
}
private void assignSections() {
@@ -1198,9 +1196,9 @@
o2.getSectionIndex());
if (cmp != 0) return cmp;
- int index1 = canReorder(o1) ? -1 : o1.getPreviousAttachState().getStableIndex();
- int index2 = canReorder(o2) ? -1 : o2.getPreviousAttachState().getStableIndex();
- cmp = Integer.compare(index1, index2);
+ cmp = Integer.compare(
+ getStableOrderIndex(o1),
+ getStableOrderIndex(o2));
if (cmp != 0) return cmp;
NotifComparator sectionComparator = getSectionComparator(o1, o2);
@@ -1214,31 +1212,32 @@
if (cmp != 0) return cmp;
}
- final NotificationEntry rep1 = o1.getRepresentativeEntry();
- final NotificationEntry rep2 = o2.getRepresentativeEntry();
- cmp = rep1.getRanking().getRank() - rep2.getRanking().getRank();
+ cmp = Integer.compare(
+ o1.getRepresentativeEntry().getRanking().getRank(),
+ o2.getRepresentativeEntry().getRanking().getRank());
if (cmp != 0) return cmp;
- cmp = Long.compare(
- rep2.getSbn().getNotification().when,
- rep1.getSbn().getNotification().when);
+ cmp = -1 * Long.compare(
+ o1.getRepresentativeEntry().getSbn().getNotification().when,
+ o2.getRepresentativeEntry().getSbn().getNotification().when);
return cmp;
};
private final Comparator<NotificationEntry> mGroupChildrenComparator = (o1, o2) -> {
- int index1 = canReorder(o1) ? -1 : o1.getPreviousAttachState().getStableIndex();
- int index2 = canReorder(o2) ? -1 : o2.getPreviousAttachState().getStableIndex();
- int cmp = Integer.compare(index1, index2);
+ int cmp = Integer.compare(
+ getStableOrderIndex(o1),
+ getStableOrderIndex(o2));
if (cmp != 0) return cmp;
- cmp = o1.getRepresentativeEntry().getRanking().getRank()
- - o2.getRepresentativeEntry().getRanking().getRank();
+ cmp = Integer.compare(
+ o1.getRepresentativeEntry().getRanking().getRank(),
+ o2.getRepresentativeEntry().getRanking().getRank());
if (cmp != 0) return cmp;
- cmp = Long.compare(
- o2.getRepresentativeEntry().getSbn().getNotification().when,
- o1.getRepresentativeEntry().getSbn().getNotification().when);
+ cmp = -1 * Long.compare(
+ o1.getRepresentativeEntry().getSbn().getNotification().when,
+ o2.getRepresentativeEntry().getSbn().getNotification().when);
return cmp;
};
@@ -1248,8 +1247,16 @@
*/
private boolean mForceReorderable = false;
- private boolean canReorder(ListEntry entry) {
- return mForceReorderable || getStabilityManager().isEntryReorderingAllowed(entry);
+ private int getStableOrderIndex(ListEntry entry) {
+ if (mForceReorderable) {
+ // this is used to determine if the list is correctly sorted
+ return -1;
+ }
+ if (getStabilityManager().isEntryReorderingAllowed(entry)) {
+ // let the stability manager constrain or allow reordering
+ return -1;
+ }
+ return entry.getPreviousAttachState().getStableIndex();
}
private boolean applyFilters(NotificationEntry entry, long now, List<NotifFilter> filters) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
index 98f2167..96b3542 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
@@ -39,9 +39,11 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.inject.Inject;
@@ -118,6 +120,11 @@
mHandler = handler;
}
+ /** @return the set of notification keys currently in the coalescer */
+ public Set<String> getCoalescedKeySet() {
+ return Collections.unmodifiableSet(mCoalescedEvents.keySet());
+ }
+
private final NotificationHandler mListener = new NotificationHandler() {
@Override
public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
index 9d0f974..32150fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
@@ -20,11 +20,9 @@
import android.os.Parcelable
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
-import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
@@ -44,14 +42,10 @@
* In addition, notifications that have recently alerted aren't filtered. Tracking this in a way
* that involves the fewest pipeline invalidations requires some unfortunately complex logic.
*/
-// This class is a singleton so that the same instance can be accessed by both the old and new
-// pipelines
@CoordinatorScope
class SmartspaceDedupingCoordinator @Inject constructor(
private val statusBarStateController: SysuiStatusBarStateController,
private val smartspaceController: LockscreenSmartspaceController,
- private val notificationEntryManager: NotificationEntryManager,
- private val notificationLockscreenUserManager: NotificationLockscreenUserManager,
private val notifPipeline: NotifPipeline,
@Main private val executor: DelayableExecutor,
private val clock: SystemClock
@@ -132,7 +126,6 @@
if (changed) {
filter.invalidateList("onNewSmartspaceTargets")
- notificationEntryManager.updateNotifications("Smartspace targets changed")
}
trackedSmartspaceTargets = newMap
@@ -169,7 +162,6 @@
target.cancelTimeoutRunnable = null
target.shouldFilter = true
filter.invalidateList("updateAlertException: ${entry.logKey}")
- notificationEntryManager.updateNotifications("deduping timeout expired")
}, alertExceptionExpires - now)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
index 46b467e..cdfd2f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
@@ -16,16 +16,14 @@
package com.android.systemui.statusbar.notification.collection.inflation;
-import android.annotation.Nullable;
+import android.annotation.NonNull;
-import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.InflationException;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder;
/**
- * Used by the {@link NotificationEntryManager}. When notifications are added or updated, the binder
+ * Used by the {@link NotifInflater}. When notifications are added or updated, the binder
* is asked to (re)inflate and prepare their views. This inflation must occur off the main thread.
*/
public interface NotificationRowBinder {
@@ -35,23 +33,11 @@
*/
void inflateViews(
NotificationEntry entry,
- NotifInflater.Params params,
+ @NonNull NotifInflater.Params params,
NotificationRowContentBinder.InflationCallback callback)
throws InflationException;
/**
- * Called when the ranking has been updated (but not add or remove has been done). The binder
- * should inspect the old and new adjustments and re-inflate the entry's views if necessary
- * (e.g. if something important changed).
- */
- void onNotificationRankingUpdated(
- NotificationEntry entry,
- @Nullable Integer oldImportance,
- NotificationUiAdjustment oldAdjustment,
- NotificationUiAdjustment newAdjustment,
- NotificationRowContentBinder.InflationCallback callback);
-
- /**
* Called when a notification is no longer likely to be displayed and can have its views freed.
*/
void releaseViews(NotificationEntry entry);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 528f720..47cdde4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -22,6 +22,7 @@
import static java.util.Objects.requireNonNull;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.os.Build;
@@ -32,12 +33,9 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.InflationException;
-import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.legacy.LowPriorityInflationHelper;
import com.android.systemui.statusbar.notification.icon.IconManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
@@ -68,8 +66,6 @@
private final ExpandableNotificationRowComponent.Builder
mExpandableNotificationRowComponentBuilder;
private final IconManager mIconManager;
- private final LowPriorityInflationHelper mLowPriorityInflationHelper;
- private final NotifPipelineFlags mNotifPipelineFlags;
private NotificationPresenter mPresenter;
private NotificationListContainer mListContainer;
@@ -86,9 +82,7 @@
RowContentBindStage rowContentBindStage,
Provider<RowInflaterTask> rowInflaterTaskProvider,
ExpandableNotificationRowComponent.Builder expandableNotificationRowComponentBuilder,
- IconManager iconManager,
- LowPriorityInflationHelper lowPriorityInflationHelper,
- NotifPipelineFlags notifPipelineFlags) {
+ IconManager iconManager) {
mContext = context;
mNotifBindPipeline = notifBindPipeline;
mRowContentBindStage = rowContentBindStage;
@@ -98,8 +92,6 @@
mRowInflaterTaskProvider = rowInflaterTaskProvider;
mExpandableNotificationRowComponentBuilder = expandableNotificationRowComponentBuilder;
mIconManager = iconManager;
- mLowPriorityInflationHelper = lowPriorityInflationHelper;
- mNotifPipelineFlags = notifPipelineFlags;
}
/**
@@ -125,13 +117,9 @@
@Override
public void inflateViews(
NotificationEntry entry,
- NotifInflater.Params params,
+ @NonNull NotifInflater.Params params,
NotificationRowContentBinder.InflationCallback callback)
throws InflationException {
- if (params == null) {
- // weak assert that the params should always be passed in the new pipeline
- mNotifPipelineFlags.checkLegacyPipelineEnabled();
- }
ViewGroup parent = mListContainer.getViewParentForNotification(entry);
if (entry.rowExists()) {
@@ -191,39 +179,6 @@
}
/**
- * Updates the views bound to an entry when the entry's ranking changes, either in-place or by
- * reinflating them.
- *
- * TODO: Should this method be in this class?
- */
- @Override
- public void onNotificationRankingUpdated(
- NotificationEntry entry,
- @Nullable Integer oldImportance,
- NotificationUiAdjustment oldAdjustment,
- NotificationUiAdjustment newAdjustment,
- NotificationRowContentBinder.InflationCallback callback) {
- mNotifPipelineFlags.checkLegacyPipelineEnabled();
- if (NotificationUiAdjustment.needReinflate(oldAdjustment, newAdjustment)) {
- if (entry.rowExists()) {
- ExpandableNotificationRow row = entry.getRow();
- row.reset();
- updateRow(entry, row);
- inflateContentViews(entry, null, row, callback);
- } else {
- // Once the RowInflaterTask is done, it will pick up the updated entry, so
- // no-op here.
- }
- } else {
- if (oldImportance != null && entry.getImportance() != oldImportance) {
- if (entry.rowExists()) {
- entry.getRow().onNotificationRankingUpdated();
- }
- }
- }
- }
-
- /**
* Update row after the notification has updated.
*
* @param entry notification that has updated
@@ -243,24 +198,12 @@
*/
private void inflateContentViews(
NotificationEntry entry,
- NotifInflater.Params inflaterParams,
+ @NonNull NotifInflater.Params inflaterParams,
ExpandableNotificationRow row,
@Nullable NotificationRowContentBinder.InflationCallback inflationCallback) {
final boolean useIncreasedCollapsedHeight =
mMessagingUtil.isImportantMessaging(entry.getSbn(), entry.getImportance());
- final boolean isLowPriority;
- if (inflaterParams != null) {
- // NEW pipeline
- isLowPriority = inflaterParams.isLowPriority();
- } else {
- // LEGACY pipeline
- mNotifPipelineFlags.checkLegacyPipelineEnabled();
- // If this is our first time inflating, we don't actually know the groupings for real
- // yet, so we might actually inflate a low priority content view incorrectly here and
- // have to correct it later in the pipeline. On subsequent inflations (i.e. updates),
- // this should inflate the correct view.
- isLowPriority = mLowPriorityInflationHelper.shouldUseLowPriorityView(entry);
- }
+ final boolean isLowPriority = inflaterParams.isLowPriority();
RowContentBindParams params = mRowContentBindStage.getStageParams(entry);
params.requireContentViews(FLAG_CONTENT_VIEW_CONTRACTED);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LowPriorityInflationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LowPriorityInflationHelper.java
deleted file mode 100644
index 89445a5..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LowPriorityInflationHelper.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2020 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.statusbar.notification.collection.legacy;
-
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.statusbar.notification.NotifPipelineFlags;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-
-import javax.inject.Inject;
-
-/**
- * Helper class that provide methods to help check when we need to inflate a low priority version
- * ot notification content.
- */
-@SysUISingleton
-public class LowPriorityInflationHelper {
- private final NotificationGroupManagerLegacy mGroupManager;
- private final NotifPipelineFlags mNotifPipelineFlags;
-
- @Inject
- LowPriorityInflationHelper(
- NotificationGroupManagerLegacy groupManager,
- NotifPipelineFlags notifPipelineFlags) {
- mGroupManager = groupManager;
- mNotifPipelineFlags = notifPipelineFlags;
- }
-
- /**
- * Whether the notification should inflate a low priority version of its content views.
- */
- public boolean shouldUseLowPriorityView(NotificationEntry entry) {
- mNotifPipelineFlags.checkLegacyPipelineEnabled();
- return entry.isAmbient() && !mGroupManager.isChildInGroup(entry);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
deleted file mode 100644
index d41f6fe..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
+++ /dev/null
@@ -1,950 +0,0 @@
-/*
- * Copyright (C) 2015 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.statusbar.notification.collection.legacy;
-
-import static com.android.systemui.statusbar.notification.NotificationUtils.logKey;
-
-import static java.util.Objects.requireNonNull;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Notification;
-import android.service.notification.StatusBarNotification;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager.OnGroupExpansionChangeListener;
-import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
-import com.android.systemui.util.Compile;
-import com.android.wm.shell.bubbles.Bubbles;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.TreeSet;
-import java.util.function.Function;
-
-import javax.inject.Inject;
-
-import dagger.Lazy;
-
-/**
- * A class to handle notifications and their corresponding groups.
- * This includes:
- * 1. Determining whether an entry is a member of a group and whether it is a summary or a child
- * 2. Tracking group expansion states
- */
-@SysUISingleton
-public class NotificationGroupManagerLegacy implements StateListener, Dumpable {
-
- private static final String TAG = "LegacyNotifGroupManager";
- private static final boolean DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG);
- private static final boolean SPEW = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE);
- /**
- * The maximum amount of time (in ms) between the posting of notifications that can be
- * considered part of the same update batch.
- */
- private static final long POST_BATCH_MAX_AGE = 5000;
- private final HashMap<String, NotificationGroup> mGroupMap = new HashMap<>();
- private final Lazy<PeopleNotificationIdentifier> mPeopleNotificationIdentifier;
- private final Optional<Bubbles> mBubblesOptional;
- private final GroupEventDispatcher mEventDispatcher = new GroupEventDispatcher(mGroupMap::get);
- private final HashMap<String, StatusBarNotification> mIsolatedEntries = new HashMap<>();
- private boolean mIsUpdatingUnchangedGroup;
-
- @Inject
- public NotificationGroupManagerLegacy(
- StatusBarStateController statusBarStateController,
- Lazy<PeopleNotificationIdentifier> peopleNotificationIdentifier,
- Optional<Bubbles> bubblesOptional,
- DumpManager dumpManager) {
- statusBarStateController.addCallback(this);
- mPeopleNotificationIdentifier = peopleNotificationIdentifier;
- mBubblesOptional = bubblesOptional;
-
- dumpManager.registerDumpable(this);
- }
-
- /**
- * Add a listener for changes to groups.
- */
- public void registerGroupChangeListener(OnGroupChangeListener listener) {
- mEventDispatcher.registerGroupChangeListener(listener);
- }
-
- private void setGroupExpanded(NotificationGroup group, boolean expanded) {
- group.expanded = expanded;
- }
-
- /**
- * When we want to remove an entry from being tracked for grouping
- */
- public void onEntryRemoved(NotificationEntry removed) {
- if (SPEW) {
- Log.d(TAG, "onEntryRemoved: entry=" + logKey(removed));
- }
- mEventDispatcher.openBufferScope();
- onEntryRemovedInternal(removed, removed.getSbn());
- StatusBarNotification oldSbn = mIsolatedEntries.remove(removed.getKey());
- if (oldSbn != null) {
- updateSuppression(mGroupMap.get(oldSbn.getGroupKey()));
- }
- mEventDispatcher.closeBufferScope();
- }
-
- /**
- * An entry was removed.
- *
- * @param removed the removed entry
- * @param sbn the notification the entry has, which doesn't need to be the same as it's internal
- * notification
- */
- private void onEntryRemovedInternal(NotificationEntry removed,
- final StatusBarNotification sbn) {
- onEntryRemovedInternal(removed, sbn.getGroupKey(), sbn.isGroup(),
- sbn.getNotification().isGroupSummary());
- }
-
- private void onEntryRemovedInternal(NotificationEntry removed, String notifGroupKey, boolean
- isGroup, boolean isGroupSummary) {
- String groupKey = getGroupKey(removed.getKey(), notifGroupKey);
- final NotificationGroup group = mGroupMap.get(groupKey);
- if (group == null) {
- // When an app posts 2 different notifications as summary of the same group, then a
- // cancellation of the first notification removes this group.
- // This situation is not supported and we will not allow such notifications anymore in
- // the close future. See b/23676310 for reference.
- return;
- }
- if (SPEW) {
- Log.d(TAG, "onEntryRemovedInternal: entry=" + logKey(removed)
- + " group=" + logGroupKey(group));
- }
- if (isGroupChild(removed.getKey(), isGroup, isGroupSummary)) {
- group.children.remove(removed.getKey());
- } else {
- group.summary = null;
- }
- updateSuppression(group);
- if (group.children.isEmpty()) {
- if (group.summary == null) {
- mGroupMap.remove(groupKey);
- mEventDispatcher.notifyGroupRemoved(group);
- }
- }
- }
-
- private void onEntryAddedInternal(final NotificationEntry added) {
- if (added.isRowRemoved()) {
- added.setDebugThrowable(new Throwable());
- }
- final StatusBarNotification sbn = added.getSbn();
- boolean isGroupChild = isGroupChild(sbn);
- String groupKey = getGroupKey(sbn);
- NotificationGroup group = mGroupMap.get(groupKey);
- if (group == null) {
- group = new NotificationGroup(groupKey);
- mGroupMap.put(groupKey, group);
- mEventDispatcher.notifyGroupCreated(group);
- }
- if (SPEW) {
- Log.d(TAG, "onEntryAddedInternal: entry=" + logKey(added)
- + " group=" + logGroupKey(group));
- }
- if (isGroupChild) {
- NotificationEntry existing = group.children.get(added.getKey());
- if (existing != null && existing != added) {
- Throwable existingThrowable = existing.getDebugThrowable();
- Log.wtf(TAG, "Inconsistent entries found with the same key " + logKey(added)
- + "existing removed: " + existing.isRowRemoved()
- + (existingThrowable != null
- ? Log.getStackTraceString(existingThrowable) + "\n" : "")
- + " added removed" + added.isRowRemoved(), new Throwable());
- }
- group.children.put(added.getKey(), added);
- addToPostBatchHistory(group, added);
- updateSuppression(group);
- } else {
- group.summary = added;
- addToPostBatchHistory(group, added);
- group.expanded = added.areChildrenExpanded();
- updateSuppression(group);
- if (!group.children.isEmpty()) {
- ArrayList<NotificationEntry> childrenCopy =
- new ArrayList<>(group.children.values());
- for (NotificationEntry child : childrenCopy) {
- onEntryBecomingChild(child);
- }
- mEventDispatcher.notifyGroupsChanged();
- }
- }
- }
-
- private void addToPostBatchHistory(NotificationGroup group, @Nullable NotificationEntry entry) {
- if (entry == null) {
- return;
- }
- boolean didAdd = group.postBatchHistory.add(new PostRecord(entry));
- if (didAdd) {
- trimPostBatchHistory(group.postBatchHistory);
- }
- }
-
- /** remove all history that's too old to be in the batch. */
- private void trimPostBatchHistory(@NonNull TreeSet<PostRecord> postBatchHistory) {
- if (postBatchHistory.size() <= 1) {
- return;
- }
- long batchStartTime = postBatchHistory.last().postTime - POST_BATCH_MAX_AGE;
- while (!postBatchHistory.isEmpty() && postBatchHistory.first().postTime < batchStartTime) {
- postBatchHistory.pollFirst();
- }
- }
-
- private void onEntryBecomingChild(NotificationEntry entry) {
- updateIsolation(entry);
- }
-
- private void updateSuppression(NotificationGroup group) {
- if (group == null) {
- return;
- }
- NotificationEntry prevAlertOverride = group.alertOverride;
- group.alertOverride = getPriorityConversationAlertOverride(group);
-
- int childCount = 0;
- boolean hasBubbles = false;
- for (NotificationEntry entry : group.children.values()) {
- if (mBubblesOptional.isPresent() && mBubblesOptional.get()
- .isBubbleNotificationSuppressedFromShade(
- entry.getKey(), entry.getSbn().getGroupKey())) {
- hasBubbles = true;
- } else {
- childCount++;
- }
- }
-
- boolean prevSuppressed = group.suppressed;
- group.suppressed = group.summary != null && !group.expanded
- && (childCount == 1
- || (childCount == 0
- && group.summary.getSbn().getNotification().isGroupSummary()
- && (hasIsolatedChildren(group) || hasBubbles)));
-
- boolean alertOverrideChanged = prevAlertOverride != group.alertOverride;
- boolean suppressionChanged = prevSuppressed != group.suppressed;
- if (alertOverrideChanged || suppressionChanged) {
- if (DEBUG) {
- Log.d(TAG, "updateSuppression:"
- + " willNotifyListeners=" + !mIsUpdatingUnchangedGroup
- + " changes for group:\n" + group);
- if (alertOverrideChanged) {
- Log.d(TAG, "updateSuppression: alertOverride was=" + logKey(prevAlertOverride)
- + " now=" + logKey(group.alertOverride));
- }
- if (suppressionChanged) {
- Log.d(TAG, "updateSuppression: suppressed changed to " + group.suppressed);
- }
- }
- if (alertOverrideChanged) {
- mEventDispatcher.notifyAlertOverrideChanged(group, prevAlertOverride);
- }
- if (suppressionChanged) {
- mEventDispatcher.notifySuppressedChanged(group);
- }
- if (!mIsUpdatingUnchangedGroup) {
- mEventDispatcher.notifyGroupsChanged();
- }
- }
- }
-
- /**
- * Finds the isolated logical child of this group which is should be alerted instead.
- *
- * Notifications from priority conversations are isolated from their groups to make them more
- * prominent, however apps may post these with a GroupAlertBehavior that has the group receiving
- * the alert. This would lead to the group alerting even though the conversation that was
- * updated was not actually a part of that group. This method finds the best priority
- * conversation in this situation, if there is one, so they can be set as the alertOverride of
- * the group.
- *
- * @param group the group to check
- * @return the entry which should receive the alert instead of the group, if any.
- */
- @Nullable
- private NotificationEntry getPriorityConversationAlertOverride(NotificationGroup group) {
- // GOAL: if there is a priority child which wouldn't alert based on its groupAlertBehavior,
- // but which should be alerting (because priority conversations are isolated), find it.
- if (group == null || group.summary == null) {
- if (SPEW) {
- Log.d(TAG, "getPriorityConversationAlertOverride: null group or summary"
- + " group=" + logGroupKey(group));
- }
- return null;
- }
- if (isIsolated(group.summary.getKey())) {
- if (SPEW) {
- Log.d(TAG, "getPriorityConversationAlertOverride: isolated group"
- + " group=" + logGroupKey(group));
- }
- return null;
- }
-
- // Precondiions:
- // * Only necessary when all notifications in the group use GROUP_ALERT_SUMMARY
- // * Only necessary when at least one notification in the group is on a priority channel
- if (group.summary.getSbn().getNotification().getGroupAlertBehavior()
- == Notification.GROUP_ALERT_CHILDREN) {
- if (SPEW) {
- Log.d(TAG, "getPriorityConversationAlertOverride: summary == GROUP_ALERT_CHILDREN"
- + " group=" + logGroupKey(group));
- }
- return null;
- }
-
- // Get the important children first, copy the keys for the final importance check,
- // then add the non-isolated children to the map for unified lookup.
- HashMap<String, NotificationEntry> children = getImportantConversations(group);
- if (children == null || children.isEmpty()) {
- if (SPEW) {
- Log.d(TAG, "getPriorityConversationAlertOverride: no important conversations"
- + " group=" + logGroupKey(group));
- }
- return null;
- }
- HashSet<String> importantChildKeys = new HashSet<>(children.keySet());
- children.putAll(group.children);
-
- // Ensure all children have GROUP_ALERT_SUMMARY
- for (NotificationEntry child : children.values()) {
- if (child.getSbn().getNotification().getGroupAlertBehavior()
- != Notification.GROUP_ALERT_SUMMARY) {
- if (SPEW) {
- Log.d(TAG, "getPriorityConversationAlertOverride: child != GROUP_ALERT_SUMMARY"
- + " group=" + logGroupKey(group));
- }
- return null;
- }
- }
-
- // Create a merged post history from all the children
- TreeSet<PostRecord> combinedHistory = new TreeSet<>(group.postBatchHistory);
- for (String importantChildKey : importantChildKeys) {
- NotificationGroup importantChildGroup = mGroupMap.get(importantChildKey);
- combinedHistory.addAll(importantChildGroup.postBatchHistory);
- }
- trimPostBatchHistory(combinedHistory);
-
- // This is a streamlined implementation of the following idea:
- // * From the subset of notifications in the latest 'batch' of updates. A batch is:
- // * Notifs posted less than POST_BATCH_MAX_AGE before the most recently posted.
- // * Only including notifs newer than the second-to-last post of any notification.
- // * Find the newest child in the batch -- the with the largest 'when' value.
- // * If the newest child is a priority conversation, set that as the override.
- HashSet<String> batchKeys = new HashSet<>();
- long newestChildWhen = -1;
- NotificationEntry newestChild = null;
- // Iterate backwards through the post history, tracking the child with the smallest sort key
- for (PostRecord record : combinedHistory.descendingSet()) {
- if (batchKeys.contains(record.key)) {
- // Once you see a notification again, the batch has ended
- break;
- }
- batchKeys.add(record.key);
- NotificationEntry child = children.get(record.key);
- if (child != null) {
- long childWhen = child.getSbn().getNotification().when;
- if (newestChild == null || childWhen > newestChildWhen) {
- newestChildWhen = childWhen;
- newestChild = child;
- }
- }
- }
- if (newestChild != null && importantChildKeys.contains(newestChild.getKey())) {
- if (SPEW) {
- Log.d(TAG, "getPriorityConversationAlertOverride:"
- + " result=" + logKey(newestChild)
- + " group=" + logGroupKey(group));
- }
- return newestChild;
- }
- if (SPEW) {
- Log.d(TAG, "getPriorityConversationAlertOverride:"
- + " result=null newestChild=" + logKey(newestChild)
- + " group=" + logGroupKey(group));
- }
- return null;
- }
-
- private boolean hasIsolatedChildren(NotificationGroup group) {
- return getNumberOfIsolatedChildren(group.summary.getSbn().getGroupKey()) != 0;
- }
-
- private int getNumberOfIsolatedChildren(String groupKey) {
- int count = 0;
- for (StatusBarNotification sbn : mIsolatedEntries.values()) {
- if (sbn.getGroupKey().equals(groupKey) && isIsolated(sbn.getKey())) {
- count++;
- }
- }
- return count;
- }
-
- @Nullable
- private HashMap<String, NotificationEntry> getImportantConversations(NotificationGroup group) {
- String groupKey = group.summary.getSbn().getGroupKey();
- HashMap<String, NotificationEntry> result = null;
- for (StatusBarNotification sbn : mIsolatedEntries.values()) {
- if (sbn.getGroupKey().equals(groupKey)) {
- NotificationEntry entry = mGroupMap.get(sbn.getKey()).summary;
- if (isImportantConversation(entry)) {
- if (result == null) {
- result = new HashMap<>();
- }
- result.put(sbn.getKey(), entry);
- }
- }
- }
- return result;
- }
-
- private void setStatusBarState(int newState) {
- if (newState == StatusBarState.KEYGUARD) {
- collapseGroups();
- }
- }
-
- private void collapseGroups() {
- // Because notifications can become isolated when the group becomes suppressed it can
- // lead to concurrent modifications while looping. We need to make a copy.
- ArrayList<NotificationGroup> groupCopy = new ArrayList<>(mGroupMap.values());
- int size = groupCopy.size();
- for (int i = 0; i < size; i++) {
- NotificationGroup group = groupCopy.get(i);
- if (group.expanded) {
- setGroupExpanded(group, false);
- }
- updateSuppression(group);
- }
- }
-
- public boolean isChildInGroup(NotificationEntry entry) {
- final StatusBarNotification sbn = entry.getSbn();
- if (!isGroupChild(sbn)) {
- return false;
- }
- NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
- if (group == null || group.summary == null || group.suppressed) {
- return false;
- }
- if (group.children.isEmpty()) {
- // If the suppression of a group changes because the last child was removed, this can
- // still be called temporarily because the child hasn't been fully removed yet. Let's
- // make sure we still return false in that case.
- return false;
- }
- return true;
- }
-
- /**
- * If there is a {@link NotificationGroup} associated with the provided entry, this method
- * will update the suppression of that group.
- */
- public void updateSuppression(NotificationEntry entry) {
- NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn()));
- if (group != null) {
- updateSuppression(group);
- }
- }
-
- /**
- * Get the group key. May differ from the one in the notification due to the notification
- * being temporarily isolated.
- *
- * @param sbn notification to check
- * @return the key of the notification
- */
- private String getGroupKey(StatusBarNotification sbn) {
- return getGroupKey(sbn.getKey(), sbn.getGroupKey());
- }
-
- private String getGroupKey(String key, String groupKey) {
- if (isIsolated(key)) {
- return key;
- }
- return groupKey;
- }
-
- private boolean isIsolated(String sbnKey) {
- return mIsolatedEntries.containsKey(sbnKey);
- }
-
- /**
- * Whether a notification is visually a group child.
- *
- * @param sbn notification to check
- * @return true if it is visually a group child
- */
- private boolean isGroupChild(StatusBarNotification sbn) {
- return isGroupChild(sbn.getKey(), sbn.isGroup(), sbn.getNotification().isGroupSummary());
- }
-
- private boolean isGroupChild(String key, boolean isGroup, boolean isGroupSummary) {
- if (isIsolated(key)) {
- return false;
- }
- return isGroup && !isGroupSummary;
- }
-
- /**
- * Whether a notification that is normally part of a group should be temporarily isolated from
- * the group and put in their own group visually. This generally happens when the notification
- * is alerting.
- *
- * @param entry the notification to check
- * @return true if the entry should be isolated
- */
- private boolean shouldIsolate(NotificationEntry entry) {
- StatusBarNotification sbn = entry.getSbn();
- if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
- return false;
- }
- if (isImportantConversation(entry)) {
- return true;
- }
- NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
- return (sbn.getNotification().fullScreenIntent != null
- || notificationGroup == null
- || !notificationGroup.expanded
- || isGroupNotFullyVisible(notificationGroup));
- }
-
- private boolean isImportantConversation(NotificationEntry entry) {
- int peopleNotificationType =
- mPeopleNotificationIdentifier.get().getPeopleNotificationType(entry);
- return peopleNotificationType == PeopleNotificationIdentifier.TYPE_IMPORTANT_PERSON;
- }
-
- /**
- * Isolate a notification from its group so that it visually shows as its own group.
- *
- * @param entry the notification to isolate
- */
- private void isolateNotification(NotificationEntry entry) {
- if (SPEW) {
- Log.d(TAG, "isolateNotification: entry=" + logKey(entry));
- }
- // We will be isolated now, so lets update the groups
- onEntryRemovedInternal(entry, entry.getSbn());
-
- mIsolatedEntries.put(entry.getKey(), entry.getSbn());
-
- onEntryAddedInternal(entry);
- // We also need to update the suppression of the old group, because this call comes
- // even before the groupManager knows about the notification at all.
- // When the notification gets added afterwards it is already isolated and therefore
- // it doesn't lead to an update.
- updateSuppression(mGroupMap.get(entry.getSbn().getGroupKey()));
- mEventDispatcher.notifyGroupsChanged();
- }
-
- /**
- * Update the isolation of an entry, splitting it from the group.
- */
- private void updateIsolation(NotificationEntry entry) {
- // We need to buffer a few events because we do isolation changes in 3 steps:
- // removeInternal, update mIsolatedEntries, addInternal. This means that often the
- // alertOverride will update on the removal, however processing the event in that case can
- // cause problems because the mIsolatedEntries map is not in its final state, so the event
- // listener may be unable to correctly determine the true state of the group. By delaying
- // the alertOverride change until after the add phase, we can ensure that listeners only
- // have to handle a consistent state.
- mEventDispatcher.openBufferScope();
- boolean isIsolated = isIsolated(entry.getSbn().getKey());
- if (shouldIsolate(entry)) {
- if (!isIsolated) {
- isolateNotification(entry);
- }
- } else if (isIsolated) {
- stopIsolatingNotification(entry);
- }
- mEventDispatcher.closeBufferScope();
- }
-
- /**
- * Stop isolating a notification and re-group it with its original logical group.
- *
- * @param entry the notification to un-isolate
- */
- private void stopIsolatingNotification(NotificationEntry entry) {
- if (SPEW) {
- Log.d(TAG, "stopIsolatingNotification: entry=" + logKey(entry));
- }
- // not isolated anymore, we need to update the groups
- onEntryRemovedInternal(entry, entry.getSbn());
- mIsolatedEntries.remove(entry.getKey());
- onEntryAddedInternal(entry);
- mEventDispatcher.notifyGroupsChanged();
- }
-
- private boolean isGroupNotFullyVisible(NotificationGroup notificationGroup) {
- return notificationGroup.summary == null
- || notificationGroup.summary.isGroupNotFullyVisible();
- }
-
- @Override
- public void dump(PrintWriter pw, String[] args) {
- pw.println("GroupManagerLegacy state:");
- pw.println(" number of groups: " + mGroupMap.size());
- for (Map.Entry<String, NotificationGroup> entry : mGroupMap.entrySet()) {
- pw.println("\n key: " + logKey(entry.getKey())); pw.println(entry.getValue());
- }
- pw.println("\n isolated entries: " + mIsolatedEntries.size());
- for (Map.Entry<String, StatusBarNotification> entry : mIsolatedEntries.entrySet()) {
- pw.print(" "); pw.print(logKey(entry.getKey()));
- pw.print(", "); pw.println(entry.getValue());
- }
- }
-
- @Override
- public void onStateChanged(int newState) {
- setStatusBarState(newState);
- }
-
- /** Get the group key, reformatted for logging, for the (optional) group */
- private static String logGroupKey(NotificationGroup group) {
- if (group == null) {
- return "null";
- }
- return logKey(group.groupKey);
- }
-
- /**
- * A record of a notification being posted, containing the time of the post and the key of the
- * notification entry. These are stored in a TreeSet by the NotificationGroup and used to
- * calculate a batch of notifications.
- */
- public static class PostRecord implements Comparable<PostRecord> {
- public final long postTime;
- public final String key;
-
- /** constructs a record containing the post time and key from the notification entry */
- public PostRecord(@NonNull NotificationEntry entry) {
- this.postTime = entry.getSbn().getPostTime();
- this.key = entry.getKey();
- }
-
- @Override
- public int compareTo(PostRecord o) {
- int postTimeComparison = Long.compare(this.postTime, o.postTime);
- return postTimeComparison == 0
- ? String.CASE_INSENSITIVE_ORDER.compare(this.key, o.key)
- : postTimeComparison;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- PostRecord that = (PostRecord) o;
- return postTime == that.postTime && key.equals(that.key);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(postTime, key);
- }
- }
-
- /**
- * Represents a notification group in the notification shade.
- */
- public static class NotificationGroup {
- public final String groupKey;
- public final HashMap<String, NotificationEntry> children = new HashMap<>();
- public final TreeSet<PostRecord> postBatchHistory = new TreeSet<>();
- public NotificationEntry summary;
- public boolean expanded;
- /**
- * Is this notification group suppressed, i.e its summary is hidden
- */
- public boolean suppressed;
- /**
- * The child (which is isolated from this group) to which the alert should be transferred,
- * due to priority conversations.
- */
- public NotificationEntry alertOverride;
-
- NotificationGroup(String groupKey) {
- this.groupKey = groupKey;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append(" groupKey: ").append(groupKey);
- sb.append("\n summary:");
- appendEntry(sb, summary);
- sb.append("\n children size: ").append(children.size());
- for (NotificationEntry child : children.values()) {
- appendEntry(sb, child);
- }
- sb.append("\n alertOverride:");
- appendEntry(sb, alertOverride);
- sb.append("\n summary suppressed: ").append(suppressed);
- return sb.toString();
- }
-
- private void appendEntry(StringBuilder sb, NotificationEntry entry) {
- sb.append("\n ").append(entry != null ? entry.getSbn() : "null");
- if (entry != null && entry.getDebugThrowable() != null) {
- sb.append(Log.getStackTraceString(entry.getDebugThrowable()));
- }
- }
- }
-
- /**
- * This class is a toggleable buffer for a subset of events of {@link OnGroupChangeListener}.
- * When buffering, instead of notifying the listeners it will set internal state that will allow
- * it to notify listeners of those events later
- */
- static class GroupEventDispatcher {
- private final Function<String, NotificationGroup> mGroupMapGetter;
- private final ArraySet<OnGroupChangeListener> mGroupChangeListeners = new ArraySet<>();
- private final HashMap<String, NotificationEntry> mOldAlertOverrideByGroup = new HashMap<>();
- private final HashMap<String, Boolean> mOldSuppressedByGroup = new HashMap<>();
- private int mBufferScopeDepth = 0;
- private boolean mDidGroupsChange = false;
-
- GroupEventDispatcher(Function<String, NotificationGroup> groupMapGetter) {
- mGroupMapGetter = requireNonNull(groupMapGetter);
- }
-
- void registerGroupChangeListener(OnGroupChangeListener listener) {
- mGroupChangeListeners.add(listener);
- }
-
- private boolean isBuffering() {
- return mBufferScopeDepth > 0;
- }
-
- void notifyAlertOverrideChanged(NotificationGroup group,
- NotificationEntry oldAlertOverride) {
- if (isBuffering()) {
- // The value in this map is the override before the event. If there is an entry
- // already in the map, then we are effectively coalescing two events, which means
- // we need to preserve the original initial value.
- if (!mOldAlertOverrideByGroup.containsKey(group.groupKey)) {
- mOldAlertOverrideByGroup.put(group.groupKey, oldAlertOverride);
- }
- } else {
- for (OnGroupChangeListener listener : mGroupChangeListeners) {
- listener.onGroupAlertOverrideChanged(group, oldAlertOverride,
- group.alertOverride);
- }
- }
- }
-
- void notifySuppressedChanged(NotificationGroup group) {
- if (isBuffering()) {
- // The value in this map is the 'suppressed' before the event. If there is a value
- // already in the map, then we are effectively coalescing two events, which means
- // we need to preserve the original initial value.
- mOldSuppressedByGroup.putIfAbsent(group.groupKey, !group.suppressed);
- } else {
- for (OnGroupChangeListener listener : mGroupChangeListeners) {
- listener.onGroupSuppressionChanged(group, group.suppressed);
- }
- }
- }
-
- void notifyGroupsChanged() {
- if (isBuffering()) {
- mDidGroupsChange = true;
- } else {
- for (OnGroupChangeListener listener : mGroupChangeListeners) {
- listener.onGroupsChanged();
- }
- }
- }
-
- void notifyGroupCreated(NotificationGroup group) {
- // NOTE: given how this event is used, it doesn't need to be buffered right now
- final String groupKey = group.groupKey;
- for (OnGroupChangeListener listener : mGroupChangeListeners) {
- listener.onGroupCreated(group, groupKey);
- }
- }
-
- void notifyGroupRemoved(NotificationGroup group) {
- // NOTE: given how this event is used, it doesn't need to be buffered right now
- final String groupKey = group.groupKey;
- for (OnGroupChangeListener listener : mGroupChangeListeners) {
- listener.onGroupRemoved(group, groupKey);
- }
- }
-
- void openBufferScope() {
- mBufferScopeDepth++;
- if (SPEW) {
- Log.d(TAG, "openBufferScope: scopeDepth=" + mBufferScopeDepth);
- }
- }
-
- void closeBufferScope() {
- mBufferScopeDepth--;
- if (SPEW) {
- Log.d(TAG, "closeBufferScope: scopeDepth=" + mBufferScopeDepth);
- }
- // Flush buffered events if the last buffer scope has closed
- if (!isBuffering()) {
- flushBuffer();
- }
- }
-
- private void flushBuffer() {
- if (SPEW) {
- Log.d(TAG, "flushBuffer: "
- + " suppressed.size=" + mOldSuppressedByGroup.size()
- + " alertOverride.size=" + mOldAlertOverrideByGroup.size()
- + " mDidGroupsChange=" + mDidGroupsChange);
- }
- // alert all group suppressed changes for groups that were not removed
- for (Map.Entry<String, Boolean> entry : mOldSuppressedByGroup.entrySet()) {
- NotificationGroup group = mGroupMapGetter.apply(entry.getKey());
- if (group == null) {
- // The group can be null if this suppressed changed before the group was
- // permanently removed, meaning that there's no guarantee that listeners will
- // that field clear.
- if (SPEW) {
- Log.d(TAG, "flushBuffer: suppressed:"
- + " cannot report for removed group: " + logKey(entry.getKey()));
- }
- continue;
- }
- boolean oldSuppressed = entry.getValue();
- if (group.suppressed == oldSuppressed) {
- // If the final suppressed equals the initial, it means we coalesced two
- // events which undid the change, so we can drop it entirely.
- if (SPEW) {
- Log.d(TAG, "flushBuffer: suppressed:"
- + " did not change for group: " + logKey(entry.getKey()));
- }
- continue;
- }
- notifySuppressedChanged(group);
- }
- mOldSuppressedByGroup.clear();
- // alert all group alert override changes for groups that were not removed
- for (Map.Entry<String, NotificationEntry> entry : mOldAlertOverrideByGroup.entrySet()) {
- NotificationGroup group = mGroupMapGetter.apply(entry.getKey());
- if (group == null) {
- // The group can be null if this alertOverride changed before the group was
- // permanently removed, meaning that there's no guarantee that listeners will
- // that field clear.
- if (SPEW) {
- Log.d(TAG, "flushBuffer: alertOverride:"
- + " cannot report for removed group: " + entry.getKey());
- }
- continue;
- }
- NotificationEntry oldAlertOverride = entry.getValue();
- if (group.alertOverride == oldAlertOverride) {
- // If the final alertOverride equals the initial, it means we coalesced two
- // events which undid the change, so we can drop it entirely.
- if (SPEW) {
- Log.d(TAG, "flushBuffer: alertOverride:"
- + " did not change for group: " + logKey(entry.getKey()));
- }
- continue;
- }
- notifyAlertOverrideChanged(group, oldAlertOverride);
- }
- mOldAlertOverrideByGroup.clear();
- // alert that groups changed
- if (mDidGroupsChange) {
- notifyGroupsChanged();
- mDidGroupsChange = false;
- }
- }
- }
-
- /**
- * Listener for group changes not including group expansion changes which are handled by
- * {@link OnGroupExpansionChangeListener}.
- */
- public interface OnGroupChangeListener {
- /**
- * A new group has been created.
- *
- * @param group the group that was created
- * @param groupKey the group's key
- */
- default void onGroupCreated(
- NotificationGroup group,
- String groupKey) {}
-
- /**
- * A group has been removed.
- *
- * @param group the group that was removed
- * @param groupKey the group's key
- */
- default void onGroupRemoved(
- NotificationGroup group,
- String groupKey) {}
-
- /**
- * The suppression of a group has changed.
- *
- * @param group the group that has changed
- * @param suppressed true if the group is now suppressed, false o/w
- */
- default void onGroupSuppressionChanged(
- NotificationGroup group,
- boolean suppressed) {}
-
- /**
- * The alert override of a group has changed.
- *
- * @param group the group that has changed
- * @param oldAlertOverride the previous notification to which the group's alerts were sent
- * @param newAlertOverride the notification to which the group's alerts should now be sent
- */
- default void onGroupAlertOverrideChanged(
- NotificationGroup group,
- @Nullable NotificationEntry oldAlertOverride,
- @Nullable NotificationEntry newAlertOverride) {}
-
- /**
- * The groups have changed. This can happen if the isolation of a child has changes or if a
- * group became suppressed / unsuppressed
- */
- default void onGroupsChanged() {}
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/VisualStabilityManager.java
deleted file mode 100644
index bb8c0e0..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/VisualStabilityManager.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2016 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.statusbar.notification.collection.legacy;
-
-import com.android.systemui.keyguard.WakefulnessLifecycle;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
-import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
-
-/**
- * A manager that ensures that notifications are visually stable. It will suppress reorderings
- * and reorder at the right time when they are out of view.
- */
-public class VisualStabilityManager {
-
- private final VisualStabilityProvider mVisualStabilityProvider;
-
- private boolean mPanelExpanded;
- private boolean mScreenOn;
- private boolean mPulsing;
-
- /**
- * Injected constructor. See {@link NotificationsModule}.
- */
- public VisualStabilityManager(
- VisualStabilityProvider visualStabilityProvider,
- StatusBarStateController statusBarStateController,
- WakefulnessLifecycle wakefulnessLifecycle) {
-
- mVisualStabilityProvider = visualStabilityProvider;
-
- if (statusBarStateController != null) {
- setPulsing(statusBarStateController.isPulsing());
- statusBarStateController.addCallback(new StatusBarStateController.StateListener() {
- @Override
- public void onPulsingChanged(boolean pulsing) {
- setPulsing(pulsing);
- }
-
- @Override
- public void onExpandedChanged(boolean expanded) {
- setPanelExpanded(expanded);
- }
- });
- }
-
- if (wakefulnessLifecycle != null) {
- wakefulnessLifecycle.addObserver(mWakefulnessObserver);
- }
- }
-
- /**
- * @param screenOn whether the screen is on
- */
- private void setScreenOn(boolean screenOn) {
- mScreenOn = screenOn;
- updateAllowedStates();
- }
-
- /**
- * Set the panel to be expanded.
- */
- private void setPanelExpanded(boolean expanded) {
- mPanelExpanded = expanded;
- updateAllowedStates();
- }
-
- /**
- * @param pulsing whether we are currently pulsing for ambient display.
- */
- private void setPulsing(boolean pulsing) {
- if (mPulsing == pulsing) {
- return;
- }
- mPulsing = pulsing;
- updateAllowedStates();
- }
-
- private void updateAllowedStates() {
- boolean reorderingAllowed = (!mScreenOn || !mPanelExpanded) && !mPulsing;
- mVisualStabilityProvider.setReorderingAllowed(reorderingAllowed);
- }
-
- final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
- @Override
- public void onFinishedGoingToSleep() {
- setScreenOn(false);
- }
-
- @Override
- public void onStartedWakingUp() {
- setScreenOn(true);
- }
- };
-
-
- /**
- * See {@link Callback#onChangeAllowed()}
- */
- public interface Callback {
-
- /**
- * Called when changing is allowed again.
- */
- void onChangeAllowed();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollection.java
index 4ff6a64..fc7d682 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollection.java
@@ -19,7 +19,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -29,9 +28,8 @@
* A notification collection that manages the list of {@link NotificationEntry}s that will be
* rendered.
*
- * TODO: (b/145659174) Once we fully switch off {@link NotificationEntryManager} to
- * {@link NotifPipeline}, we probably won't need this, but having it for now makes it easy to
- * switch between the two.
+ * TODO: (b/145659174) Once we fully migrate to {@link NotifPipeline}, we probably won't need this,
+ * but having it for now makes it easy to switch between the two.
*/
public interface CommonNotifCollection {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTracker.kt
new file mode 100644
index 0000000..8bce5b0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTracker.kt
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.notifcollection
+
+import android.service.notification.NotificationListenerService.RankingMap
+import android.util.ArrayMap
+import com.android.internal.annotations.VisibleForTesting
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import java.io.PrintWriter
+
+class NotifCollectionInconsistencyTracker(val logger: NotifCollectionLogger) {
+ fun attach(
+ collectedKeySetAccessor: () -> Set<String>,
+ coalescedKeySetAccessor: () -> Set<String>,
+ ) {
+ if (attached) {
+ throw RuntimeException("attach() called twice")
+ }
+ attached = true
+ this.collectedKeySetAccessor = collectedKeySetAccessor
+ this.coalescedKeySetAccessor = coalescedKeySetAccessor
+ }
+
+ fun logNewMissingNotifications(rankingMap: RankingMap) {
+ val currentCollectedKeys = collectedKeySetAccessor()
+ val currentCoalescedKeys = coalescedKeySetAccessor()
+ val newMissingNotifications = rankingMap.orderedKeys.asSequence()
+ .filter { it !in currentCollectedKeys }
+ .filter { it !in currentCoalescedKeys }
+ .toSet()
+ maybeLogMissingNotifications(missingNotifications, newMissingNotifications)
+ missingNotifications = newMissingNotifications
+ }
+
+ @VisibleForTesting
+ fun maybeLogMissingNotifications(
+ oldMissingKeys: Set<String>,
+ newMissingKeys: Set<String>,
+ ) {
+ if (oldMissingKeys.isEmpty() && newMissingKeys.isEmpty()) return
+ if (oldMissingKeys == newMissingKeys) return
+ (oldMissingKeys - newMissingKeys).sorted().let { justFound ->
+ if (justFound.isNotEmpty()) {
+ logger.logFoundNotifications(justFound, newMissingKeys.size)
+ }
+ }
+ (newMissingKeys - oldMissingKeys).sorted().let { goneMissing ->
+ if (goneMissing.isNotEmpty()) {
+ logger.logMissingNotifications(goneMissing, newMissingKeys.size)
+ }
+ }
+ }
+
+ fun logNewInconsistentRankings(
+ currentEntriesWithoutRankings: ArrayMap<String, NotificationEntry>?,
+ rankingMap: RankingMap,
+ ) {
+ maybeLogInconsistentRankings(
+ notificationsWithoutRankings,
+ currentEntriesWithoutRankings ?: emptyMap(),
+ rankingMap
+ )
+ notificationsWithoutRankings = currentEntriesWithoutRankings?.keys ?: emptySet()
+ }
+
+ @VisibleForTesting
+ fun maybeLogInconsistentRankings(
+ oldKeysWithoutRankings: Set<String>,
+ newEntriesWithoutRankings: Map<String, NotificationEntry>,
+ rankingMap: RankingMap,
+ ) {
+ if (oldKeysWithoutRankings.isEmpty() && newEntriesWithoutRankings.isEmpty()) return
+ if (oldKeysWithoutRankings == newEntriesWithoutRankings.keys) return
+ val newlyConsistent: List<String> = oldKeysWithoutRankings
+ .mapNotNull { key ->
+ key.takeIf { key !in newEntriesWithoutRankings }
+ .takeIf { key in rankingMap.orderedKeys }
+ }.sorted()
+ if (newlyConsistent.isNotEmpty()) {
+ val totalInconsistent: Int = newEntriesWithoutRankings.size
+ logger.logRecoveredRankings(newlyConsistent, totalInconsistent)
+ }
+ val newlyInconsistent: List<NotificationEntry> = newEntriesWithoutRankings
+ .mapNotNull { (key, entry) ->
+ entry.takeIf { key !in oldKeysWithoutRankings }
+ }.sortedBy { it.key }
+ if (newlyInconsistent.isNotEmpty()) {
+ val totalInconsistent: Int = newEntriesWithoutRankings.size
+ logger.logMissingRankings(newlyInconsistent, totalInconsistent, rankingMap)
+ }
+ }
+
+ fun dump(pw: PrintWriter) {
+ pw.println("notificationsWithoutRankings: ${notificationsWithoutRankings.size}")
+ for (key in notificationsWithoutRankings) {
+ pw.println("\t * : $key")
+ }
+ pw.println("missingNotifications: ${missingNotifications.size}")
+ for (key in missingNotifications) {
+ pw.println("\t * : $key")
+ }
+ }
+
+ private var attached: Boolean = false
+ private lateinit var collectedKeySetAccessor: (() -> Set<String>)
+ private lateinit var coalescedKeySetAccessor: (() -> Set<String>)
+ private var notificationsWithoutRankings = emptySet<String>()
+ private var missingNotifications = emptySet<String>()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
index ebcac6b..aa27e1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
@@ -215,8 +215,9 @@
})
}
- fun logRecoveredRankings(newlyConsistentKeys: List<String>) {
+ fun logRecoveredRankings(newlyConsistentKeys: List<String>, totalInconsistent: Int) {
buffer.log(TAG, INFO, {
+ int1 = totalInconsistent
int1 = newlyConsistentKeys.size
str1 = newlyConsistentKeys.joinToString { logKey(it) ?: "null" }
}, {
@@ -224,6 +225,32 @@
})
}
+ fun logMissingNotifications(
+ newlyMissingKeys: List<String>,
+ totalMissing: Int,
+ ) {
+ buffer.log(TAG, WARNING, {
+ int1 = totalMissing
+ int2 = newlyMissingKeys.size
+ str1 = newlyMissingKeys.joinToString { logKey(it) ?: "null" }
+ }, {
+ "Collection missing $int1 entries in ranking update. Just lost $int2: $str1"
+ })
+ }
+
+ fun logFoundNotifications(
+ newlyFoundKeys: List<String>,
+ totalMissing: Int,
+ ) {
+ buffer.log(TAG, INFO, {
+ int1 = totalMissing
+ int2 = newlyFoundKeys.size
+ str1 = newlyFoundKeys.joinToString { logKey(it) ?: "null" }
+ }, {
+ "Collection missing $int1 entries in ranking update. Just found $int2: $str1"
+ })
+ }
+
fun logRemoteExceptionOnNotificationClear(entry: NotificationEntry, e: RemoteException) {
buffer.log(TAG, WTF, {
str1 = entry.logKey
@@ -362,29 +389,4 @@
}
}
-fun maybeLogInconsistentRankings(
- logger: NotifCollectionLogger,
- oldKeysWithoutRankings: Set<String>,
- newEntriesWithoutRankings: Map<String, NotificationEntry>?,
- rankingMap: RankingMap
-) {
- if (oldKeysWithoutRankings.isEmpty() && newEntriesWithoutRankings == null) return
- val newlyConsistent: List<String> = oldKeysWithoutRankings
- .mapNotNull { key ->
- key.takeIf { key !in (newEntriesWithoutRankings ?: emptyMap()) }
- .takeIf { key in rankingMap.orderedKeys }
- }.sorted()
- if (newlyConsistent.isNotEmpty()) {
- logger.logRecoveredRankings(newlyConsistent)
- }
- val newlyInconsistent: List<NotificationEntry> = newEntriesWithoutRankings
- ?.mapNotNull { (key, entry) ->
- entry.takeIf { key !in oldKeysWithoutRankings }
- }?.sortedBy { it.key } ?: emptyList()
- if (newlyInconsistent.isNotEmpty()) {
- val totalInconsistent: Int = newEntriesWithoutRankings?.size ?: 0
- logger.logMissingRankings(newlyInconsistent, totalInconsistent, rankingMap)
- }
-}
-
private const val TAG = "NotifCollection"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index eda2eec..da4cced 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -24,24 +24,18 @@
import android.view.accessibility.AccessibilityManager;
import com.android.internal.logging.UiEventLogger;
-import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
-import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.settings.UserContextProvider;
import com.android.systemui.shade.NotifPanelEventsModule;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
-import com.android.systemui.statusbar.notification.NotifPipelineFlags;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreImpl;
@@ -53,12 +47,9 @@
import com.android.systemui.statusbar.notification.collection.inflation.BindEventManagerImpl;
import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.inflation.OnUserInteractionCallbackImpl;
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
-import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.collection.provider.NotificationVisibilityProviderImpl;
-import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
@@ -84,7 +75,6 @@
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.util.leak.LeakDetector;
import com.android.systemui.wmshell.BubblesManager;
import java.util.Optional;
@@ -114,22 +104,6 @@
@Binds
StackScrollAlgorithm.BypassController bindBypassController(KeyguardBypassController impl);
- /** Provides an instance of {@link NotificationEntryManager} */
- @SysUISingleton
- @Provides
- static NotificationEntryManager provideNotificationEntryManager(
- NotificationEntryManagerLogger logger,
- NotificationGroupManagerLegacy groupManager,
- NotifPipelineFlags notifPipelineFlags,
- Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
- LeakDetector leakDetector,
- IStatusBarService statusBarService,
- @Background Executor bgExecutor) {
- return new NotificationEntryManager(
- logger
- );
- }
-
/** Provides an instance of {@link NotificationGutsManager} */
@SysUISingleton
@Provides
@@ -141,7 +115,6 @@
AccessibilityManager accessibilityManager,
HighPriorityProvider highPriorityProvider,
INotificationManager notificationManager,
- NotificationEntryManager notificationEntryManager,
PeopleSpaceWidgetManager peopleSpaceWidgetManager,
LauncherApps launcherApps,
ShortcutManager shortcutManager,
@@ -177,20 +150,6 @@
@Binds
NotifGutsViewManager bindNotifGutsViewManager(NotificationGutsManager notificationGutsManager);
- /** Provides an instance of {@link VisualStabilityManager} */
- @SysUISingleton
- @Provides
- static VisualStabilityManager provideVisualStabilityManager(
- VisualStabilityProvider visualStabilityProvider,
- StatusBarStateController statusBarStateController,
- WakefulnessLifecycle wakefulnessLifecycle) {
- return new VisualStabilityManager(
- visualStabilityProvider,
- statusBarStateController,
- wakefulnessLifecycle
- );
- }
-
/** Provides an instance of {@link NotificationLogger} */
@SysUISingleton
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt
index 3dcd3cb..b2cb23b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt
@@ -23,7 +23,6 @@
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
import com.android.systemui.statusbar.notification.collection.render.NotifStackController
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
-import java.io.PrintWriter
/**
* The master controller for all notifications-related work
@@ -40,9 +39,7 @@
bindRowCallback: NotificationRowBinderImpl.BindRowCallback
)
- fun requestNotificationUpdate(reason: String)
fun resetUserExpandedStates()
fun setNotificationSnoozed(sbn: StatusBarNotification, snoozeOption: SnoozeOption)
fun getActiveNotificationsCount(): Int
- fun dump(pw: PrintWriter, args: Array<String>, dumpTruck: Boolean)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index 0e9f1cd..1aa0295 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.init
import android.service.notification.StatusBarNotification
+import com.android.systemui.ForegroundServiceNotificationListener
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.people.widget.PeopleSpaceWidgetManager
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption
@@ -25,23 +26,21 @@
import com.android.systemui.statusbar.notification.AnimatedImageNotificationManager
import com.android.systemui.statusbar.notification.NotificationActivityStarter
import com.android.systemui.statusbar.notification.NotificationClicker
-import com.android.systemui.statusbar.notification.NotificationEntryManager
-import com.android.systemui.statusbar.notification.NotificationListController
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore
import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.TargetSdkResolver
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.notification.collection.render.NotifStackController
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.statusbar.phone.CentralSurfaces
-import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.wm.shell.bubbles.Bubbles
import dagger.Lazy
-import java.io.PrintWriter
import java.util.Optional
import javax.inject.Inject
@@ -56,20 +55,19 @@
class NotificationsControllerImpl @Inject constructor(
private val centralSurfaces: Lazy<CentralSurfaces>,
private val notificationListener: NotificationListener,
- private val entryManager: NotificationEntryManager,
private val commonNotifCollection: Lazy<CommonNotifCollection>,
private val notifPipeline: Lazy<NotifPipeline>,
private val notifLiveDataStore: NotifLiveDataStore,
private val targetSdkResolver: TargetSdkResolver,
private val notifPipelineInitializer: Lazy<NotifPipelineInitializer>,
private val notifBindPipelineInitializer: NotifBindPipelineInitializer,
- private val deviceProvisionedController: DeviceProvisionedController,
private val notificationRowBinder: NotificationRowBinderImpl,
private val headsUpViewBinder: HeadsUpViewBinder,
private val clickerBuilder: NotificationClicker.Builder,
private val animatedImageNotificationManager: AnimatedImageNotificationManager,
private val peopleSpaceWidgetManager: PeopleSpaceWidgetManager,
private val bubblesOptional: Optional<Bubbles>,
+ private val fgsNotifListener: ForegroundServiceNotificationListener,
) : NotificationsController {
override fun initialize(
@@ -81,12 +79,11 @@
) {
notificationListener.registerAsSystemService()
- val listController =
- NotificationListController(
- entryManager,
- listContainer,
- deviceProvisionedController)
- listController.bind()
+ notifPipeline.get().addCollectionListener(object : NotifCollectionListener {
+ override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
+ listContainer.cleanUpViewStateForEntry(entry)
+ }
+ })
notificationRowBinder.setNotificationClicker(
clickerBuilder.build(
@@ -109,24 +106,11 @@
targetSdkResolver.initialize(notifPipeline.get())
peopleSpaceWidgetManager.attach(notificationListener)
- }
-
- override fun dump(
- pw: PrintWriter,
- args: Array<String>,
- dumpTruck: Boolean
- ) {
- if (dumpTruck) {
- entryManager.dump(pw, " ")
- }
+ fgsNotifListener.init()
}
// TODO: Convert all functions below this line into listeners instead of public methods
- override fun requestNotificationUpdate(reason: String) {
- entryManager.updateNotifications(reason)
- }
-
override fun resetUserExpandedStates() {
// TODO: this is a view thing that should be done through the views, but that means doing it
// both when this event is fired and any time a row is attached.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
index 10da0d2..744166d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
@@ -24,7 +24,6 @@
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
import com.android.systemui.statusbar.notification.collection.render.NotifStackController
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
-import java.io.PrintWriter
import javax.inject.Inject
/**
@@ -46,9 +45,6 @@
notificationListener.registerAsSystemService()
}
- override fun requestNotificationUpdate(reason: String) {
- }
-
override fun resetUserExpandedStates() {
}
@@ -58,14 +54,4 @@
override fun getActiveNotificationsCount(): Int {
return 0
}
-
- override fun dump(
- pw: PrintWriter,
- args: Array<String>,
- dumpTruck: Boolean
- ) {
- pw.println()
- pw.println("Notification handling disabled")
- pw.println()
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/NotificationPersonExtractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/NotificationPersonExtractor.kt
new file mode 100644
index 0000000..4cf3572
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/NotificationPersonExtractor.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.people
+
+import android.service.notification.StatusBarNotification
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.NotificationPersonExtractorPlugin
+import com.android.systemui.statusbar.policy.ExtensionController
+import javax.inject.Inject
+
+interface NotificationPersonExtractor {
+ fun isPersonNotification(sbn: StatusBarNotification): Boolean
+}
+
+@SysUISingleton
+class NotificationPersonExtractorPluginBoundary @Inject constructor(
+ extensionController: ExtensionController
+) : NotificationPersonExtractor {
+
+ private var plugin: NotificationPersonExtractorPlugin? = null
+
+ init {
+ plugin = extensionController
+ .newExtension(NotificationPersonExtractorPlugin::class.java)
+ .withPlugin(NotificationPersonExtractorPlugin::class.java)
+ .withCallback { extractor ->
+ plugin = extractor
+ }
+ .build()
+ .get()
+ }
+
+ override fun isPersonNotification(sbn: StatusBarNotification): Boolean =
+ plugin?.isPersonNotification(sbn) ?: false
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt
deleted file mode 100644
index 3af6ba8..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 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.statusbar.notification.people
-
-import android.graphics.drawable.Drawable
-
-/**
- * `ViewModel` for PeopleHub view.
- *
- * @param people ViewModels for individual people in PeopleHub, in order that they should be
- * displayed
- * @param isVisible Whether or not the whole PeopleHub UI is visible
- **/
-data class PeopleHubViewModel(val people: Sequence<PersonViewModel>, val isVisible: Boolean)
-
-/** `ViewModel` for a single "Person' in PeopleHub. */
-data class PersonViewModel(
- val name: CharSequence,
- val icon: Drawable,
- val onClick: () -> Unit
-)
-
-/**
- * `Model` for PeopleHub.
- *
- * @param people Models for individual people in PeopleHub, in order that they should be displayed
- **/
-data class PeopleHubModel(val people: Collection<PersonModel>)
-
-/** `Model` for a single "Person" in PeopleHub. */
-data class PersonModel(
- val key: PersonKey,
- val userId: Int,
- // TODO: these should live in the ViewModel
- val name: CharSequence,
- val avatar: Drawable,
- val clickRunnable: Runnable
-)
-
-/** Unique identifier for a Person in PeopleHub. */
-typealias PersonKey = String
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
index 16574ab..c17ffb0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
@@ -21,25 +21,6 @@
@Module
abstract class PeopleHubModule {
-
- @Binds
- abstract fun peopleHubSectionFooterViewAdapter(
- impl: PeopleHubViewAdapterImpl
- ): PeopleHubViewAdapter
-
- @Binds
- abstract fun peopleHubDataSource(impl: PeopleHubDataSourceImpl): DataSource<PeopleHubModel>
-
- @Binds
- abstract fun peopleHubSettingChangeDataSource(
- impl: PeopleHubSettingChangeDataSourceImpl
- ): DataSource<Boolean>
-
- @Binds
- abstract fun peopleHubViewModelFactoryDataSource(
- impl: PeopleHubViewModelFactoryDataSourceImpl
- ): DataSource<PeopleHubViewModelFactory>
-
@Binds
abstract fun peopleNotificationIdentifier(
impl: PeopleNotificationIdentifierImpl
@@ -49,4 +30,4 @@
abstract fun notificationPersonExtractor(
pluginImpl: NotificationPersonExtractorPluginBoundary
): NotificationPersonExtractor
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
deleted file mode 100644
index 6062941..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (C) 2019 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.statusbar.notification.people
-
-import android.app.Notification
-import android.content.Context
-import android.content.pm.LauncherApps
-import android.content.pm.PackageManager
-import android.content.pm.UserInfo
-import android.graphics.drawable.Drawable
-import android.os.UserManager
-import android.service.notification.NotificationListenerService
-import android.service.notification.NotificationListenerService.REASON_SNOOZED
-import android.service.notification.StatusBarNotification
-import android.util.IconDrawableFactory
-import android.util.SparseArray
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import com.android.internal.widget.MessagingGroup
-import com.android.settingslib.notification.ConversationIconFactory
-import com.android.systemui.R
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.plugins.NotificationPersonExtractorPlugin
-import com.android.systemui.statusbar.NotificationListener
-import com.android.systemui.statusbar.NotificationLockscreenUserManager
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
-import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
-import com.android.systemui.statusbar.policy.ExtensionController
-import java.util.ArrayDeque
-import java.util.concurrent.Executor
-import javax.inject.Inject
-
-private const val MAX_STORED_INACTIVE_PEOPLE = 10
-
-interface NotificationPersonExtractor {
- fun extractPerson(sbn: StatusBarNotification): PersonModel?
- fun extractPersonKey(sbn: StatusBarNotification): String?
- fun isPersonNotification(sbn: StatusBarNotification): Boolean
-}
-
-@SysUISingleton
-class NotificationPersonExtractorPluginBoundary @Inject constructor(
- extensionController: ExtensionController
-) : NotificationPersonExtractor {
-
- private var plugin: NotificationPersonExtractorPlugin? = null
-
- init {
- plugin = extensionController
- .newExtension(NotificationPersonExtractorPlugin::class.java)
- .withPlugin(NotificationPersonExtractorPlugin::class.java)
- .withCallback { extractor ->
- plugin = extractor
- }
- .build()
- .get()
- }
-
- override fun extractPerson(sbn: StatusBarNotification) =
- plugin?.extractPerson(sbn)?.run {
- PersonModel(key, sbn.user.identifier, name, avatar, clickRunnable)
- }
-
- override fun extractPersonKey(sbn: StatusBarNotification) = plugin?.extractPersonKey(sbn)
-
- override fun isPersonNotification(sbn: StatusBarNotification): Boolean =
- plugin?.isPersonNotification(sbn) ?: false
-}
-
-@SysUISingleton
-class PeopleHubDataSourceImpl @Inject constructor(
- private val notifCollection: CommonNotifCollection,
- private val extractor: NotificationPersonExtractor,
- private val userManager: UserManager,
- launcherApps: LauncherApps,
- packageManager: PackageManager,
- context: Context,
- private val notificationListener: NotificationListener,
- @Background private val bgExecutor: Executor,
- @Main private val mainExecutor: Executor,
- private val notifLockscreenUserMgr: NotificationLockscreenUserManager,
- private val peopleNotificationIdentifier: PeopleNotificationIdentifier
-) : DataSource<PeopleHubModel> {
-
- private var userChangeSubscription: Subscription? = null
- private val dataListeners = mutableListOf<DataListener<PeopleHubModel>>()
- private val peopleHubManagerForUser = SparseArray<PeopleHubManager>()
-
- private val iconFactory = run {
- val appContext = context.applicationContext
- ConversationIconFactory(
- appContext,
- launcherApps,
- packageManager,
- IconDrawableFactory.newInstance(appContext),
- appContext.resources.getDimensionPixelSize(
- R.dimen.notification_guts_conversation_icon_size
- )
- )
- }
-
- private val notifCollectionListener = object : NotifCollectionListener {
- override fun onEntryAdded(entry: NotificationEntry) = addVisibleEntry(entry)
- override fun onEntryUpdated(entry: NotificationEntry) = addVisibleEntry(entry)
- override fun onEntryRemoved(entry: NotificationEntry, reason: Int) =
- removeVisibleEntry(entry, reason)
- }
-
- private fun removeVisibleEntry(entry: NotificationEntry, reason: Int) {
- (extractor.extractPersonKey(entry.sbn) ?: entry.extractPersonKey())?.let { key ->
- val userId = entry.sbn.user.identifier
- bgExecutor.execute {
- val parentId = userManager.getProfileParent(userId)?.id ?: userId
- mainExecutor.execute {
- if (reason == REASON_SNOOZED) {
- if (peopleHubManagerForUser[parentId]?.migrateActivePerson(key) == true) {
- updateUi()
- }
- } else {
- peopleHubManagerForUser[parentId]?.removeActivePerson(key)
- }
- }
- }
- }
- }
-
- private fun addVisibleEntry(entry: NotificationEntry) {
- entry.extractPerson()?.let { personModel ->
- val userId = entry.sbn.user.identifier
- bgExecutor.execute {
- val parentId = userManager.getProfileParent(userId)?.id ?: userId
- mainExecutor.execute {
- val manager = peopleHubManagerForUser[parentId]
- ?: PeopleHubManager().also { peopleHubManagerForUser.put(parentId, it) }
- if (manager.addActivePerson(personModel)) {
- updateUi()
- }
- }
- }
- }
- }
-
- override fun registerListener(listener: DataListener<PeopleHubModel>): Subscription {
- val register = dataListeners.isEmpty()
- dataListeners.add(listener)
- if (register) {
- userChangeSubscription = notifLockscreenUserMgr.registerListener(
- object : NotificationLockscreenUserManager.UserChangedListener {
- override fun onUserChanged(userId: Int) = updateUi()
- override fun onCurrentProfilesChanged(
- currentProfiles: SparseArray<UserInfo>?
- ) = updateUi()
- })
- notifCollection.addCollectionListener(notifCollectionListener)
- } else {
- getPeopleHubModelForCurrentUser()?.let(listener::onDataChanged)
- }
- return object : Subscription {
- override fun unsubscribe() {
- dataListeners.remove(listener)
- if (dataListeners.isEmpty()) {
- userChangeSubscription?.unsubscribe()
- userChangeSubscription = null
- notifCollection.removeCollectionListener(notifCollectionListener)
- }
- }
- }
- }
-
- private fun getPeopleHubModelForCurrentUser(): PeopleHubModel? {
- val currentUserId = notifLockscreenUserMgr.currentUserId
- val model = peopleHubManagerForUser[currentUserId]?.getPeopleHubModel()
- ?: return null
- val currentProfiles = notifLockscreenUserMgr.currentProfiles
- return model.copy(people = model.people.filter { person ->
- currentProfiles[person.userId]?.isQuietModeEnabled == false
- })
- }
-
- private fun updateUi() {
- val model = getPeopleHubModelForCurrentUser() ?: return
- for (listener in dataListeners) {
- listener.onDataChanged(model)
- }
- }
-
- private fun NotificationEntry.extractPerson(): PersonModel? {
- val type = peopleNotificationIdentifier.getPeopleNotificationType(this)
- if (type == TYPE_NON_PERSON) {
- return null
- }
- val clickRunnable = Runnable { notificationListener.unsnoozeNotification(key) }
- val extras = sbn.notification.extras
- val name = ranking.conversationShortcutInfo?.label
- ?: extras.getCharSequence(Notification.EXTRA_CONVERSATION_TITLE)
- ?: extras.getCharSequence(Notification.EXTRA_TITLE)
- ?: return null
- val drawable = ranking.getIcon(iconFactory, sbn)
- ?: iconFactory.getConversationDrawable(
- extractAvatarFromRow(this),
- sbn.packageName,
- sbn.uid,
- ranking.channel.isImportantConversation
- )
- return PersonModel(key, sbn.user.identifier, name, drawable, clickRunnable)
- }
-
- private fun NotificationListenerService.Ranking.getIcon(
- iconFactory: ConversationIconFactory,
- sbn: StatusBarNotification
- ): Drawable? =
- conversationShortcutInfo?.let { conversationShortcutInfo ->
- iconFactory.getConversationDrawable(
- conversationShortcutInfo,
- sbn.packageName,
- sbn.uid,
- channel.isImportantConversation
- )
- }
-
- private fun NotificationEntry.extractPersonKey(): PersonKey? {
- // TODO migrate to shortcut id when snoozing is conversation wide
- val type = peopleNotificationIdentifier.getPeopleNotificationType(this)
- return if (type != TYPE_NON_PERSON) key else null
- }
-}
-
-private fun NotificationLockscreenUserManager.registerListener(
- listener: NotificationLockscreenUserManager.UserChangedListener
-): Subscription {
- addUserChangedListener(listener)
- return object : Subscription {
- override fun unsubscribe() {
- removeUserChangedListener(listener)
- }
- }
-}
-
-class PeopleHubManager {
-
- // People currently visible in the notification shade, and so are not in the hub
- private val activePeople = mutableMapOf<PersonKey, PersonModel>()
-
- // People that were once "active" and have been dismissed, and so can be displayed in the hub
- private val inactivePeople = ArrayDeque<PersonModel>(MAX_STORED_INACTIVE_PEOPLE)
-
- fun migrateActivePerson(key: PersonKey): Boolean {
- activePeople.remove(key)?.let { data ->
- if (inactivePeople.size >= MAX_STORED_INACTIVE_PEOPLE) {
- inactivePeople.removeLast()
- }
- inactivePeople.addFirst(data)
- return true
- }
- return false
- }
-
- fun removeActivePerson(key: PersonKey) {
- activePeople.remove(key)
- }
-
- fun addActivePerson(person: PersonModel): Boolean {
- activePeople[person.key] = person
- return inactivePeople.removeIf { it.key == person.key }
- }
-
- fun getPeopleHubModel(): PeopleHubModel = PeopleHubModel(inactivePeople)
-}
-
-private val ViewGroup.children
- get(): Sequence<View> = sequence {
- for (i in 0 until childCount) {
- yield(getChildAt(i))
- }
- }
-
-private fun ViewGroup.childrenWithId(id: Int): Sequence<View> = children.filter { it.id == id }
-
-fun extractAvatarFromRow(entry: NotificationEntry): Drawable? =
- entry.row
- ?.childrenWithId(R.id.expanded)
- ?.mapNotNull { it as? ViewGroup }
- ?.flatMap {
- it.childrenWithId(com.android.internal.R.id.status_bar_latest_event_content)
- }
- ?.mapNotNull {
- it.findViewById<ViewGroup>(com.android.internal.R.id.notification_messaging)
- }
- ?.mapNotNull { messagesView ->
- messagesView.children
- .mapNotNull { it as? MessagingGroup }
- .lastOrNull()
- ?.findViewById<ImageView>(com.android.internal.R.id.message_icon)
- ?.drawable
- }
- ?.firstOrNull()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
deleted file mode 100644
index 55bd77f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2019 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.statusbar.notification.people
-
-import android.content.Context
-import android.database.ContentObserver
-import android.net.Uri
-import android.os.Handler
-import android.os.UserHandle
-import android.provider.Settings
-import android.view.View
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.plugins.ActivityStarter
-import javax.inject.Inject
-
-/** Boundary between the View and PeopleHub, as seen by the View. */
-interface PeopleHubViewAdapter {
- fun bindView(viewBoundary: PeopleHubViewBoundary): Subscription
-}
-
-/** Abstract `View` representation of PeopleHub. */
-interface PeopleHubViewBoundary {
- /** View used for animating the activity launch caused by clicking a person in the hub. */
- val associatedViewForClickAnimation: View
-
- /**
- * [DataListener]s for individual people in the hub.
- *
- * These listeners should be ordered such that the first element will be bound to the most
- * recent person to be added to the hub, and then continuing in descending order. If there are
- * not enough people to satisfy each listener, `null` will be passed instead, indicating that
- * the `View` should render a placeholder.
- */
- val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
-
- /** Sets the visibility of the Hub in the notification shade. */
- fun setVisible(isVisible: Boolean)
-}
-
-/** Creates a [PeopleHubViewModel] given some additional information required from the `View`. */
-interface PeopleHubViewModelFactory {
-
- /**
- * Creates a [PeopleHubViewModel] that, when clicked, starts an activity using an animation
- * involving the given [view].
- */
- fun createWithAssociatedClickView(view: View): PeopleHubViewModel
-}
-
-/**
- * Wraps a [PeopleHubViewBoundary] in a [DataListener], and connects it to the data
- * pipeline.
- *
- * @param dataSource PeopleHub data pipeline.
- */
-@SysUISingleton
-class PeopleHubViewAdapterImpl @Inject constructor(
- private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubViewModelFactory>
-) : PeopleHubViewAdapter {
-
- override fun bindView(viewBoundary: PeopleHubViewBoundary): Subscription =
- dataSource.registerListener(PeopleHubDataListenerImpl(viewBoundary))
-}
-
-private class PeopleHubDataListenerImpl(
- private val viewBoundary: PeopleHubViewBoundary
-) : DataListener<PeopleHubViewModelFactory> {
-
- override fun onDataChanged(data: PeopleHubViewModelFactory) {
- val viewModel = data.createWithAssociatedClickView(
- viewBoundary.associatedViewForClickAnimation
- )
- viewBoundary.setVisible(viewModel.isVisible)
- val padded = viewModel.people + repeated(null)
- for ((adapter, model) in viewBoundary.personViewAdapters.zip(padded)) {
- adapter.onDataChanged(model)
- }
- }
-}
-
-/**
- * Converts [PeopleHubModel]s into [PeopleHubViewModelFactory]s.
- *
- * This class serves as the glue between the View layer (which depends on
- * [PeopleHubViewBoundary]) and the Data layer (which produces [PeopleHubModel]s).
- */
-@SysUISingleton
-class PeopleHubViewModelFactoryDataSourceImpl @Inject constructor(
- private val activityStarter: ActivityStarter,
- private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubModel>
-) : DataSource<PeopleHubViewModelFactory> {
-
- override fun registerListener(listener: DataListener<PeopleHubViewModelFactory>): Subscription {
- var model: PeopleHubModel? = null
-
- fun updateListener() {
- // don't invoke listener until we've received our first model
- model?.let { model ->
- val factory = PeopleHubViewModelFactoryImpl(model, activityStarter)
- listener.onDataChanged(factory)
- }
- }
- val dataSub = dataSource.registerListener(object : DataListener<PeopleHubModel> {
- override fun onDataChanged(data: PeopleHubModel) {
- model = data
- updateListener()
- }
- })
- return object : Subscription {
- override fun unsubscribe() {
- dataSub.unsubscribe()
- }
- }
- }
-}
-
-private object EmptyViewModelFactory : PeopleHubViewModelFactory {
- override fun createWithAssociatedClickView(view: View): PeopleHubViewModel {
- return PeopleHubViewModel(emptySequence(), false)
- }
-}
-
-private class PeopleHubViewModelFactoryImpl(
- private val model: PeopleHubModel,
- private val activityStarter: ActivityStarter
-) : PeopleHubViewModelFactory {
-
- override fun createWithAssociatedClickView(view: View): PeopleHubViewModel {
- val personViewModels = model.people.asSequence().map { personModel ->
- val onClick = {
- personModel.clickRunnable.run()
- }
- PersonViewModel(personModel.name, personModel.avatar, onClick)
- }
- return PeopleHubViewModel(personViewModels, model.people.isNotEmpty())
- }
-}
-
-@SysUISingleton
-class PeopleHubSettingChangeDataSourceImpl @Inject constructor(
- @Main private val handler: Handler,
- context: Context
-) : DataSource<Boolean> {
-
- private val settingUri = Settings.Secure.getUriFor(Settings.Secure.PEOPLE_STRIP)
- private val contentResolver = context.contentResolver
-
- override fun registerListener(listener: DataListener<Boolean>): Subscription {
- // Immediately report current value of setting
- updateListener(listener)
- val observer = object : ContentObserver(handler) {
- override fun onChange(selfChange: Boolean, uri: Uri?, flags: Int) {
- super.onChange(selfChange, uri, flags)
- updateListener(listener)
- }
- }
- contentResolver.registerContentObserver(settingUri, false, observer, UserHandle.USER_ALL)
- return object : Subscription {
- override fun unsubscribe() = contentResolver.unregisterContentObserver(observer)
- }
- }
-
- private fun updateListener(listener: DataListener<Boolean>) {
- val setting = Settings.Secure.getIntForUser(
- contentResolver,
- Settings.Secure.PEOPLE_STRIP,
- 0,
- UserHandle.USER_CURRENT
- )
- listener.onDataChanged(setting != 0)
- }
-}
-
-private fun <T> repeated(value: T): Sequence<T> = sequence {
- while (true) {
- yield(value)
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 9ad906c..6138265 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -20,14 +20,11 @@
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
-import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -69,6 +66,9 @@
import android.widget.FrameLayout;
import android.widget.ImageView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -236,11 +236,6 @@
*/
private boolean mIsHeadsUp;
- /**
- * Whether or not the notification should be redacted on the lock screen, i.e has sensitive
- * content which should be redacted on the lock screen.
- */
- private boolean mNeedsRedaction;
private boolean mLastChronometerRunning = true;
private ViewStub mChildrenContainerStub;
private GroupMembershipManager mGroupMembershipManager;
@@ -1502,23 +1497,6 @@
mUseIncreasedHeadsUpHeight = use;
}
- /** @deprecated TODO: Remove this when the old pipeline code is removed. */
- @Deprecated
- public void setNeedsRedaction(boolean needsRedaction) {
- if (mNeedsRedaction != needsRedaction) {
- mNeedsRedaction = needsRedaction;
- if (!isRemoved()) {
- RowContentBindParams params = mRowContentBindStage.getStageParams(mEntry);
- if (needsRedaction) {
- params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC);
- } else {
- params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC);
- }
- mRowContentBindStage.requestRebind(mEntry, null /* callback */);
- }
- }
- }
-
public interface ExpansionLogger {
void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
@@ -3270,6 +3248,7 @@
}
@Override
+ @NonNull
public ExpandableViewState createExpandableViewState() {
return new NotificationViewState();
}
@@ -3476,6 +3455,8 @@
pw.print("visibility: " + getVisibility());
pw.print(", alpha: " + getAlpha());
pw.print(", translation: " + getTranslation());
+ pw.print(", Entry isDismissable: " + mEntry.isDismissable());
+ pw.print(", mOnUserInteractionCallback null: " + (mOnUserInteractionCallback == null));
pw.print(", removed: " + isRemoved());
pw.print(", expandAnimationRunning: " + mExpandAnimationRunning);
NotificationContentView showingLayout = getShowingLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 8f73b80..1e09b8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -29,6 +29,7 @@
import android.view.ViewParent;
import android.widget.FrameLayout;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.systemui.Dumpable;
@@ -66,7 +67,7 @@
protected float mContentTransformationAmount;
protected boolean mIsLastChild;
protected int mContentShift;
- private final ExpandableViewState mViewState;
+ @NonNull private final ExpandableViewState mViewState;
private float mContentTranslation;
protected boolean mLastInSection;
protected boolean mFirstInSection;
@@ -610,6 +611,7 @@
public void setActualHeightAnimating(boolean animating) {}
+ @NonNull
protected ExpandableViewState createExpandableViewState() {
return new ExpandableViewState();
}
@@ -642,7 +644,12 @@
return mViewState;
}
- @Nullable public ExpandableViewState getViewState() {
+ /**
+ * Get the {@link ExpandableViewState} associated with the view.
+ *
+ * @return the ExpandableView's view state.
+ */
+ @NonNull public ExpandableViewState getViewState() {
return mViewState;
}
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 e43ecf7..49dc655 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
@@ -23,6 +23,8 @@
import android.util.IndentingPrintWriter;
import android.view.View;
+import androidx.annotation.NonNull;
+
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.ViewState;
@@ -142,6 +144,7 @@
}
@Override
+ @NonNull
public ExpandableViewState createExpandableViewState() {
return new FooterViewState();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
deleted file mode 100644
index 6abfee9..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2018 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.statusbar.notification.row;
-
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-
-import android.content.Context;
-import android.metrics.LogMaker;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
-import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
-import com.android.systemui.statusbar.notification.logging.NotificationCounters;
-import com.android.systemui.util.Compile;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Manager for the notification blocking helper - tracks and helps create the blocking helper
- * affordance.
- */
-public class NotificationBlockingHelperManager {
- /** Enables debug logging and always makes the blocking helper show up after a dismiss. */
- private static final String TAG = "BlockingHelper";
- private static final boolean DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG);
- private static final boolean DEBUG_ALWAYS_SHOW = false;
-
- private final Context mContext;
- private final NotificationGutsManager mNotificationGutsManager;
- private final NotificationEntryManager mNotificationEntryManager;
- private final MetricsLogger mMetricsLogger;
- private final GroupMembershipManager mGroupMembershipManager;
- /** Row that the blocking helper will be shown in (via {@link NotificationGuts}. */
- private ExpandableNotificationRow mBlockingHelperRow;
- private Set<String> mNonBlockablePkgs;
-
- /**
- * Whether the notification shade/stack is expanded - used to determine blocking helper
- * eligibility.
- */
- private boolean mIsShadeExpanded;
-
- /**
- * Injected constructor. See {@link NotificationsModule}.
- */
- public NotificationBlockingHelperManager(
- Context context,
- NotificationGutsManager notificationGutsManager,
- NotificationEntryManager notificationEntryManager,
- MetricsLogger metricsLogger,
- GroupMembershipManager groupMembershipManager) {
- mContext = context;
- mNotificationGutsManager = notificationGutsManager;
- mNotificationEntryManager = notificationEntryManager;
- mMetricsLogger = metricsLogger;
- mNonBlockablePkgs = new HashSet<>();
- Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray(
- com.android.internal.R.array.config_nonBlockableNotificationPackages));
- mGroupMembershipManager = groupMembershipManager;
- }
-
- /**
- * Potentially shows the blocking helper, represented via the {@link NotificationInfo} menu
- * item, in the current row if user sentiment is negative.
- *
- * @param row row to render the blocking helper in
- * @param menuRow menu used to generate the {@link NotificationInfo} view that houses the
- * blocking helper UI
- * @return whether we're showing a blocking helper in the given notification row
- */
- boolean perhapsShowBlockingHelper(
- ExpandableNotificationRow row, NotificationMenuRowPlugin menuRow) {
- // We only show the blocking helper if:
- // - User sentiment is negative (DEBUG flag can bypass)
- // - The notification shade is fully expanded (guarantees we're not touching a HUN).
- // - The row is blockable (i.e. not non-blockable)
- // - The dismissed row is a valid group (>1 or 0 children from the same channel)
- // or the only child in the group
- final NotificationEntry entry = row.getEntry();
- if ((entry.getUserSentiment() == USER_SENTIMENT_NEGATIVE || DEBUG_ALWAYS_SHOW)
- && mIsShadeExpanded
- && !row.getIsNonblockable()
- && ((!row.isChildInGroup() || mGroupMembershipManager.isOnlyChildInGroup(entry))
- && row.getNumUniqueChannels() <= 1)) {
- // Dismiss any current blocking helper before continuing forward (only one can be shown
- // at a given time).
- dismissCurrentBlockingHelper();
-
- if (DEBUG) {
- Log.d(TAG, "Manager.perhapsShowBlockingHelper: Showing new blocking helper");
- }
-
- // Enable blocking helper on the row before moving forward so everything in the guts is
- // correctly prepped.
- mBlockingHelperRow = row;
- mBlockingHelperRow.setBlockingHelperShowing(true);
-
- // Log triggering of blocking helper by the system. This log line
- // should be emitted before the "display" log line.
- mMetricsLogger.write(
- getLogMaker().setSubtype(MetricsEvent.BLOCKING_HELPER_TRIGGERED_BY_SYSTEM));
-
- // We don't care about the touch origin (x, y) since we're opening guts without any
- // explicit user interaction.
- mNotificationGutsManager.openGuts(
- mBlockingHelperRow, 0, 0, menuRow.getLongpressMenuItem(mContext));
-
- mMetricsLogger.count(NotificationCounters.BLOCKING_HELPER_SHOWN, 1);
- return true;
- }
- return false;
- }
-
- /**
- * Dismiss the currently showing blocking helper, if any, through a notification update.
- *
- * @return whether the blocking helper was dismissed
- */
- boolean dismissCurrentBlockingHelper() {
- if (!isBlockingHelperRowNull()) {
- if (DEBUG) {
- Log.d(TAG, "Manager.dismissCurrentBlockingHelper: Dismissing current helper");
- }
- if (!mBlockingHelperRow.isBlockingHelperShowing()) {
- Log.e(TAG, "Manager.dismissCurrentBlockingHelper: "
- + "Non-null row is not showing a blocking helper");
- }
-
- mBlockingHelperRow.setBlockingHelperShowing(false);
- if (mBlockingHelperRow.isAttachedToWindow()) {
- mNotificationEntryManager.updateNotifications("dismissCurrentBlockingHelper");
- }
- mBlockingHelperRow = null;
- return true;
- }
- return false;
- }
-
- /**
- * Update the expansion status of the notification shade/stack.
- *
- * @param expandedHeight how much the shade is expanded ({code 0} indicating it's collapsed)
- */
- public void setNotificationShadeExpanded(float expandedHeight) {
- mIsShadeExpanded = expandedHeight > 0.0f;
- }
-
- /**
- * Returns whether the given package name is in the list of non-blockable packages.
- */
- public boolean isNonblockable(String packageName, String channelName) {
- return mNonBlockablePkgs.contains(packageName)
- || mNonBlockablePkgs.contains(makeChannelKey(packageName, channelName));
- }
-
- private LogMaker getLogMaker() {
- return mBlockingHelperRow.getEntry().getSbn()
- .getLogMaker()
- .setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER);
- }
-
- // Format must stay in sync with frameworks/base/core/res/res/values/config.xml
- // config_nonBlockableNotificationPackages
- private String makeChannelKey(String pkg, String channel) {
- return pkg + ":" + channel;
- }
-
- @VisibleForTesting
- boolean isBlockingHelperRowNull() {
- return mBlockingHelperRow == null;
- }
-
- @VisibleForTesting
- void setBlockingHelperRowForTest(ExpandableNotificationRow blockingHelperRowForTest) {
- mBlockingHelperRow = blockingHelperRowForTest;
- }
-
- @VisibleForTesting
- void setNonBlockablePkgs(String[] pkgsAndChannels) {
- mNonBlockablePkgs = new HashSet<>();
- Collections.addAll(mNonBlockablePkgs, pkgsAndChannels);
- }
-}
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 79d883b3..1fb265f 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
@@ -4460,8 +4460,7 @@
}
private void updateVisibility() {
- boolean shouldShow = !mAmbientState.isFullyHidden() || !onKeyguard();
- setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
+ mController.updateVisibility(!mAmbientState.isFullyHidden() || !onKeyguard());
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
@@ -4526,17 +4525,21 @@
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- void updateEmptyShadeView(boolean visible, boolean notifVisibleInShade) {
+ void updateEmptyShadeView(boolean visible, boolean areNotificationsHiddenInShade) {
mEmptyShadeView.setVisible(visible, mIsExpanded && mAnimationsEnabled);
int oldTextRes = mEmptyShadeView.getTextResource();
- int newTextRes = notifVisibleInShade
+ int newTextRes = areNotificationsHiddenInShade
? R.string.dnd_suppressing_shade_text : R.string.empty_shade_text;
if (oldTextRes != newTextRes) {
mEmptyShadeView.setText(newTextRes);
}
}
+ public boolean isEmptyShadeViewVisible() {
+ return mEmptyShadeView.isVisible();
+ }
+
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void updateFooterView(boolean visible, boolean showDismissView, boolean showHistory) {
if (mFooterView == null) {
@@ -6116,9 +6119,6 @@
}
return row.canViewBeDismissed();
}
- if (v instanceof PeopleHubView) {
- return ((PeopleHubView) v).getCanSwipe();
- }
return false;
}
@@ -6130,9 +6130,6 @@
}
return row.canViewBeCleared();
}
- if (v instanceof PeopleHubView) {
- return ((PeopleHubView) v).getCanSwipe();
- }
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 3f6586c..843a9ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -81,14 +81,11 @@
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.PipelineDumpable;
import com.android.systemui.statusbar.notification.collection.PipelineDumper;
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.OnGroupChangeListener;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
@@ -157,7 +154,6 @@
private final ScrimController mScrimController;
private final NotifPipeline mNotifPipeline;
private final NotifCollection mNotifCollection;
- private final NotificationEntryManager mNotificationEntryManager;
private final UiEventLogger mUiEventLogger;
private final NotificationRemoteInputManager mRemoteInputManager;
private final ShadeController mShadeController;
@@ -179,7 +175,6 @@
private NotificationStackScrollLayout mView;
private boolean mFadeNotificationsOnDismiss;
private NotificationSwipeHelper mSwipeHelper;
- private boolean mShowEmptyShadeView;
@Nullable private Boolean mHistoryEnabled;
private int mBarState;
private HeadsUpAppearanceController mHeadsUpAppearanceController;
@@ -310,7 +305,6 @@
mView.updateSensitiveness(mStatusBarStateController.goingToFullShade(),
mLockscreenUserManager.isAnyProfilePublicMode());
mView.onStatePostChange(mStatusBarStateController.fromShadeLocked());
- mNotificationEntryManager.updateNotifications("CentralSurfaces state changed");
}
};
@@ -633,12 +627,10 @@
NotificationSwipeHelper.Builder notificationSwipeHelperBuilder,
CentralSurfaces centralSurfaces,
ScrimController scrimController,
- NotificationGroupManagerLegacy legacyGroupManager,
GroupExpansionManager groupManager,
@SilentHeader SectionHeaderController silentHeaderController,
NotifPipeline notifPipeline,
NotifCollection notifCollection,
- NotificationEntryManager notificationEntryManager,
LockscreenShadeTransitionController lockscreenShadeTransitionController,
ShadeTransitionController shadeTransitionController,
UiEventLogger uiEventLogger,
@@ -677,16 +669,9 @@
mJankMonitor = jankMonitor;
mNotificationStackSizeCalculator = notificationStackSizeCalculator;
mGroupExpansionManager = groupManager;
- legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() {
- @Override
- public void onGroupsChanged() {
- mCentralSurfaces.requestNotificationUpdate("onGroupsChanged");
- }
- });
mSilentHeaderController = silentHeaderController;
mNotifPipeline = notifPipeline;
mNotifCollection = notifCollection;
- mNotificationEntryManager = notificationEntryManager;
mUiEventLogger = uiEventLogger;
mRemoteInputManager = remoteInputManager;
mShadeController = shadeController;
@@ -1182,8 +1167,21 @@
}
/**
- * Update whether we should show the empty shade view (no notifications in the shade).
- * If so, send the update to our view.
+ * Set the visibility of the view, and propagate it to specific children.
+ *
+ * @param visible either the view is visible or not.
+ */
+ public void updateVisibility(boolean visible) {
+ mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+
+ if (mView.getVisibility() == View.VISIBLE) {
+ // Synchronize EmptyShadeView visibility with the parent container.
+ updateShowEmptyShadeView();
+ }
+ }
+
+ /**
+ * Update whether we should show the empty shade view ("no notifications" in the shade).
*
* When in split mode, notifications are always visible regardless of the state of the
* QuickSettings panel. That being the case, empty view is always shown if the other conditions
@@ -1191,18 +1189,31 @@
*/
public void updateShowEmptyShadeView() {
Trace.beginSection("NSSLC.updateShowEmptyShadeView");
- mShowEmptyShadeView = mStatusBarStateController.getCurrentOrUpcomingState() != KEYGUARD
- && !mView.isQsFullScreen()
- && getVisibleNotificationCount() == 0;
- mView.updateEmptyShadeView(
- mShowEmptyShadeView,
- mZenModeController.areNotificationsHiddenInShade());
+ final boolean shouldShow = getVisibleNotificationCount() == 0
+ && !mView.isQsFullScreen()
+ // Hide empty shade view when in transition to Keyguard.
+ // That avoids "No Notifications" to blink when transitioning to AOD.
+ // For more details, see: b/228790482
+ && !isInTransitionToKeyguard();
+
+ mView.updateEmptyShadeView(shouldShow, mZenModeController.areNotificationsHiddenInShade());
+
Trace.endSection();
}
+ /**
+ * @return true if {@link StatusBarStateController} is in transition to the KEYGUARD
+ * and false otherwise.
+ */
+ private boolean isInTransitionToKeyguard() {
+ final int currentState = mStatusBarStateController.getState();
+ final int upcomingState = mStatusBarStateController.getCurrentOrUpcomingState();
+ return (currentState != upcomingState && upcomingState == KEYGUARD);
+ }
+
public boolean isShowingEmptyShadeView() {
- return mShowEmptyShadeView;
+ return mView.isEmptyShadeViewVisible();
}
public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
deleted file mode 100644
index b13e7fb..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2019 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.statusbar.notification.stack
-
-import android.annotation.ColorInt
-import android.content.Context
-import android.util.AttributeSet
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.TextView
-import com.android.systemui.R
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin
-import com.android.systemui.statusbar.notification.people.DataListener
-import com.android.systemui.statusbar.notification.people.PersonViewModel
-import com.android.systemui.statusbar.notification.row.StackScrollerDecorView
-
-class PeopleHubView(context: Context, attrs: AttributeSet) :
- StackScrollerDecorView(context, attrs), SwipeableView {
-
- private lateinit var contents: ViewGroup
- private lateinit var label: TextView
-
- lateinit var personViewAdapters: Sequence<DataListener<PersonViewModel?>>
- private set
-
- override fun onFinishInflate() {
- contents = requireViewById(R.id.people_list)
- label = requireViewById(R.id.header_label)
- personViewAdapters = (0 until contents.childCount)
- .asSequence() // so we can map
- .mapNotNull { idx ->
- // get all our people slots
- (contents.getChildAt(idx) as? ImageView)?.let(::PersonDataListenerImpl)
- }
- .toList() // cache it
- .asSequence() // but don't reveal it's a list
- super.onFinishInflate()
- setVisible(true /* nowVisible */, false /* animate */)
- }
-
- fun setTextColor(@ColorInt color: Int) = label.setTextColor(color)
-
- override fun findContentView(): View = contents
- override fun findSecondaryView(): View? = null
-
- override fun hasFinishedInitialization(): Boolean = true
-
- override fun createMenu(): NotificationMenuRowPlugin? = null
-
- override fun resetTranslation() {
- translationX = 0f
- }
-
- override fun setTranslation(translation: Float) {
- if (canSwipe) {
- super.setTranslation(translation)
- }
- }
-
- var canSwipe: Boolean = false
- set(value) {
- if (field != value) {
- if (field) {
- resetTranslation()
- }
- field = value
- }
- }
-
- override fun needsClippingToShelf(): Boolean = true
-
- override fun applyContentTransformation(contentAlpha: Float, translationY: Float) {
- super.applyContentTransformation(contentAlpha, translationY)
- for (i in 0 until contents.childCount) {
- val view = contents.getChildAt(i)
- view.alpha = contentAlpha
- view.translationY = translationY
- }
- }
-
- fun setOnHeaderClickListener(listener: OnClickListener) = label.setOnClickListener(listener)
-
- private inner class PersonDataListenerImpl(val avatarView: ImageView) :
- DataListener<PersonViewModel?> {
-
- override fun onDataChanged(data: PersonViewModel?) {
- avatarView.visibility = data?.let { View.VISIBLE } ?: View.GONE
- avatarView.setImageDrawable(data?.icon)
- avatarView.setOnClickListener { data?.onClick?.invoke() }
- }
- }
-}
\ No newline at end of file
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 6d513d0da..353355b 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
@@ -120,11 +120,64 @@
updateClipping(algorithmState, ambientState);
updateSpeedBumpState(algorithmState, speedBumpIndex);
updateShelfState(algorithmState, ambientState);
+ updateAlphaState(algorithmState, ambientState);
getNotificationChildrenStates(algorithmState, ambientState);
}
+ private void updateAlphaState(StackScrollAlgorithmState algorithmState,
+ AmbientState ambientState) {
+ for (ExpandableView view : algorithmState.visibleChildren) {
+ final ViewState viewState = view.getViewState();
+
+ final boolean isHunGoingToShade = ambientState.isShadeExpanded()
+ && view == ambientState.getTrackedHeadsUpRow();
+
+ if (isHunGoingToShade) {
+ // Keep 100% opacity for heads up notification going to shade.
+ viewState.alpha = 1f;
+ } else if (ambientState.isOnKeyguard()) {
+ // Adjust alpha for wakeup to lockscreen.
+ viewState.alpha = 1f - ambientState.getHideAmount();
+ } else if (ambientState.isExpansionChanging()) {
+ // Adjust alpha for shade open & close.
+ float expansion = ambientState.getExpansionFraction();
+ viewState.alpha = ambientState.isBouncerInTransit()
+ ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
+ : ShadeInterpolation.getContentAlpha(expansion);
+ }
+
+ // For EmptyShadeView if on keyguard, we need to control the alpha to create
+ // a nice transition when the user is dragging down the notification panel.
+ if (view instanceof EmptyShadeView && ambientState.isOnKeyguard()) {
+ final float fractionToShade = ambientState.getFractionToShade();
+ viewState.alpha = ShadeInterpolation.getContentAlpha(fractionToShade);
+ }
+
+ NotificationShelf shelf = ambientState.getShelf();
+ if (shelf != null) {
+ final ViewState shelfState = shelf.getViewState();
+
+ // After the shelf has updated its yTranslation, explicitly set alpha=0 for view
+ // below shelf to skip rendering them in the hardware layer. We do not set them
+ // invisible because that runs invalidate & onDraw when these views return onscreen,
+ // which is more expensive.
+ if (shelfState.hidden) {
+ // When the shelf is hidden, it won't clip views, so we don't hide rows
+ return;
+ }
+
+ final float shelfTop = shelfState.yTranslation;
+ final float viewTop = viewState.yTranslation;
+ if (viewTop >= shelfTop) {
+ viewState.alpha = 0;
+ }
+ }
+ }
+ }
+
/**
* How expanded or collapsed notifications are when pulling down the shade.
+ *
* @param ambientState Current ambient state.
* @return 0 when fully collapsed, 1 when expanded.
*/
@@ -208,22 +261,6 @@
}
shelf.updateState(algorithmState, ambientState);
-
- // After the shelf has updated its yTranslation, explicitly set alpha=0 for view below shelf
- // to skip rendering them in the hardware layer. We do not set them invisible because that
- // runs invalidate & onDraw when these views return onscreen, which is more expensive.
- if (shelf.getViewState().hidden) {
- // When the shelf is hidden, it won't clip views, so we don't hide rows
- return;
- }
- final float shelfTop = shelf.getViewState().yTranslation;
-
- for (ExpandableView view : algorithmState.visibleChildren) {
- final float viewTop = view.getViewState().yTranslation;
- if (viewTop >= shelfTop) {
- view.getViewState().alpha = 0;
- }
- }
}
private void updateClipping(StackScrollAlgorithmState algorithmState,
@@ -473,21 +510,6 @@
ExpandableViewState viewState = view.getViewState();
viewState.location = ExpandableViewState.LOCATION_UNKNOWN;
- final boolean isHunGoingToShade = ambientState.isShadeExpanded()
- && view == ambientState.getTrackedHeadsUpRow();
- if (isHunGoingToShade) {
- // Keep 100% opacity for heads up notification going to shade.
- } else if (ambientState.isOnKeyguard()) {
- // Adjust alpha for wakeup to lockscreen.
- viewState.alpha = 1f - ambientState.getHideAmount();
- } else if (ambientState.isExpansionChanging()) {
- // Adjust alpha for shade open & close.
- float expansion = ambientState.getExpansionFraction();
- viewState.alpha = ambientState.isBouncerInTransit()
- ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
- : ShadeInterpolation.getContentAlpha(expansion);
- }
-
final float expansionFraction = getExpansionFractionWithoutShelf(
algorithmState, ambientState);
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 e754d5d..8bd7886 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -23,6 +23,7 @@
import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricSourceType;
+import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.metrics.LogMaker;
import android.os.Handler;
@@ -64,7 +65,6 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -87,7 +87,7 @@
private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl();
- private static final int FP_ATTEMPTS_BEFORE_SHOW_BOUNCER = 2;
+ private static final int UDFPS_ATTEMPTS_BEFORE_SHOW_BOUNCER = 3;
private static final VibrationEffect SUCCESS_VIBRATION_EFFECT =
VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
private static final VibrationEffect ERROR_VIBRATION_EFFECT =
@@ -450,7 +450,7 @@
// During wake and unlock, we need to draw black before waking up to avoid abrupt
// brightness changes due to display state transitions.
Runnable wakeUp = ()-> {
- if (!wasDeviceInteractive) {
+ if (!wasDeviceInteractive || mUpdateMonitor.isDreaming()) {
if (DEBUG_BIO_WAKELOCK) {
Log.i(TAG, "bio wakelock: Authenticated, waking up...");
}
@@ -662,7 +662,7 @@
if (!mVibratorHelper.hasVibrator()
&& (!mUpdateMonitor.isDeviceInteractive() || mUpdateMonitor.isDreaming())) {
- startWakeAndUnlock(MODE_SHOW_BOUNCER);
+ startWakeAndUnlock(MODE_ONLY_WAKE);
} else if (biometricSourceType == BiometricSourceType.FINGERPRINT
&& mUpdateMonitor.isUdfpsSupported()) {
long currUptimeMillis = SystemClock.uptimeMillis();
@@ -673,7 +673,7 @@
}
mLastFpFailureUptimeMillis = currUptimeMillis;
- if (mNumConsecutiveFpFailures >= FP_ATTEMPTS_BEFORE_SHOW_BOUNCER) {
+ if (mNumConsecutiveFpFailures >= UDFPS_ATTEMPTS_BEFORE_SHOW_BOUNCER) {
startWakeAndUnlock(MODE_SHOW_BOUNCER);
UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN, getSessionId());
mNumConsecutiveFpFailures = 0;
@@ -699,13 +699,13 @@
Optional.ofNullable(BiometricUiEvent.ERROR_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
.ifPresent(event -> UI_EVENT_LOGGER.log(event, getSessionId()));
- // if we're on the shade and we're locked out, immediately show the bouncer
- if (biometricSourceType == BiometricSourceType.FINGERPRINT
+ final boolean fingerprintLockout = biometricSourceType == BiometricSourceType.FINGERPRINT
&& (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT
- || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT)
- && mUpdateMonitor.isUdfpsSupported()
- && (mStatusBarStateController.getState() == StatusBarState.SHADE
- || mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED)) {
+ || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT);
+ final boolean faceLockout = biometricSourceType == BiometricSourceType.FACE
+ && (msgId == FaceManager.FACE_ERROR_LOCKOUT
+ || msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT);
+ if (fingerprintLockout || faceLockout) {
startWakeAndUnlock(MODE_SHOW_BOUNCER);
UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN, getSessionId());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index 5a80508..d1b2974 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -225,8 +225,6 @@
boolean isShadeDisabled();
- void requestNotificationUpdate(String reason);
-
void requestFaceAuth(boolean userInitiatedRequest);
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index 747c4de..52a45d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -55,7 +55,6 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.qs.QSPanelController;
-import com.android.systemui.shade.NotificationPanelView;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.CommandQueue;
@@ -326,12 +325,12 @@
mNotificationPanelViewController.expand(true /* animate */);
mNotificationStackScrollLayoutController.setWillExpand(true);
mHeadsUpManager.unpinAll(true /* userUnpinned */);
- mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN, 1);
+ mMetricsLogger.count("panel_open", 1);
} else if (!mNotificationPanelViewController.isInSettings()
&& !mNotificationPanelViewController.isExpanding()) {
mNotificationPanelViewController.flingSettings(0 /* velocity */,
- NotificationPanelView.FLING_EXPAND);
- mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN_QS, 1);
+ NotificationPanelViewController.FLING_EXPAND);
+ mMetricsLogger.count("panel_open_qs", 1);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 08b1c19..df6e545 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -203,7 +203,6 @@
import com.android.systemui.statusbar.core.StatusBarInitializer;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.init.NotificationsController;
@@ -508,7 +507,6 @@
private boolean mExpandedVisible;
- protected final NotificationEntryManager mEntryManager;
private final NotificationGutsManager mGutsManager;
private final NotificationLogger mNotificationLogger;
private final PanelExpansionStateManager mPanelExpansionStateManager;
@@ -681,7 +679,6 @@
FalsingManager falsingManager,
FalsingCollector falsingCollector,
BroadcastDispatcher broadcastDispatcher,
- NotificationEntryManager notificationEntryManager,
NotificationGutsManager notificationGutsManager,
NotificationLogger notificationLogger,
NotificationInterruptStateProvider notificationInterruptStateProvider,
@@ -768,7 +765,6 @@
mFalsingCollector = falsingCollector;
mFalsingManager = falsingManager;
mBroadcastDispatcher = broadcastDispatcher;
- mEntryManager = notificationEntryManager;
mGutsManager = notificationGutsManager;
mNotificationLogger = notificationLogger;
mNotificationInterruptStateProvider = notificationInterruptStateProvider;
@@ -839,11 +835,8 @@
mPanelExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged);
- mBubbleExpandListener =
- (isExpanding, key) -> mContext.getMainExecutor().execute(() -> {
- mNotificationsController.requestNotificationUpdate("onBubbleExpandChanged");
- updateScrimController();
- });
+ mBubbleExpandListener = (isExpanding, key) ->
+ mContext.getMainExecutor().execute(this::updateScrimController);
mActivityIntentHelper = new ActivityIntentHelper(mContext);
mActivityLaunchAnimator = activityLaunchAnimator;
@@ -1616,15 +1609,6 @@
}
/**
- * Request a notification update
- * @param reason why we're requesting a notification update
- */
- @Override
- public void requestNotificationUpdate(String reason) {
- mNotificationsController.requestNotificationUpdate(reason);
- }
-
- /**
* Asks {@link KeyguardUpdateMonitor} to run face auth.
*/
@Override
@@ -2328,8 +2312,6 @@
mStatusBarKeyguardViewManager.dump(pw);
}
- mNotificationsController.dump(pw, args, DUMPTRUCK);
-
if (DEBUG_GESTURES) {
pw.print(" status bar gestures: ");
mGestureRec.dump(pw, args);
@@ -4066,7 +4048,7 @@
final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback,
@Nullable ActivityLaunchAnimator.Controller animationController) {
final boolean willLaunchResolverActivity = intent.isActivity()
- && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
+ && mActivityIntentHelper.wouldPendingLaunchResolverActivity(intent,
mLockscreenUserManager.getCurrentUserId());
boolean animate = !willLaunchResolverActivity
@@ -4233,14 +4215,6 @@
maybeEscalateHeadsUp();
}
}
-
- // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
- // KeyguardCoordinator
- @Override
- public void onStrongAuthStateChanged(int userId) {
- super.onStrongAuthStateChanged(userId);
- mNotificationsController.requestNotificationUpdate("onStrongAuthStateChanged");
- }
};
@@ -4429,7 +4403,6 @@
updateQsExpansionEnabled();
mKeyguardViewMediator.setDozing(mDozing);
- mNotificationsController.requestNotificationUpdate("onDozingChanged");
updateDozingState();
mDozeServiceHost.updateDozing();
updateScrimController();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 51536c3..38c3f93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -21,14 +21,17 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Region;
+import android.os.Handler;
import android.util.Pools;
import androidx.collection.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.UiEventLogger;
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.StatusBarState;
@@ -37,6 +40,7 @@
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.HeadsUpManagerLogger;
@@ -104,8 +108,11 @@
KeyguardBypassController bypassController,
GroupMembershipManager groupMembershipManager,
VisualStabilityProvider visualStabilityProvider,
- ConfigurationController configurationController) {
- super(context, logger);
+ ConfigurationController configurationController,
+ @Main Handler handler,
+ AccessibilityManagerWrapper accessibilityManagerWrapper,
+ UiEventLogger uiEventLogger) {
+ super(context, logger, handler, accessibilityManagerWrapper, uiEventLogger);
Resources resources = mContext.getResources();
mExtensionTime = resources.getInteger(R.integer.ambient_notification_extension_time);
statusBarStateController.addCallback(mStatusBarStateListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
deleted file mode 100644
index 2c4fc6c..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2018 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.statusbar.phone;
-
-import static com.android.systemui.statusbar.phone.CentralSurfaces.DEBUG;
-import static com.android.systemui.statusbar.phone.CentralSurfaces.MULTIUSER_DEBUG;
-
-import android.service.notification.StatusBarNotification;
-import android.util.Log;
-
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-
-import javax.inject.Inject;
-
-@SysUISingleton
-public class KeyguardEnvironmentImpl implements KeyguardEnvironment {
-
- private static final String TAG = "KeyguardEnvironmentImpl";
-
- private final NotificationLockscreenUserManager mLockscreenUserManager;
- private final DeviceProvisionedController mDeviceProvisionedController;
-
- @Inject
- public KeyguardEnvironmentImpl(
- NotificationLockscreenUserManager notificationLockscreenUserManager,
- DeviceProvisionedController deviceProvisionedController) {
- mLockscreenUserManager = notificationLockscreenUserManager;
- mDeviceProvisionedController = deviceProvisionedController;
- }
-
- @Override // NotificationEntryManager.KeyguardEnvironment
- public boolean isDeviceProvisioned() {
- return mDeviceProvisionedController.isDeviceProvisioned();
- }
-
- @Override // NotificationEntryManager.KeyguardEnvironment
- public boolean isNotificationForCurrentProfiles(StatusBarNotification n) {
- final int notificationUserId = n.getUserId();
- if (DEBUG && MULTIUSER_DEBUG) {
- Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d", n,
- mLockscreenUserManager.getCurrentUserId(), notificationUserId));
- }
- return mLockscreenUserManager.isCurrentProfile(notificationUserId);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index f06b346..ce2c9c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -16,6 +16,9 @@
package com.android.systemui.statusbar.phone;
+import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
+import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
+
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import android.animation.Animator;
@@ -43,8 +46,10 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.NotificationPanelViewController;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.disableflags.DisableStateTracker;
import com.android.systemui.statusbar.events.SystemStatusAnimationCallback;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.notification.AnimatableProperty;
@@ -108,6 +113,7 @@
private final StatusBarUserSwitcherController mUserSwitcherController;
private final StatusBarUserInfoTracker mStatusBarUserInfoTracker;
private final SecureSettings mSecureSettings;
+ private final CommandQueue mCommandQueue;
private final Executor mMainExecutor;
private final Object mLock = new Object();
@@ -218,6 +224,9 @@
}
};
+
+ private final DisableStateTracker mDisableStateTracker;
+
private final List<String> mBlockedIcons = new ArrayList<>();
private final int mNotificationsHeaderCollideDistance;
@@ -269,6 +278,7 @@
StatusBarUserSwitcherController userSwitcherController,
StatusBarUserInfoTracker statusBarUserInfoTracker,
SecureSettings secureSettings,
+ CommandQueue commandQueue,
@Main Executor mainExecutor
) {
super(view);
@@ -292,6 +302,7 @@
mUserSwitcherController = userSwitcherController;
mStatusBarUserInfoTracker = statusBarUserInfoTracker;
mSecureSettings = secureSettings;
+ mCommandQueue = commandQueue;
mMainExecutor = mainExecutor;
mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
@@ -316,6 +327,12 @@
!mFeatureController.isStatusBarUserSwitcherFeatureEnabled());
mFeatureController.addCallback(enabled -> mView.setKeyguardUserAvatarEnabled(!enabled));
mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, r);
+
+ mDisableStateTracker = new DisableStateTracker(
+ /* mask1= */ DISABLE_SYSTEM_INFO,
+ /* mask2= */ DISABLE2_SYSTEM_ICONS,
+ this::updateViewState
+ );
}
@Override
@@ -333,6 +350,7 @@
mUserInfoController.addCallback(mOnUserInfoChangedListener);
mStatusBarStateController.addCallback(mStatusBarStateListener);
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
+ mDisableStateTracker.startTracking(mCommandQueue, mView.getDisplay().getDisplayId());
if (mTintedIconManager == null) {
mTintedIconManager =
mTintedIconManagerFactory.create(mView.findViewById(R.id.statusIcons));
@@ -357,6 +375,7 @@
mUserInfoController.removeCallback(mOnUserInfoChangedListener);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
+ mDisableStateTracker.stopTracking(mCommandQueue);
mSecureSettings.unregisterContentObserver(mVolumeSettingObserver);
if (mTintedIconManager != null) {
mStatusBarIconController.removeIconGroup(mTintedIconManager);
@@ -411,6 +430,10 @@
/** Animate the keyguard status bar in. */
public void animateKeyguardStatusBarIn() {
+ if (mDisableStateTracker.isDisabled()) {
+ // If our view is disabled, don't allow us to animate in.
+ return;
+ }
mView.setVisibility(View.VISIBLE);
mView.setAlpha(0f);
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
@@ -463,7 +486,11 @@
boolean hideForBypass =
mFirstBypassAttempt && mKeyguardUpdateMonitor.shouldListenForFace()
|| mDelayShowingKeyguardStatusBar;
- int newVisibility = newAlpha != 0f && !mDozing && !hideForBypass
+ int newVisibility =
+ newAlpha != 0f
+ && !mDozing
+ && !hideForBypass
+ && !mDisableStateTracker.isDisabled()
? View.VISIBLE : View.INVISIBLE;
updateViewState(newAlpha, newVisibility);
@@ -473,6 +500,9 @@
* Updates the {@link KeyguardStatusBarView} state based on the provided values.
*/
public void updateViewState(float alpha, int visibility) {
+ if (mDisableStateTracker.isDisabled()) {
+ visibility = View.INVISIBLE;
+ }
mView.setAlpha(alpha);
mView.setVisibility(visibility);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 5168533..365fbac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -29,6 +29,7 @@
/**
* Container for image of the multi user switcher (tappable).
*/
+// TODO(b/242040009): Remove this file.
public class MultiUserSwitch extends FrameLayout {
public MultiUserSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java
index 799e5fe..4d61689 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java
@@ -40,6 +40,7 @@
import javax.inject.Inject;
/** View Controller for {@link MultiUserSwitch}. */
+// TODO(b/242040009): Remove this file.
public class MultiUserSwitchController extends ViewController<MultiUserSwitch> {
private final UserManager mUserManager;
private final UserSwitcherController mUserSwitcherController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 290df3e..48e58fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -33,6 +33,7 @@
import android.content.res.Resources;
import android.media.AudioManager;
import android.os.Handler;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -127,7 +128,7 @@
private final DateFormatUtil mDateFormatUtil;
private final TelecomManager mTelecomManager;
- private final Handler mHandler = new Handler();
+ private final Handler mHandler;
private final CastController mCast;
private final HotspotController mHotspot;
private final NextAlarmController mNextAlarmController;
@@ -166,7 +167,7 @@
@Inject
public PhoneStatusBarPolicy(StatusBarIconController iconController,
CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher,
- @UiBackground Executor uiBgExecutor, @Main Resources resources,
+ @UiBackground Executor uiBgExecutor, @Main Looper looper, @Main Resources resources,
CastController castController, HotspotController hotspotController,
BluetoothController bluetoothController, NextAlarmController nextAlarmController,
UserInfoController userInfoController, RotationLockController rotationLockController,
@@ -185,6 +186,7 @@
mIconController = iconController;
mCommandQueue = commandQueue;
mBroadcastDispatcher = broadcastDispatcher;
+ mHandler = new Handler(looper);
mResources = resources;
mCast = castController;
mHotspot = hotspotController;
@@ -332,6 +334,7 @@
mRotationLockController.addCallback(this);
mBluetooth.addCallback(this);
mProvisionedController.addCallback(this);
+ mCurrentUserSetup = mProvisionedController.isCurrentUserSetup();
mZenController.addCallback(this);
mCast.addCallback(mCastCallback);
mHotspot.addCallback(mHotspotCallback);
@@ -562,6 +565,7 @@
mHandler.post(() -> {
updateAlarm();
updateManagedProfile();
+ onUserSetupChanged();
});
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java
index ebfbf54..ae201e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java
@@ -120,7 +120,6 @@
@Override
public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
- mNotificationsController.requestNotificationUpdate("onHeadsUpStateChanged");
if (mStatusBarStateController.isDozing() && isHeadsUp) {
entry.setPulseSuppressed(false);
mDozeServiceHost.fireNotificationPulse(entry);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index ed186ab..8273d57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -33,7 +33,6 @@
import androidx.annotation.VisibleForTesting;
import com.android.internal.statusbar.StatusBarIcon;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.demomode.DemoModeCommandReceiver;
@@ -137,11 +136,12 @@
LinearLayout linearLayout,
FeatureFlags featureFlags,
StatusBarPipelineFlags statusBarPipelineFlags,
- Provider<WifiViewModel> wifiViewModelProvider) {
+ Provider<WifiViewModel> wifiViewModelProvider,
+ DarkIconDispatcher darkIconDispatcher) {
super(linearLayout, featureFlags, statusBarPipelineFlags, wifiViewModelProvider);
mIconHPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.status_bar_icon_padding);
- mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
+ mDarkIconDispatcher = darkIconDispatcher;
}
@Override
@@ -198,20 +198,24 @@
private final FeatureFlags mFeatureFlags;
private final StatusBarPipelineFlags mStatusBarPipelineFlags;
private final Provider<WifiViewModel> mWifiViewModelProvider;
+ private final DarkIconDispatcher mDarkIconDispatcher;
@Inject
public Factory(
FeatureFlags featureFlags,
StatusBarPipelineFlags statusBarPipelineFlags,
- Provider<WifiViewModel> wifiViewModelProvider) {
+ Provider<WifiViewModel> wifiViewModelProvider,
+ DarkIconDispatcher darkIconDispatcher) {
mFeatureFlags = featureFlags;
mStatusBarPipelineFlags = statusBarPipelineFlags;
mWifiViewModelProvider = wifiViewModelProvider;
+ mDarkIconDispatcher = darkIconDispatcher;
}
public DarkIconManager create(LinearLayout group) {
return new DarkIconManager(
- group, mFeatureFlags, mStatusBarPipelineFlags, mWifiViewModelProvider);
+ group, mFeatureFlags, mStatusBarPipelineFlags, mWifiViewModelProvider,
+ mDarkIconDispatcher);
}
}
}
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 d5c6f89..f106e54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -589,7 +589,7 @@
public void reset(boolean hideBouncerWhenShowing) {
if (mShowing) {
// Hide quick settings.
- mNotificationPanelViewController.resetViews(/* animate= */ true);
+ mNotificationPanelViewController.resetViews(/* animate= */ !mOccluded);
// Hide bouncer and quick-quick settings.
if (mOccluded && !mDozing) {
mCentralSurfaces.hideKeyguard();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 374f091..5cd2ba1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -223,12 +223,12 @@
boolean isActivityIntent = intent != null && intent.isActivity() && !isBubble;
final boolean willLaunchResolverActivity = isActivityIntent
- && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
+ && mActivityIntentHelper.wouldPendingLaunchResolverActivity(intent,
mLockscreenUserManager.getCurrentUserId());
final boolean animate = !willLaunchResolverActivity
&& mCentralSurfaces.shouldAnimateLaunch(isActivityIntent);
boolean showOverLockscreen = mKeyguardStateController.isShowing() && intent != null
- && mActivityIntentHelper.wouldShowOverLockscreen(intent.getIntent(),
+ && mActivityIntentHelper.wouldPendingShowOverLockscreen(intent,
mLockscreenUserManager.getCurrentUserId());
ActivityStarter.OnDismissAction postKeyguardAction = new ActivityStarter.OnDismissAction() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 6996ee7..64ca2705 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -33,8 +33,6 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.systemui.Dependency;
-import com.android.systemui.ForegroundServiceNotificationListener;
import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
@@ -184,10 +182,6 @@
mMediaManager.setUpWithPresenter(this);
mGutsManager.setUpWithPresenter(
this, mNotifListContainer, mOnSettingsClickListener);
- // ForegroundServiceNotificationListener adds its listener in its constructor
- // but we need to request it here in order for it to be instantiated.
- // TODO: figure out how to do this correctly once Dependency.get() is gone.
- Dependency.get(ForegroundServiceNotificationListener.class);
onUserSwitched(mLockscreenUserManager.getCurrentUserId());
});
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 40b9a15..70af77e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -259,8 +259,9 @@
final boolean isActivity = pendingIntent.isActivity();
if (isActivity || appRequestedAuth) {
mActionClickLogger.logWaitingToCloseKeyguard(pendingIntent);
- final boolean afterKeyguardGone = mActivityIntentHelper.wouldLaunchResolverActivity(
- pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId());
+ final boolean afterKeyguardGone = mActivityIntentHelper
+ .wouldPendingLaunchResolverActivity(pendingIntent,
+ mLockscreenUserManager.getCurrentUserId());
mActivityStarter.dismissKeyguardThenExecute(() -> {
mActionClickLogger.logKeyguardGone(pendingIntent);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index 84bb82b..ce04fb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -442,7 +442,6 @@
state |= DISABLE_CLOCK;
}
-
if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
if (mNetworkController.hasEmergencyCryptKeeperText()) {
state |= DISABLE_NOTIFICATION_ICONS;
@@ -452,13 +451,6 @@
}
}
- // The shelf will be hidden when dozing with a custom clock, we must show notification
- // icons in this occasion.
- if (mStatusBarStateController.isDozing()
- && mNotificationPanelViewController.hasCustomClock()) {
- state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO;
- }
-
if (mOngoingCallController.hasOngoingCall()) {
state &= ~DISABLE_ONGOING_CALL_CHIP;
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt
index 5566fa6..c96faab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt
@@ -16,13 +16,23 @@
package com.android.systemui.statusbar.pipeline.wifi.data.model
+import androidx.annotation.VisibleForTesting
+
/** Provides information about the current wifi network. */
sealed class WifiNetworkModel {
/** A model representing that we have no active wifi network. */
object Inactive : WifiNetworkModel()
+ /**
+ * A model representing that our wifi network is actually a carrier merged network, meaning it's
+ * treated as more of a mobile network.
+ *
+ * See [android.net.wifi.WifiInfo.isCarrierMerged] for more information.
+ */
+ object CarrierMerged : WifiNetworkModel()
+
/** Provides information about an active wifi network. */
- class Active(
+ data class Active(
/**
* The [android.net.Network.netId] we received from
* [android.net.ConnectivityManager.NetworkCallback] in association with this wifi network.
@@ -31,6 +41,19 @@
*/
val networkId: Int,
+ /** See [android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED]. */
+ val isValidated: Boolean = false,
+
+ /**
+ * The wifi signal level, guaranteed to be 0 <= level <= 4.
+ *
+ * Null if we couldn't fetch the level for some reason.
+ *
+ * TODO(b/238425913): The level will only be null if we have a null WifiManager. Is there a
+ * way we can guarantee a non-null WifiManager?
+ */
+ val level: Int? = null,
+
/** See [android.net.wifi.WifiInfo.ssid]. */
val ssid: String? = null,
@@ -42,5 +65,18 @@
/** See [android.net.wifi.WifiInfo.passpointProviderFriendlyName]. */
val passpointProviderFriendlyName: String? = null,
- ) : WifiNetworkModel()
+ ) : WifiNetworkModel() {
+ init {
+ require(level == null || level in MIN_VALID_LEVEL..MAX_VALID_LEVEL) {
+ "0 <= wifi level <= 4 required; level was $level"
+ }
+ }
+
+ companion object {
+ @VisibleForTesting
+ internal const val MIN_VALID_LEVEL = 0
+ @VisibleForTesting
+ internal const val MAX_VALID_LEVEL = 4
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
index 43fbabc..103f3fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
@@ -21,6 +21,7 @@
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN
+import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkRequest
@@ -31,6 +32,7 @@
import com.android.settingslib.Utils
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG
@@ -38,10 +40,13 @@
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import java.util.concurrent.Executor
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.stateIn
/**
* Provides data related to the wifi state.
@@ -63,10 +68,11 @@
@SysUISingleton
@SuppressLint("MissingPermission")
class WifiRepositoryImpl @Inject constructor(
- connectivityManager: ConnectivityManager,
- wifiManager: WifiManager?,
- @Main mainExecutor: Executor,
- logger: ConnectivityPipelineLogger,
+ connectivityManager: ConnectivityManager,
+ logger: ConnectivityPipelineLogger,
+ @Main mainExecutor: Executor,
+ @Application scope: CoroutineScope,
+ wifiManager: WifiManager?,
) : WifiRepository {
override val wifiNetwork: Flow<WifiNetworkModel> = conflatedCallbackFlow {
var currentWifi: WifiNetworkModel = WIFI_NETWORK_DEFAULT
@@ -80,7 +86,12 @@
val wifiInfo = networkCapabilitiesToWifiInfo(networkCapabilities)
if (wifiInfo?.isPrimary == true) {
- val wifiNetworkModel = wifiInfoToModel(wifiInfo, network.getNetId())
+ val wifiNetworkModel = createWifiNetworkModel(
+ wifiInfo,
+ network,
+ networkCapabilities,
+ wifiManager,
+ )
logger.logTransformation(
WIFI_NETWORK_CALLBACK_NAME,
oldValue = currentWifi,
@@ -107,11 +118,19 @@
}
}
- trySend(WIFI_NETWORK_DEFAULT)
connectivityManager.registerNetworkCallback(WIFI_NETWORK_CALLBACK_REQUEST, callback)
awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
}
+ // There will be multiple wifi icons in different places that will frequently
+ // subscribe/unsubscribe to flows as the views attach/detach. Using [stateIn] ensures that
+ // new subscribes will get the latest value immediately upon subscription. Otherwise, the
+ // views could show stale data. See b/244173280.
+ .stateIn(
+ scope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = WIFI_NETWORK_DEFAULT
+ )
override val wifiActivity: Flow<WifiActivityModel> =
if (wifiManager == null) {
@@ -164,14 +183,25 @@
}
}
- private fun wifiInfoToModel(wifiInfo: WifiInfo, networkId: Int): WifiNetworkModel {
- return WifiNetworkModel.Active(
- networkId,
- wifiInfo.ssid,
- wifiInfo.isPasspointAp,
- wifiInfo.isOsuAp,
- wifiInfo.passpointProviderFriendlyName
- )
+ private fun createWifiNetworkModel(
+ wifiInfo: WifiInfo,
+ network: Network,
+ networkCapabilities: NetworkCapabilities,
+ wifiManager: WifiManager?,
+ ): WifiNetworkModel {
+ return if (wifiInfo.isCarrierMerged) {
+ WifiNetworkModel.CarrierMerged
+ } else {
+ WifiNetworkModel.Active(
+ network.getNetId(),
+ isValidated = networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED),
+ level = wifiManager?.calculateSignalLevel(wifiInfo.rssi),
+ wifiInfo.ssid,
+ wifiInfo.isPasspointAp,
+ wifiInfo.isOsuAp,
+ wifiInfo.passpointProviderFriendlyName
+ )
+ }
}
private fun prettyPrintActivity(activity: Int): String {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
index a9da63b..afe19af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
@@ -33,11 +33,12 @@
*/
@SysUISingleton
class WifiInteractor @Inject constructor(
- repository: WifiRepository,
+ repository: WifiRepository,
) {
private val ssid: Flow<String?> = repository.wifiNetwork.map { info ->
when (info) {
is WifiNetworkModel.Inactive -> null
+ is WifiNetworkModel.CarrierMerged -> null
is WifiNetworkModel.Active -> when {
info.isPasspointAccessPoint || info.isOnlineSignUpForPasspointAccessPoint ->
info.passpointProviderFriendlyName
@@ -47,6 +48,10 @@
}
}
+ /** Our current wifi network. See [WifiNetworkModel]. */
+ val wifiNetwork: Flow<WifiNetworkModel> = repository.wifiNetwork
+
+ /** True if our wifi network has activity in (download), and false otherwise. */
val hasActivityIn: Flow<Boolean> = combine(repository.wifiActivity, ssid) { activity, ssid ->
activity.hasActivityIn && ssid != null
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
index b06aaf4..7607ddf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
@@ -25,10 +25,10 @@
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.R
import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
/**
@@ -50,11 +50,22 @@
view.isVisible = true
iconView.isVisible = true
- iconView.setImageDrawable(view.context.getDrawable(WIFI_FULL_ICONS[2]))
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) {
launch {
+ viewModel.wifiIconResId.distinctUntilChanged().collect { iconResId ->
+ iconView.setImageDrawable(
+ if (iconResId != null && iconResId > 0) {
+ iconView.context.getDrawable(iconResId)
+ } else {
+ null
+ }
+ )
+ }
+ }
+
+ launch {
viewModel.tint.collect { tint ->
iconView.imageTintList = ColorStateList.valueOf(tint)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
index 7a26260..4fdcc44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
@@ -17,20 +17,24 @@
package com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel
import android.graphics.Color
+import androidx.annotation.DrawableRes
+import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS
+import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS
+import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
+import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
/**
* Models the UI state for the status bar wifi icon.
- *
- * TODO(b/238425913): Hook this up to the real status bar wifi view using a view binder.
*/
class WifiViewModel @Inject constructor(
statusBarPipelineFlags: StatusBarPipelineFlags,
@@ -38,6 +42,23 @@
private val logger: ConnectivityPipelineLogger,
private val interactor: WifiInteractor,
) {
+ /**
+ * The drawable resource ID to use for the wifi icon. Null if we shouldn't display any icon.
+ */
+ @DrawableRes
+ val wifiIconResId: Flow<Int?> = interactor.wifiNetwork.map {
+ when (it) {
+ is WifiNetworkModel.CarrierMerged -> null
+ is WifiNetworkModel.Inactive -> WIFI_NO_NETWORK
+ is WifiNetworkModel.Active ->
+ when {
+ it.level == null -> null
+ it.isValidated -> WIFI_FULL_ICONS[it.level]
+ else -> WIFI_NO_INTERNET_ICONS[it.level]
+ }
+ }
+ }
+
val isActivityInVisible: Flow<Boolean>
get() =
if (!constants.shouldShowActivityConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index d3837d7..9f21ed9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.os.Handler;
import android.provider.Settings;
import android.util.ArrayMap;
import android.view.accessibility.AccessibilityManager;
@@ -31,9 +32,9 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
@@ -79,11 +80,15 @@
}
}
- public HeadsUpManager(@NonNull final Context context, HeadsUpManagerLogger logger) {
- super(logger);
+ public HeadsUpManager(@NonNull final Context context,
+ HeadsUpManagerLogger logger,
+ @Main Handler handler,
+ AccessibilityManagerWrapper accessibilityManagerWrapper,
+ UiEventLogger uiEventLogger) {
+ super(logger, handler);
mContext = context;
- mAccessibilityMgr = Dependency.get(AccessibilityManagerWrapper.class);
- mUiEventLogger = Dependency.get(UiEventLogger.class);
+ mAccessibilityMgr = accessibilityManagerWrapper;
+ mUiEventLogger = uiEventLogger;
Resources resources = context.getResources();
mMinimumDisplayTime = resources.getInteger(R.integer.heads_up_notification_minimum_time);
mAutoDismissNotificationDecay = resources.getInteger(R.integer.heads_up_notification_decay);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
index 169347a..16306081 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
@@ -49,6 +49,7 @@
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.UserAvatarView;
+import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.util.ViewController;
import javax.inject.Inject;
@@ -79,7 +80,7 @@
@VisibleForTesting
UserAvatarView mUserAvatarView;
private View mUserAvatarViewWithBackground;
- UserSwitcherController.UserRecord mCurrentUser;
+ UserRecord mCurrentUser;
private boolean mIsKeyguardShowing;
// State info for the user switch and keyguard
@@ -269,10 +270,10 @@
* @return true if the current user has changed
*/
private boolean updateCurrentUser() {
- UserSwitcherController.UserRecord previousUser = mCurrentUser;
+ UserRecord previousUser = mCurrentUser;
mCurrentUser = null;
for (int i = 0; i < mAdapter.getCount(); i++) {
- UserSwitcherController.UserRecord r = mAdapter.getItem(i);
+ UserRecord r = mAdapter.getItem(i);
if (r.isCurrent) {
mCurrentUser = r;
return !mCurrentUser.equals(previousUser);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
index 03ab888..e2f5734 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
@@ -52,6 +52,7 @@
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
+import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.util.ViewController;
import java.util.ArrayList;
@@ -287,8 +288,8 @@
}
KeyguardUserDetailItemView newView = (KeyguardUserDetailItemView)
mAdapter.getView(i, oldView, mListView);
- UserSwitcherController.UserRecord userTag =
- (UserSwitcherController.UserRecord) newView.getTag();
+ UserRecord userTag =
+ (UserRecord) newView.getTag();
if (userTag.isCurrent) {
if (i != 0) {
Log.w(TAG, "Current user is not the first view in the list");
@@ -443,7 +444,7 @@
private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
private View mCurrentUserView;
// List of users where the first entry is always the current user
- private ArrayList<UserSwitcherController.UserRecord> mUsersOrdered = new ArrayList<>();
+ private ArrayList<UserRecord> mUsersOrdered = new ArrayList<>();
KeyguardUserAdapter(Context context, Resources resources, LayoutInflater layoutInflater,
UserSwitcherController controller,
@@ -464,10 +465,10 @@
}
void refreshUserOrder() {
- ArrayList<UserSwitcherController.UserRecord> users = super.getUsers();
+ ArrayList<UserRecord> users = super.getUsers();
mUsersOrdered = new ArrayList<>(users.size());
for (int i = 0; i < users.size(); i++) {
- UserSwitcherController.UserRecord record = users.get(i);
+ UserRecord record = users.get(i);
if (record.isCurrent) {
mUsersOrdered.add(0, record);
} else {
@@ -477,19 +478,19 @@
}
@Override
- protected ArrayList<UserSwitcherController.UserRecord> getUsers() {
+ protected ArrayList<UserRecord> getUsers() {
return mUsersOrdered;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- UserSwitcherController.UserRecord item = getItem(position);
+ UserRecord item = getItem(position);
return createUserDetailItemView(convertView, parent, item);
}
KeyguardUserDetailItemView convertOrInflate(View convertView, ViewGroup parent) {
if (!(convertView instanceof KeyguardUserDetailItemView)
- || !(convertView.getTag() instanceof UserSwitcherController.UserRecord)) {
+ || !(convertView.getTag() instanceof UserRecord)) {
convertView = mLayoutInflater.inflate(
R.layout.keyguard_user_switcher_item, parent, false);
}
@@ -497,7 +498,7 @@
}
KeyguardUserDetailItemView createUserDetailItemView(View convertView, ViewGroup parent,
- UserSwitcherController.UserRecord item) {
+ UserRecord item) {
KeyguardUserDetailItemView v = convertOrInflate(convertView, parent);
v.setOnClickListener(this);
@@ -513,7 +514,7 @@
v.bind(name, drawable, item.info.id);
}
v.setActivated(item.isCurrent);
- v.setDisabledByAdmin(item.isDisabledByAdmin);
+ v.setDisabledByAdmin(mController.isDisabledByAdmin(item));
v.setEnabled(item.isSwitchToEnabled);
v.setAlpha(v.isEnabled() ? USER_SWITCH_ENABLED_ALPHA : USER_SWITCH_DISABLED_ALPHA);
@@ -524,7 +525,7 @@
return v;
}
- private Drawable getDrawable(UserSwitcherController.UserRecord item) {
+ private Drawable getDrawable(UserRecord item) {
Drawable drawable;
if (item.isCurrent && item.isGuest) {
drawable = mContext.getDrawable(R.drawable.ic_avatar_guest_user);
@@ -547,7 +548,7 @@
@Override
public void onClick(View v) {
- UserSwitcherController.UserRecord user = (UserSwitcherController.UserRecord) v.getTag();
+ UserRecord user = (UserRecord) v.getTag();
if (mKeyguardUserSwitcherController.isListAnimating()) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 62fc01f..a5bcb53 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -45,7 +45,7 @@
import android.provider.Settings;
import android.telephony.TelephonyCallback;
import android.text.TextUtils;
-import android.util.FeatureFlagUtils;
+import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -55,6 +55,7 @@
import android.widget.Toast;
import androidx.annotation.Nullable;
+import androidx.collection.SimpleArrayMap;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
@@ -84,6 +85,7 @@
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.user.CreateUserActivity;
+import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.util.settings.GlobalSettings;
import com.android.systemui.util.settings.SecureSettings;
@@ -139,6 +141,9 @@
private final InteractionJankMonitor mInteractionJankMonitor;
private final LatencyTracker mLatencyTracker;
private final DialogLaunchAnimator mDialogLaunchAnimator;
+ private final SimpleArrayMap<UserRecord, EnforcedAdmin> mEnforcedAdminByUserRecord =
+ new SimpleArrayMap<>();
+ private final ArraySet<UserRecord> mDisabledByAdmin = new ArraySet<>();
private ArrayList<UserRecord> mUsers = new ArrayList<>();
@VisibleForTesting
@@ -287,10 +292,6 @@
refreshUsers(UserHandle.USER_NULL);
}
- private static boolean isEnableGuestModeUxChanges(Context context) {
- return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_GUEST_MODE_UX_CHANGES);
- }
-
/**
* Refreshes users from UserManager.
*
@@ -549,17 +550,9 @@
}
if (currUserInfo != null && currUserInfo.isGuest()) {
- if (isEnableGuestModeUxChanges(mContext)) {
- showExitGuestDialog(currUserId, currUserInfo.isEphemeral(),
- record.resolveId(), dialogShower);
- return;
- } else {
- if (currUserInfo.isEphemeral()) {
- showExitGuestDialog(currUserId, currUserInfo.isEphemeral(),
- record.resolveId(), dialogShower);
- return;
- }
- }
+ showExitGuestDialog(currUserId, currUserInfo.isEphemeral(),
+ record.resolveId(), dialogShower);
+ return;
}
if (dialogShower != null) {
@@ -988,6 +981,21 @@
return mKeyguardStateController;
}
+ /**
+ * Returns the {@link EnforcedAdmin} for the given record, or {@code null} if there isn't one.
+ */
+ @Nullable
+ public EnforcedAdmin getEnforcedAdmin(UserRecord record) {
+ return mEnforcedAdminByUserRecord.get(record);
+ }
+
+ /**
+ * Returns {@code true} if the given record is disabled by the admin; {@code false} otherwise.
+ */
+ public boolean isDisabledByAdmin(UserRecord record) {
+ return mDisabledByAdmin.contains(record);
+ }
+
public static abstract class BaseUserAdapter extends BaseAdapter {
final UserSwitcherController mController;
@@ -1056,14 +1064,8 @@
public String getName(Context context, UserRecord item) {
if (item.isGuest) {
if (item.isCurrent) {
- if (isEnableGuestModeUxChanges(context)) {
- return context.getString(
- com.android.settingslib.R.string.guest_exit_quick_settings_button);
- } else {
- return context.getString(mController.mGuestUserAutoCreated
- ? com.android.settingslib.R.string.guest_reset_guest
- : com.android.settingslib.R.string.guest_exit_guest);
- }
+ return context.getString(
+ com.android.settingslib.R.string.guest_exit_quick_settings_button);
} else {
if (item.info != null) {
return context.getString(com.android.internal.R.string.guest_name);
@@ -1080,13 +1082,8 @@
? com.android.settingslib.R.string.guest_resetting
: com.android.internal.R.string.guest_name);
} else {
- if (isEnableGuestModeUxChanges(context)) {
- // we always show "guest" as string, instead of "add guest"
- return context.getString(com.android.internal.R.string.guest_name);
- } else {
- return context.getString(
- com.android.settingslib.R.string.guest_new_guest);
- }
+ // we always show "guest" as string, instead of "add guest"
+ return context.getString(com.android.internal.R.string.guest_name);
}
}
}
@@ -1108,11 +1105,7 @@
protected static Drawable getIconDrawable(Context context, UserRecord item) {
int iconRes;
if (item.isAddUser) {
- if (isEnableGuestModeUxChanges(context)) {
- iconRes = R.drawable.ic_add;
- } else {
- iconRes = R.drawable.ic_account_circle_filled;
- }
+ iconRes = R.drawable.ic_add;
} else if (item.isGuest) {
iconRes = R.drawable.ic_account_circle;
} else if (item.isAddSupervisedUser) {
@@ -1134,11 +1127,11 @@
UserManager.DISALLOW_ADD_USER, mUserTracker.getUserId());
if (admin != null && !RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
UserManager.DISALLOW_ADD_USER, mUserTracker.getUserId())) {
- record.isDisabledByAdmin = true;
- record.enforcedAdmin = admin;
+ mDisabledByAdmin.add(record);
+ mEnforcedAdminByUserRecord.put(record, admin);
} else {
- record.isDisabledByAdmin = false;
- record.enforcedAdmin = null;
+ mDisabledByAdmin.remove(record);
+ mEnforcedAdminByUserRecord.put(record, null);
}
}
@@ -1180,74 +1173,6 @@
}
}
- public static final class UserRecord {
- public final UserInfo info;
- public final Bitmap picture;
- public final boolean isGuest;
- public final boolean isCurrent;
- public final boolean isAddUser;
- public final boolean isAddSupervisedUser;
- /** If true, the record is only visible to the owner and only when unlocked. */
- public final boolean isRestricted;
- public boolean isDisabledByAdmin;
- public EnforcedAdmin enforcedAdmin;
- public boolean isSwitchToEnabled;
-
- public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent,
- boolean isAddUser, boolean isRestricted, boolean isSwitchToEnabled,
- boolean isAddSupervisedUser) {
- this.info = info;
- this.picture = picture;
- this.isGuest = isGuest;
- this.isCurrent = isCurrent;
- this.isAddUser = isAddUser;
- this.isRestricted = isRestricted;
- this.isSwitchToEnabled = isSwitchToEnabled;
- this.isAddSupervisedUser = isAddSupervisedUser;
- }
-
- public UserRecord copyWithIsCurrent(boolean _isCurrent) {
- return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted,
- isSwitchToEnabled, isAddSupervisedUser);
- }
-
- public int resolveId() {
- if (isGuest || info == null) {
- return UserHandle.USER_NULL;
- }
- return info.id;
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("UserRecord(");
- if (info != null) {
- sb.append("name=\"").append(info.name).append("\" id=").append(info.id);
- } else {
- if (isGuest) {
- sb.append("<add guest placeholder>");
- } else if (isAddUser) {
- sb.append("<add user placeholder>");
- }
- }
- if (isGuest) sb.append(" <isGuest>");
- if (isAddUser) sb.append(" <isAddUser>");
- if (isAddSupervisedUser) sb.append(" <isAddSupervisedUser>");
- if (isCurrent) sb.append(" <isCurrent>");
- if (picture != null) sb.append(" <hasPicture>");
- if (isRestricted) sb.append(" <isRestricted>");
- if (isDisabledByAdmin) {
- sb.append(" <isDisabledByAdmin>");
- sb.append(" enforcedAdmin=").append(enforcedAdmin);
- }
- if (isSwitchToEnabled) {
- sb.append(" <isSwitchToEnabled>");
- }
- sb.append(')');
- return sb.toString();
- }
- }
-
private final KeyguardStateController.Callback mCallback =
new KeyguardStateController.Callback() {
@Override
@@ -1289,46 +1214,32 @@
ExitGuestDialog(Context context, int guestId, boolean isGuestEphemeral,
int targetId) {
super(context);
- if (isEnableGuestModeUxChanges(context)) {
- if (isGuestEphemeral) {
- setTitle(context.getString(
- com.android.settingslib.R.string.guest_exit_dialog_title));
- setMessage(context.getString(
- com.android.settingslib.R.string.guest_exit_dialog_message));
- setButton(DialogInterface.BUTTON_NEUTRAL,
- context.getString(android.R.string.cancel), this);
- setButton(DialogInterface.BUTTON_POSITIVE,
- context.getString(
- com.android.settingslib.R.string.guest_exit_dialog_button), this);
- } else {
- setTitle(context.getString(
- com.android.settingslib
- .R.string.guest_exit_dialog_title_non_ephemeral));
- setMessage(context.getString(
- com.android.settingslib
- .R.string.guest_exit_dialog_message_non_ephemeral));
- setButton(DialogInterface.BUTTON_NEUTRAL,
- context.getString(android.R.string.cancel), this);
- setButton(DialogInterface.BUTTON_NEGATIVE,
- context.getString(
- com.android.settingslib.R.string.guest_exit_clear_data_button),
- this);
- setButton(DialogInterface.BUTTON_POSITIVE,
- context.getString(
- com.android.settingslib.R.string.guest_exit_save_data_button),
- this);
- }
- } else {
- setTitle(mGuestUserAutoCreated
- ? com.android.settingslib.R.string.guest_reset_guest_dialog_title
- : com.android.settingslib.R.string.guest_remove_guest_dialog_title);
- setMessage(context.getString(R.string.guest_exit_guest_dialog_message));
+ if (isGuestEphemeral) {
+ setTitle(context.getString(
+ com.android.settingslib.R.string.guest_exit_dialog_title));
+ setMessage(context.getString(
+ com.android.settingslib.R.string.guest_exit_dialog_message));
setButton(DialogInterface.BUTTON_NEUTRAL,
context.getString(android.R.string.cancel), this);
setButton(DialogInterface.BUTTON_POSITIVE,
- context.getString(mGuestUserAutoCreated
- ? com.android.settingslib.R.string.guest_reset_guest_confirm_button
- : com.android.settingslib.R.string.guest_remove_guest_confirm_button),
+ context.getString(
+ com.android.settingslib.R.string.guest_exit_dialog_button), this);
+ } else {
+ setTitle(context.getString(
+ com.android.settingslib
+ .R.string.guest_exit_dialog_title_non_ephemeral));
+ setMessage(context.getString(
+ com.android.settingslib
+ .R.string.guest_exit_dialog_message_non_ephemeral));
+ setButton(DialogInterface.BUTTON_NEUTRAL,
+ context.getString(android.R.string.cancel), this);
+ setButton(DialogInterface.BUTTON_NEGATIVE,
+ context.getString(
+ com.android.settingslib.R.string.guest_exit_clear_data_button),
+ this);
+ setButton(DialogInterface.BUTTON_POSITIVE,
+ context.getString(
+ com.android.settingslib.R.string.guest_exit_save_data_button),
this);
}
SystemUIDialog.setWindowOnTop(this, mKeyguardStateController.isShowing());
@@ -1345,39 +1256,29 @@
if (mFalsingManager.isFalseTap(penalty)) {
return;
}
- if (isEnableGuestModeUxChanges(getContext())) {
- if (mIsGuestEphemeral) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- mDialogLaunchAnimator.dismissStack(this);
- // Ephemeral guest: exit guest, guest is removed by the system
- // on exit, since its marked ephemeral
- exitGuestUser(mGuestId, mTargetId, false);
- } else if (which == DialogInterface.BUTTON_NEGATIVE) {
- // Cancel clicked, do nothing
- cancel();
- }
- } else {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- mDialogLaunchAnimator.dismissStack(this);
- // Non-ephemeral guest: exit guest, guest is not removed by the system
- // on exit, since its marked non-ephemeral
- exitGuestUser(mGuestId, mTargetId, false);
- } else if (which == DialogInterface.BUTTON_NEGATIVE) {
- mDialogLaunchAnimator.dismissStack(this);
- // Non-ephemeral guest: remove guest and then exit
- exitGuestUser(mGuestId, mTargetId, true);
- } else if (which == DialogInterface.BUTTON_NEUTRAL) {
- // Cancel clicked, do nothing
- cancel();
- }
+ if (mIsGuestEphemeral) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ mDialogLaunchAnimator.dismissStack(this);
+ // Ephemeral guest: exit guest, guest is removed by the system
+ // on exit, since its marked ephemeral
+ exitGuestUser(mGuestId, mTargetId, false);
+ } else if (which == DialogInterface.BUTTON_NEGATIVE) {
+ // Cancel clicked, do nothing
+ cancel();
}
} else {
- if (which == BUTTON_NEUTRAL) {
- cancel();
- } else {
- mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE);
+ if (which == DialogInterface.BUTTON_POSITIVE) {
mDialogLaunchAnimator.dismissStack(this);
- removeGuestUser(mGuestId, mTargetId);
+ // Non-ephemeral guest: exit guest, guest is not removed by the system
+ // on exit, since its marked non-ephemeral
+ exitGuestUser(mGuestId, mTargetId, false);
+ } else if (which == DialogInterface.BUTTON_NEGATIVE) {
+ mDialogLaunchAnimator.dismissStack(this);
+ // Non-ephemeral guest: remove guest and then exit
+ exitGuestUser(mGuestId, mTargetId, true);
+ } else if (which == DialogInterface.BUTTON_NEUTRAL) {
+ // Cancel clicked, do nothing
+ cancel();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index aac5bf0..27746c0 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -26,6 +26,7 @@
import androidx.annotation.Nullable;
+import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.KeyguardViewController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
@@ -55,14 +56,13 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryControllerImpl;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -150,10 +150,6 @@
abstract DockManager bindDockManager(DockManagerImpl dockManager);
@Binds
- abstract NotificationEntryManager.KeyguardEnvironment bindKeyguardEnvironment(
- KeyguardEnvironmentImpl keyguardEnvironment);
-
- @Binds
abstract ShadeController provideShadeController(ShadeControllerImpl shadeController);
@SysUISingleton
@@ -172,7 +168,10 @@
KeyguardBypassController bypassController,
GroupMembershipManager groupManager,
VisualStabilityProvider visualStabilityProvider,
- ConfigurationController configurationController) {
+ ConfigurationController configurationController,
+ @Main Handler handler,
+ AccessibilityManagerWrapper accessibilityManagerWrapper,
+ UiEventLogger uiEventLogger) {
return new HeadsUpManagerPhone(
context,
headsUpManagerLogger,
@@ -180,7 +179,10 @@
bypassController,
groupManager,
visualStabilityProvider,
- configurationController
+ configurationController,
+ handler,
+ accessibilityManagerWrapper,
+ uiEventLogger
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt b/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
index 74d5111..ff0f0d4 100644
--- a/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
@@ -35,6 +35,7 @@
import android.widget.ArrayAdapter
import android.widget.ImageView
import android.widget.TextView
+import androidx.activity.ComponentActivity
import androidx.constraintlayout.helper.widget.Flow
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.util.UserIcons
@@ -50,8 +51,7 @@
import com.android.systemui.statusbar.policy.UserSwitcherController.BaseUserAdapter
import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA
import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA
-import com.android.systemui.statusbar.policy.UserSwitcherController.UserRecord
-import com.android.systemui.util.LifecycleActivity
+import com.android.systemui.user.data.source.UserRecord
import javax.inject.Inject
import kotlin.math.ceil
@@ -68,7 +68,7 @@
private val falsingManager: FalsingManager,
private val userManager: UserManager,
private val userTracker: UserTracker
-) : LifecycleActivity() {
+) : ComponentActivity() {
private lateinit var parent: UserSwitcherRootView
private lateinit var broadcastReceiver: BroadcastReceiver
@@ -81,16 +81,17 @@
}
}
// When the add users options become available, insert another option to manage users
- private val manageUserRecord = UserRecord(
- null /* info */,
- null /* picture */,
- false /* isGuest */,
- false /* isCurrent */,
- false /* isAddUser */,
- false /* isRestricted */,
- false /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */
- )
+ private val manageUserRecord =
+ UserRecord(
+ null /* info */,
+ null /* picture */,
+ false /* isGuest */,
+ false /* isCurrent */,
+ false /* isAddUser */,
+ false /* isRestricted */,
+ false /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */
+ )
private val adapter = object : BaseUserAdapter(userSwitcherController) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt b/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt
new file mode 100644
index 0000000..6ab6d7d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.android.systemui.user.data.source
+
+import android.content.pm.UserInfo
+import android.graphics.Bitmap
+import android.os.UserHandle
+
+/**
+ * Encapsulates raw data for a user or an option item related to managing users on the device.
+ */
+data class UserRecord(
+ /** Relevant user information. If `null`, this record is not a user but an option item. */
+ @JvmField
+ val info: UserInfo?,
+ /** An image representing the user. */
+ @JvmField
+ val picture: Bitmap?,
+ /** Whether this record represents an option to switch to a guest user. */
+ @JvmField
+ val isGuest: Boolean,
+ /** Whether this record represents the currently-selected user. */
+ @JvmField
+ val isCurrent: Boolean,
+ /** Whether this record represents an option to add another user to the device. */
+ @JvmField
+ val isAddUser: Boolean,
+ /** If true, the record is only visible to the owner and only when unlocked. */
+ @JvmField
+ val isRestricted: Boolean,
+ /** Whether it is possible to switch to this user. */
+ @JvmField
+ val isSwitchToEnabled: Boolean,
+ /** Whether this record represents an option to add another supervised user to the device. */
+ @JvmField
+ val isAddSupervisedUser: Boolean,
+) {
+ /**
+ * Returns a new instance of [UserRecord] with its [isCurrent] set to the given value.
+ */
+ fun copyWithIsCurrent(isCurrent: Boolean): UserRecord {
+ return copy(isCurrent = isCurrent)
+ }
+
+ /**
+ * Returns the user ID for the user represented by this instance or [UserHandle.USER_NULL] if
+ * this instance if a guest or does not represent a user (represents an option item).
+ */
+ fun resolveId(): Int {
+ return if (isGuest || info == null) {
+ UserHandle.USER_NULL
+ } else {
+ info.id
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/LifecycleActivity.kt b/packages/SystemUI/src/com/android/systemui/util/LifecycleActivity.kt
deleted file mode 100644
index e4b7a20..0000000
--- a/packages/SystemUI/src/com/android/systemui/util/LifecycleActivity.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2019 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.util
-
-import android.app.Activity
-import android.os.Bundle
-import android.os.PersistableBundle
-import androidx.lifecycle.LifecycleOwner
-import com.android.settingslib.core.lifecycle.Lifecycle
-
-open class LifecycleActivity : Activity(), LifecycleOwner {
-
- private val lifecycle = Lifecycle(this)
-
- override fun getLifecycle() = lifecycle
-
- override fun onCreate(savedInstanceState: Bundle?) {
- lifecycle.onAttach(this)
- lifecycle.onCreate(savedInstanceState)
- lifecycle.handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event.ON_CREATE)
- super.onCreate(savedInstanceState)
- }
-
- override fun onCreate(
- savedInstanceState: Bundle?,
- persistentState: PersistableBundle?
- ) {
- lifecycle.onAttach(this)
- lifecycle.onCreate(savedInstanceState)
- lifecycle.handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event.ON_CREATE)
- super.onCreate(savedInstanceState, persistentState)
- }
-
- override fun onStart() {
- lifecycle.handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event.ON_START)
- super.onStart()
- }
-
- override fun onResume() {
- lifecycle.handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event.ON_RESUME)
- super.onResume()
- }
-
- override fun onPause() {
- lifecycle.handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event.ON_PAUSE)
- super.onPause()
- }
-
- override fun onStop() {
- lifecycle.handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event.ON_STOP)
- super.onStop()
- }
-
- override fun onDestroy() {
- lifecycle.handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event.ON_DESTROY)
- super.onDestroy()
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt b/packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt
index 1059d6c..99eb03b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt
@@ -33,6 +33,11 @@
* Meant to be used with a rounded ends background, it will also prevent deformation when the slider
* is meant to be smaller than the rounded corner. The background should have rounded corners that
* are half of the height.
+ *
+ * This class also assumes that a "thumb" icon exists within the end's edge of the progress
+ * drawable, and the slider's width, when interacted on, if offset by half the size of the thumb
+ * icon which puts the icon directly underneath the user's finger.
+ *
*/
class RoundedCornerProgressDrawable @JvmOverloads constructor(
drawable: Drawable? = null
@@ -54,9 +59,16 @@
override fun onLevelChange(level: Int): Boolean {
val db = drawable?.bounds!!
+
+ // The thumb offset shifts the sun icon directly under the user's thumb
+ val thumbOffset = bounds.height() / 2
+ val width = bounds.width() * level / MAX_LEVEL + thumbOffset
+
// On 0, the width is bounds.height (a circle), and on MAX_LEVEL, the width is bounds.width
- val width = bounds.height() + (bounds.width() - bounds.height()) * level / MAX_LEVEL
- drawable?.setBounds(bounds.left, db.top, bounds.left + width, db.bottom)
+ drawable?.setBounds(
+ bounds.left, db.top,
+ width.coerceAtMost(bounds.width()).coerceAtLeast(bounds.height()), db.bottom
+ )
return super.onLevelChange(level)
}
@@ -91,4 +103,4 @@
return true
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/SysuiLifecycle.java b/packages/SystemUI/src/com/android/systemui/util/SysuiLifecycle.java
deleted file mode 100644
index d731753..0000000
--- a/packages/SystemUI/src/com/android/systemui/util/SysuiLifecycle.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2018 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.util;
-
-import static androidx.lifecycle.Lifecycle.State.DESTROYED;
-import static androidx.lifecycle.Lifecycle.State.RESUMED;
-
-import android.view.View;
-import android.view.View.OnAttachStateChangeListener;
-
-import androidx.annotation.NonNull;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.LifecycleRegistry;
-
-/**
- * Tools for generating lifecycle from sysui objects.
- */
-public class SysuiLifecycle {
-
- private SysuiLifecycle() {
- }
-
- /**
- * Get a lifecycle that will be put into the resumed state when the view is attached
- * and goes to the destroyed state when the view is detached.
- */
- public static LifecycleOwner viewAttachLifecycle(View v) {
- return new ViewLifecycle(v);
- }
-
- private static class ViewLifecycle implements LifecycleOwner, OnAttachStateChangeListener {
- private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
-
- ViewLifecycle(View v) {
- v.addOnAttachStateChangeListener(this);
- if (v.isAttachedToWindow()) {
- mLifecycle.markState(RESUMED);
- }
- }
-
- @NonNull
- @Override
- public Lifecycle getLifecycle() {
- return mLifecycle;
- }
-
- @Override
- public void onViewAttachedToWindow(View v) {
- mLifecycle.markState(RESUMED);
- }
-
- @Override
- public void onViewDetachedFromWindow(View v) {
- mLifecycle.markState(DESTROYED);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
new file mode 100644
index 0000000..7baebf4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.kotlin
+
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.drop
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.flow.zip
+
+/**
+ * Returns a new [Flow] that combines the two most recent emissions from [this] using [transform].
+ * Note that the new Flow will not start emitting until it has received two emissions from the
+ * upstream Flow.
+ *
+ * Useful for code that needs to compare the current value to the previous value.
+ */
+fun <T, R> Flow<T>.pairwiseBy(transform: suspend (old: T, new: T) -> R): Flow<R> {
+ // same as current flow, but with the very first event skipped
+ val nextEvents = drop(1)
+ // zip current flow and nextEvents; transform will receive a pair of old and new value. This
+ // works because zip will suppress emissions until both flows have emitted something; since in
+ // this case both flows are emitting at the same rate, but the current flow just has one extra
+ // thing emitted at the start, the effect is that zip will cache the most recent value while
+ // waiting for the next emission from nextEvents.
+ return zip(nextEvents, transform)
+}
+
+/**
+ * Returns a new [Flow] that combines the two most recent emissions from [this] using [transform].
+ * [initialValue] will be used as the "old" value for the first emission.
+ *
+ * Useful for code that needs to compare the current value to the previous value.
+ */
+fun <T, R> Flow<T>.pairwiseBy(
+ initialValue: T,
+ transform: suspend (previousValue: T, newValue: T) -> R,
+): Flow<R> =
+ onStart { emit(initialValue) }.pairwiseBy(transform)
+
+/**
+ * Returns a new [Flow] that produces the two most recent emissions from [this]. Note that the new
+ * Flow will not start emitting until it has received two emissions from the upstream Flow.
+ *
+ * Useful for code that needs to compare the current value to the previous value.
+ */
+fun <T> Flow<T>.pairwise(): Flow<WithPrev<T>> = pairwiseBy(::WithPrev)
+
+/**
+ * Returns a new [Flow] that produces the two most recent emissions from [this]. [initialValue]
+ * will be used as the "old" value for the first emission.
+ *
+ * Useful for code that needs to compare the current value to the previous value.
+ */
+fun <T> Flow<T>.pairwise(initialValue: T): Flow<WithPrev<T>> = pairwiseBy(initialValue, ::WithPrev)
+
+/** Holds a [newValue] emitted from a [Flow], along with the [previousValue] emitted value. */
+data class WithPrev<T>(val previousValue: T, val newValue: T)
+
+/**
+ * Returns a new [Flow] that combines the [Set] changes between each emission from [this] using
+ * [transform].
+ */
+fun <T, R> Flow<Set<T>>.setChangesBy(
+ transform: suspend (removed: Set<T>, added: Set<T>) -> R,
+): Flow<R> = onStart { emit(emptySet()) }.distinctUntilChanged()
+ .pairwiseBy { old: Set<T>, new: Set<T> ->
+ // If an element was present in the old set, but not the new one, then it was removed
+ val removed = old - new
+ // If an element is present in the new set, but on the old one, then it was added
+ val added = new - old
+ transform(removed, added)
+ }
+
+/** Returns a new [Flow] that produces the [Set] changes between each emission from [this]. */
+fun <T> Flow<Set<T>>.setChanges(): Flow<SetChanges<T>> = setChangesBy(::SetChanges)
+
+/** Contains the difference in elements between two [Set]s. */
+data class SetChanges<T>(
+ /** Elements that are present in the first [Set] but not in the second. */
+ val removed: Set<T>,
+ /** Elements that are present in the second [Set] but not in the first. */
+ val added: Set<T>,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index c94a915..e6a3e74c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -48,7 +48,6 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
@@ -248,6 +247,7 @@
private final ConfigurationController mConfigurationController;
private final MediaOutputDialogFactory mMediaOutputDialogFactory;
+ private final VolumePanelFactory mVolumePanelFactory;
private final ActivityStarter mActivityStarter;
private boolean mShowing;
@@ -279,6 +279,7 @@
DeviceProvisionedController deviceProvisionedController,
ConfigurationController configurationController,
MediaOutputDialogFactory mediaOutputDialogFactory,
+ VolumePanelFactory volumePanelFactory,
ActivityStarter activityStarter,
InteractionJankMonitor interactionJankMonitor) {
mContext =
@@ -290,6 +291,7 @@
mDeviceProvisionedController = deviceProvisionedController;
mConfigurationController = configurationController;
mMediaOutputDialogFactory = mediaOutputDialogFactory;
+ mVolumePanelFactory = volumePanelFactory;
mActivityStarter = activityStarter;
mShowActiveStreamOnly = showActiveStreamOnly();
mHasSeenODICaptionsTooltip =
@@ -1043,10 +1045,9 @@
if (mSettingsIcon != null) {
mSettingsIcon.setOnClickListener(v -> {
Events.writeEvent(Events.EVENT_SETTINGS_CLICK);
- Intent intent = new Intent(Settings.Panel.ACTION_VOLUME);
dismissH(DISMISS_REASON_SETTINGS_CLICKED);
mMediaOutputDialogFactory.dismiss();
- mActivityStarter.startActivity(intent, true /* dismissShade */);
+ mVolumePanelFactory.create(true /* aboveStatusBar */, null);
});
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java
new file mode 100644
index 0000000..2c74fb9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume;
+
+import android.bluetooth.BluetoothDevice;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.provider.SettingsSlicesContract;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
+import androidx.lifecycle.LiveData;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.slice.Slice;
+import androidx.slice.SliceMetadata;
+import androidx.slice.widget.EventInfo;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settingslib.bluetooth.A2dpProfile;
+import com.android.settingslib.bluetooth.BluetoothUtils;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.settingslib.media.MediaOutputConstants;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Visual presentation of the volume panel dialog.
+ */
+public class VolumePanelDialog extends SystemUIDialog implements LifecycleOwner {
+ private static final String TAG = "VolumePanelDialog";
+
+ private static final int DURATION_SLICE_BINDING_TIMEOUT_MS = 200;
+ private static final int DEFAULT_SLICE_SIZE = 4;
+
+ private RecyclerView mVolumePanelSlices;
+ private VolumePanelSlicesAdapter mVolumePanelSlicesAdapter;
+ private final LifecycleRegistry mLifecycleRegistry;
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+ private final Map<Uri, LiveData<Slice>> mSliceLiveData = new LinkedHashMap<>();
+ private final HashSet<Uri> mLoadedSlices = new HashSet<>();
+ private boolean mSlicesReadyToLoad;
+ private LocalBluetoothProfileManager mProfileManager;
+
+ public VolumePanelDialog(Context context, boolean aboveStatusBar) {
+ super(context);
+ mLifecycleRegistry = new LifecycleRegistry(this);
+ if (!aboveStatusBar) {
+ getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.d(TAG, "onCreate");
+
+ View dialogView = LayoutInflater.from(getContext()).inflate(R.layout.volume_panel_dialog,
+ null);
+ final Window window = getWindow();
+ window.setContentView(dialogView);
+
+ Button doneButton = dialogView.findViewById(R.id.done_button);
+ doneButton.setOnClickListener(v -> dismiss());
+ Button settingsButton = dialogView.findViewById(R.id.settings_button);
+ settingsButton.setOnClickListener(v -> {
+ getContext().startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS).addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK));
+ dismiss();
+ });
+
+ LocalBluetoothManager localBluetoothManager = LocalBluetoothManager.getInstance(
+ getContext(), null);
+ if (localBluetoothManager != null) {
+ mProfileManager = localBluetoothManager.getProfileManager();
+ }
+
+ mVolumePanelSlices = dialogView.findViewById(R.id.volume_panel_parent_layout);
+ mVolumePanelSlices.setLayoutManager(new LinearLayoutManager(getContext()));
+
+ loadAllSlices();
+
+ mLifecycleRegistry.setCurrentState(Lifecycle.State.CREATED);
+ }
+
+ private void loadAllSlices() {
+ mSliceLiveData.clear();
+ mLoadedSlices.clear();
+ final List<Uri> sliceUris = getSlices();
+
+ for (Uri uri : sliceUris) {
+ final LiveData<Slice> sliceLiveData = SliceLiveData.fromUri(getContext(), uri,
+ (int type, Throwable source) -> {
+ if (!removeSliceLiveData(uri)) {
+ mLoadedSlices.add(uri);
+ }
+ });
+
+ // Add slice first to make it in order. Will remove it later if there's an error.
+ mSliceLiveData.put(uri, sliceLiveData);
+
+ sliceLiveData.observe(this, slice -> {
+ if (mLoadedSlices.contains(uri)) {
+ return;
+ }
+ Log.d(TAG, "received slice: " + (slice == null ? null : slice.getUri()));
+ final SliceMetadata metadata = SliceMetadata.from(getContext(), slice);
+ if (slice == null || metadata.isErrorSlice()) {
+ if (!removeSliceLiveData(uri)) {
+ mLoadedSlices.add(uri);
+ }
+ } else if (metadata.getLoadingState() == SliceMetadata.LOADED_ALL) {
+ mLoadedSlices.add(uri);
+ } else {
+ mHandler.postDelayed(() -> {
+ mLoadedSlices.add(uri);
+ setupAdapterWhenReady();
+ }, DURATION_SLICE_BINDING_TIMEOUT_MS);
+ }
+
+ setupAdapterWhenReady();
+ });
+ }
+ }
+
+ private void setupAdapterWhenReady() {
+ if (mLoadedSlices.size() == mSliceLiveData.size() && !mSlicesReadyToLoad) {
+ mSlicesReadyToLoad = true;
+ mVolumePanelSlicesAdapter = new VolumePanelSlicesAdapter(this, mSliceLiveData);
+ mVolumePanelSlicesAdapter.setOnSliceActionListener((eventInfo, sliceItem) -> {
+ if (eventInfo.actionType == EventInfo.ACTION_TYPE_SLIDER) {
+ return;
+ }
+ this.dismiss();
+ });
+ if (mSliceLiveData.size() < DEFAULT_SLICE_SIZE) {
+ mVolumePanelSlices.setMinimumHeight(0);
+ }
+ mVolumePanelSlices.setAdapter(mVolumePanelSlicesAdapter);
+ }
+ }
+
+ private boolean removeSliceLiveData(Uri uri) {
+ boolean removed = false;
+ // Keeps observe media output slice
+ if (!uri.equals(MEDIA_OUTPUT_INDICATOR_SLICE_URI)) {
+ Log.d(TAG, "remove uri: " + uri);
+ removed = mSliceLiveData.remove(uri) != null;
+ if (mVolumePanelSlicesAdapter != null) {
+ mVolumePanelSlicesAdapter.updateDataSet(new ArrayList<>(mSliceLiveData.values()));
+ }
+ }
+ return removed;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ Log.d(TAG, "onStart");
+ mLifecycleRegistry.setCurrentState(Lifecycle.State.STARTED);
+ mLifecycleRegistry.setCurrentState(Lifecycle.State.RESUMED);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ Log.d(TAG, "onStop");
+ mLifecycleRegistry.setCurrentState(Lifecycle.State.DESTROYED);
+ }
+
+ private List<Uri> getSlices() {
+ final List<Uri> uris = new ArrayList<>();
+ uris.add(REMOTE_MEDIA_SLICE_URI);
+ uris.add(VOLUME_MEDIA_URI);
+ Uri controlUri = getExtraControlUri();
+ if (controlUri != null) {
+ Log.d(TAG, "add extra control slice");
+ uris.add(controlUri);
+ }
+ uris.add(MEDIA_OUTPUT_INDICATOR_SLICE_URI);
+ uris.add(VOLUME_CALL_URI);
+ uris.add(VOLUME_RINGER_URI);
+ uris.add(VOLUME_ALARM_URI);
+ return uris;
+ }
+
+ private static final String SETTINGS_SLICE_AUTHORITY = "com.android.settings.slices";
+ private static final Uri REMOTE_MEDIA_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SETTINGS_SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(MediaOutputConstants.KEY_REMOTE_MEDIA)
+ .build();
+ private static final Uri VOLUME_MEDIA_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SETTINGS_SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("media_volume")
+ .build();
+ private static final Uri MEDIA_OUTPUT_INDICATOR_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SETTINGS_SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_INTENT)
+ .appendPath("media_output_indicator")
+ .build();
+ private static final Uri VOLUME_CALL_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SETTINGS_SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("call_volume")
+ .build();
+ private static final Uri VOLUME_RINGER_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SETTINGS_SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("ring_volume")
+ .build();
+ private static final Uri VOLUME_ALARM_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SETTINGS_SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("alarm_volume")
+ .build();
+
+ private Uri getExtraControlUri() {
+ Uri controlUri = null;
+ final BluetoothDevice bluetoothDevice = findActiveDevice();
+ if (bluetoothDevice != null) {
+ // The control slice width = dialog width - horizontal padding of two sides
+ final int dialogWidth =
+ getWindow().getWindowManager().getCurrentWindowMetrics().getBounds().width();
+ final int controlSliceWidth = dialogWidth
+ - getContext().getResources().getDimensionPixelSize(
+ R.dimen.volume_panel_slice_horizontal_padding) * 2;
+ final String uri = BluetoothUtils.getControlUriMetaData(bluetoothDevice);
+ if (!TextUtils.isEmpty(uri)) {
+ try {
+ controlUri = Uri.parse(uri + controlSliceWidth);
+ } catch (NullPointerException exception) {
+ Log.d(TAG, "unable to parse extra control uri");
+ controlUri = null;
+ }
+ }
+ }
+ return controlUri;
+ }
+
+ private BluetoothDevice findActiveDevice() {
+ if (mProfileManager != null) {
+ final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
+ if (a2dpProfile != null) {
+ return a2dpProfile.getActiveDevice();
+ }
+ }
+ return null;
+ }
+
+ @NonNull
+ @Override
+ public Lifecycle getLifecycle() {
+ return mLifecycleRegistry;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
new file mode 100644
index 0000000..f11d5d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.provider.Settings
+import android.text.TextUtils
+import android.util.Log
+import javax.inject.Inject
+
+private const val TAG = "VolumePanelDialogReceiver"
+private const val LAUNCH_ACTION = "com.android.systemui.action.LAUNCH_VOLUME_PANEL_DIALOG"
+private const val DISMISS_ACTION = "com.android.systemui.action.DISMISS_VOLUME_PANEL_DIALOG"
+
+/**
+ * BroadcastReceiver for handling volume panel dialog intent
+ */
+class VolumePanelDialogReceiver @Inject constructor(
+ private val volumePanelFactory: VolumePanelFactory
+) : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ Log.d(TAG, "onReceive intent" + intent.action)
+ if (TextUtils.equals(LAUNCH_ACTION, intent.action) ||
+ TextUtils.equals(Settings.Panel.ACTION_VOLUME, intent.action)) {
+ volumePanelFactory.create(true, null)
+ } else if (TextUtils.equals(DISMISS_ACTION, intent.action)) {
+ volumePanelFactory.dismiss()
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt
new file mode 100644
index 0000000..c2fafbf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume
+
+import android.content.Context
+import android.util.Log
+import android.view.View
+import com.android.systemui.animation.DialogLaunchAnimator
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+
+private const val TAG = "VolumePanelFactory"
+private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
+
+/**
+ * Factory to create [VolumePanelDialog] objects. This is the dialog that allows the user to adjust
+ * multiple streams with sliders.
+ */
+@SysUISingleton
+class VolumePanelFactory @Inject constructor(
+ private val context: Context,
+ private val dialogLaunchAnimator: DialogLaunchAnimator
+) {
+ companion object {
+ var volumePanelDialog: VolumePanelDialog? = null
+ }
+
+ /** Creates a [VolumePanelDialog]. The dialog will be animated from [view] if it is not null. */
+ fun create(aboveStatusBar: Boolean, view: View? = null) {
+ if (volumePanelDialog?.isShowing == true) {
+ return
+ }
+
+ val dialog = VolumePanelDialog(context, aboveStatusBar)
+ volumePanelDialog = dialog
+
+ // Show the dialog.
+ if (view != null) {
+ dialogLaunchAnimator.showFromView(dialog, view, animateBackgroundBoundsChange = true)
+ } else {
+ dialog.show()
+ }
+ }
+
+ /** Dismiss [VolumePanelDialog] if exist. */
+ fun dismiss() {
+ if (DEBUG) {
+ Log.d(TAG, "dismiss dialog")
+ }
+ volumePanelDialog?.dismiss()
+ volumePanelDialog = null
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelSlicesAdapter.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelSlicesAdapter.java
new file mode 100644
index 0000000..2371402
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelSlicesAdapter.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume;
+
+import static android.app.slice.Slice.HINT_ERROR;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+
+import android.content.Context;
+import android.net.Uri;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LiveData;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.widget.SliceView;
+
+import com.android.systemui.R;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * RecyclerView adapter for Slices in Settings Panels.
+ */
+public class VolumePanelSlicesAdapter extends
+ RecyclerView.Adapter<VolumePanelSlicesAdapter.SliceRowViewHolder> {
+
+ private final List<LiveData<Slice>> mSliceLiveData;
+ private final LifecycleOwner mLifecycleOwner;
+ private SliceView.OnSliceActionListener mOnSliceActionListener;
+
+ public VolumePanelSlicesAdapter(LifecycleOwner lifecycleOwner,
+ Map<Uri, LiveData<Slice>> sliceLiveData) {
+ mLifecycleOwner = lifecycleOwner;
+ mSliceLiveData = new ArrayList<>(sliceLiveData.values());
+ }
+
+ @NonNull
+ @Override
+ public SliceRowViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
+ final Context context = viewGroup.getContext();
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ View view = inflater.inflate(R.layout.volume_panel_slice_slider_row, viewGroup, false);
+ return new SliceRowViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull SliceRowViewHolder sliceRowViewHolder, int position) {
+ sliceRowViewHolder.onBind(mSliceLiveData.get(position), position);
+ }
+
+ @Override
+ public int getItemCount() {
+ return mSliceLiveData.size();
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return position;
+ }
+
+ void setOnSliceActionListener(SliceView.OnSliceActionListener listener) {
+ mOnSliceActionListener = listener;
+ }
+
+ void updateDataSet(ArrayList<LiveData<Slice>> list) {
+ mSliceLiveData.clear();
+ mSliceLiveData.addAll(list);
+ notifyDataSetChanged();
+ }
+
+ /**
+ * ViewHolder for binding Slices to SliceViews.
+ */
+ public class SliceRowViewHolder extends RecyclerView.ViewHolder {
+
+ private final SliceView mSliceView;
+
+ public SliceRowViewHolder(View view) {
+ super(view);
+ mSliceView = view.findViewById(R.id.slice_view);
+ mSliceView.setMode(SliceView.MODE_LARGE);
+ mSliceView.setShowTitleItems(true);
+ mSliceView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+ mSliceView.setOnSliceActionListener(mOnSliceActionListener);
+ }
+
+ /**
+ * Called when the view is displayed.
+ */
+ public void onBind(LiveData<Slice> sliceLiveData, int position) {
+ sliceLiveData.observe(mLifecycleOwner, mSliceView);
+
+ // Do not show the divider above media devices switcher slice per request
+ final Slice slice = sliceLiveData.getValue();
+
+ // Hides slice which reports with error hint or not contain any slice sub-item.
+ if (slice == null || !isValidSlice(slice)) {
+ mSliceView.setVisibility(View.GONE);
+ } else {
+ mSliceView.setVisibility(View.VISIBLE);
+ }
+ }
+
+ private boolean isValidSlice(Slice slice) {
+ if (slice.getHints().contains(HINT_ERROR)) {
+ return false;
+ }
+ for (SliceItem item : slice.getItems()) {
+ if (item.getFormat().equals(FORMAT_SLICE)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
index f3855bd..c5792b9 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
@@ -30,6 +30,7 @@
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.volume.VolumeDialogComponent;
import com.android.systemui.volume.VolumeDialogImpl;
+import com.android.systemui.volume.VolumePanelFactory;
import dagger.Binds;
import dagger.Module;
@@ -52,6 +53,7 @@
DeviceProvisionedController deviceProvisionedController,
ConfigurationController configurationController,
MediaOutputDialogFactory mediaOutputDialogFactory,
+ VolumePanelFactory volumePanelFactory,
ActivityStarter activityStarter,
InteractionJankMonitor interactionJankMonitor) {
VolumeDialogImpl impl = new VolumeDialogImpl(
@@ -61,6 +63,7 @@
deviceProvisionedController,
configurationController,
mediaOutputDialogFactory,
+ volumePanelFactory,
activityStarter,
interactionJankMonitor);
impl.setStreamImportant(AudioManager.STREAM_SYSTEM, false);
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
index e3cd989..d03148c 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
@@ -32,7 +32,9 @@
import android.view.WindowManager;
import android.widget.Toolbar;
+import androidx.activity.ComponentActivity;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -48,7 +50,6 @@
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.LifecycleActivity;
import java.util.concurrent.Executor;
@@ -57,7 +58,7 @@
/**
* Displays Wallet carousel screen inside an activity.
*/
-public class WalletActivity extends LifecycleActivity implements
+public class WalletActivity extends ComponentActivity implements
QuickAccessWalletClient.WalletServiceEventListener {
private static final String TAG = "WalletActivity";
@@ -105,7 +106,7 @@
}
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index 199048e..8c41374 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -57,12 +57,9 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.NotificationChannelHelper;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.coordinator.BubbleCoordinator;
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
@@ -103,7 +100,6 @@
private final NotificationVisibilityProvider mVisibilityProvider;
private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private final NotificationLockscreenUserManager mNotifUserManager;
- private final NotificationGroupManagerLegacy mNotificationGroupManager;
private final CommonNotifCollection mCommonNotifCollection;
private final NotifPipeline mNotifPipeline;
private final Executor mSysuiMainExecutor;
@@ -130,7 +126,6 @@
NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
- NotificationGroupManagerLegacy groupManager,
CommonNotifCollection notifCollection,
NotifPipeline notifPipeline,
SysUiState sysUiState,
@@ -148,7 +143,6 @@
interruptionStateProvider,
zenModeController,
notifUserManager,
- groupManager,
notifCollection,
notifPipeline,
sysUiState,
@@ -171,7 +165,6 @@
NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
- NotificationGroupManagerLegacy groupManager,
CommonNotifCollection notifCollection,
NotifPipeline notifPipeline,
SysUiState sysUiState,
@@ -185,7 +178,6 @@
mVisibilityProvider = visibilityProvider;
mNotificationInterruptStateProvider = interruptionStateProvider;
mNotifUserManager = notifUserManager;
- mNotificationGroupManager = groupManager;
mCommonNotifCollection = notifCollection;
mNotifPipeline = notifPipeline;
mSysuiMainExecutor = sysuiMainExecutor;
@@ -331,16 +323,6 @@
}
@Override
- public void removeNotificationEntry(String key) {
- sysuiMainExecutor.execute(() -> {
- final NotificationEntry entry = mCommonNotifCollection.getEntry(key);
- if (entry != null) {
- mNotificationGroupManager.onEntryRemoved(entry);
- }
- });
- }
-
- @Override
public void updateNotificationBubbleButton(String key) {
sysuiMainExecutor.execute(() -> {
final NotificationEntry entry = mCommonNotifCollection.getEntry(key);
@@ -351,16 +333,6 @@
}
@Override
- public void updateNotificationSuppression(String key) {
- sysuiMainExecutor.execute(() -> {
- final NotificationEntry entry = mCommonNotifCollection.getEntry(key);
- if (entry != null) {
- mNotificationGroupManager.updateSuppression(entry);
- }
- });
- }
-
- @Override
public void onStackExpandChanged(boolean shouldExpand) {
sysuiMainExecutor.execute(() -> {
sysUiState.setFlag(QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED, shouldExpand)
@@ -486,11 +458,6 @@
mBubbles.onNotificationChannelModified(pkg, user, channel, modificationType);
}
- /**
- * Gets the DismissedByUserStats used by {@link NotificationEntryManager}.
- * Will not be necessary when using the new notification pipeline's {@link NotifCollection}.
- * Instead, this is taken care of by {@link BubbleCoordinator}.
- */
private DismissedByUserStats getDismissedByUserStats(
NotificationEntry entry,
boolean isVisible) {
@@ -532,7 +499,10 @@
REASON_GROUP_SUMMARY_CANCELED);
}
} else {
- mNotificationGroupManager.onEntryRemoved(entry);
+ for (NotifCallback cb : mCallbacks) {
+ cb.removeNotification(entry, getDismissedByUserStats(entry, true),
+ REASON_GROUP_SUMMARY_CANCELED);
+ }
}
}, mSysuiMainExecutor);
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index a4a59fc..3961a8b 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -34,7 +34,6 @@
import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
import android.view.KeyEvent;
import androidx.annotation.NonNull;
@@ -62,12 +61,10 @@
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.onehanded.OneHandedUiEventLogger;
import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.protolog.ShellProtoLogImpl;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.sysui.ShellInterface;
import java.io.PrintWriter;
-import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executor;
@@ -336,44 +333,7 @@
if (mShell.handleCommand(args, pw)) {
return;
}
- // Handle logging commands if provided
- if (handleLoggingCommand(args, pw)) {
- return;
- }
// Dump WMShell stuff here if no commands were handled
mShell.dump(pw);
}
-
- @Override
- public void handleWindowManagerLoggingCommand(String[] args, ParcelFileDescriptor outFd) {
- PrintWriter pw = new PrintWriter(new ParcelFileDescriptor.AutoCloseOutputStream(outFd));
- handleLoggingCommand(args, pw);
- pw.flush();
- pw.close();
- }
-
- private boolean handleLoggingCommand(String[] args, PrintWriter pw) {
- ShellProtoLogImpl protoLogImpl = ShellProtoLogImpl.getSingleInstance();
- for (int i = 0; i < args.length; i++) {
- switch (args[i]) {
- case "enable-text": {
- String[] groups = Arrays.copyOfRange(args, i + 1, args.length);
- int result = protoLogImpl.startTextLogging(groups, pw);
- if (result == 0) {
- pw.println("Starting logging on groups: " + Arrays.toString(groups));
- }
- return true;
- }
- case "disable-text": {
- String[] groups = Arrays.copyOfRange(args, i + 1, args.length);
- int result = protoLogImpl.stopTextLogging(groups, pw);
- if (result == 0) {
- pw.println("Stopping logging on groups: " + Arrays.toString(groups));
- }
- return true;
- }
- }
- }
- return false;
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
new file mode 100644
index 0000000..914d945
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.keyguard
+
+import android.content.BroadcastReceiver
+import android.testing.AndroidTestingRunner
+import android.widget.TextView
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.plugins.Clock
+import com.android.systemui.plugins.ClockAnimations
+import com.android.systemui.plugins.ClockEvents
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import java.util.TimeZone
+import java.util.concurrent.Executor
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyFloat
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.junit.MockitoJUnit
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class ClockEventControllerTest : SysuiTestCase() {
+
+ @JvmField @Rule val mockito = MockitoJUnit.rule()
+ @Mock private lateinit var statusBarStateController: StatusBarStateController
+ @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
+ @Mock private lateinit var batteryController: BatteryController
+ @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ @Mock private lateinit var configurationController: ConfigurationController
+ @Mock private lateinit var animations: ClockAnimations
+ @Mock private lateinit var events: ClockEvents
+ @Mock private lateinit var clock: Clock
+ @Mock private lateinit var mainExecutor: Executor
+ @Mock private lateinit var bgExecutor: Executor
+ @Mock private lateinit var featureFlags: FeatureFlags
+
+ private lateinit var clockEventController: ClockEventController
+
+ @Before
+ fun setUp() {
+ whenever(clock.smallClock).thenReturn(TextView(context))
+ whenever(clock.largeClock).thenReturn(TextView(context))
+ whenever(clock.events).thenReturn(events)
+ whenever(clock.animations).thenReturn(animations)
+
+ clockEventController = ClockEventController(
+ statusBarStateController,
+ broadcastDispatcher,
+ batteryController,
+ keyguardUpdateMonitor,
+ configurationController,
+ context.resources,
+ context,
+ mainExecutor,
+ bgExecutor,
+ featureFlags
+ )
+ }
+
+ @Test
+ fun clockSet_validateInitialization() {
+ clockEventController.clock = clock
+
+ verify(clock).initialize(any(), anyFloat(), anyFloat())
+ }
+
+ @Test
+ fun clockUnset_validateState() {
+ clockEventController.clock = clock
+ clockEventController.clock = null
+
+ assertEquals(clockEventController.clock, null)
+ }
+
+ @Test
+ fun themeChanged_verifyClockPaletteUpdated() {
+ clockEventController.clock = clock
+ verify(events).onColorPaletteChanged(any(), any(), any())
+
+ clockEventController.registerListeners()
+
+ val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
+ verify(configurationController).addCallback(capture(captor))
+ captor.value.onThemeChanged()
+
+ verify(events, times(2)).onColorPaletteChanged(any(), any(), any())
+ }
+
+ @Test
+ fun batteryCallback_keyguardShowingCharging_verifyChargeAnimation() {
+ clockEventController.clock = clock
+ clockEventController.registerListeners()
+
+ val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
+ verify(batteryController).addCallback(capture(batteryCaptor))
+ val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
+ keyguardCaptor.value.onKeyguardVisibilityChanged(true)
+ batteryCaptor.value.onBatteryLevelChanged(10, false, true)
+
+ verify(animations).charge()
+ }
+
+ @Test
+ fun batteryCallback_keyguardShowingCharging_Duplicate_verifyChargeAnimation() {
+ clockEventController.clock = clock
+ clockEventController.registerListeners()
+
+ val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
+ verify(batteryController).addCallback(capture(batteryCaptor))
+ val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
+ keyguardCaptor.value.onKeyguardVisibilityChanged(true)
+ batteryCaptor.value.onBatteryLevelChanged(10, false, true)
+ batteryCaptor.value.onBatteryLevelChanged(10, false, true)
+
+ verify(animations, times(1)).charge()
+ }
+
+ @Test
+ fun batteryCallback_keyguardHiddenCharging_verifyChargeAnimation() {
+ clockEventController.clock = clock
+ clockEventController.registerListeners()
+
+ val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
+ verify(batteryController).addCallback(capture(batteryCaptor))
+ val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
+ keyguardCaptor.value.onKeyguardVisibilityChanged(false)
+ batteryCaptor.value.onBatteryLevelChanged(10, false, true)
+
+ verify(animations, never()).charge()
+ }
+
+ @Test
+ fun batteryCallback_keyguardShowingNotCharging_verifyChargeAnimation() {
+ clockEventController.clock = clock
+ clockEventController.registerListeners()
+
+ val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
+ verify(batteryController).addCallback(capture(batteryCaptor))
+ val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
+ keyguardCaptor.value.onKeyguardVisibilityChanged(true)
+ batteryCaptor.value.onBatteryLevelChanged(10, false, false)
+
+ verify(animations, never()).charge()
+ }
+
+ @Test
+ fun localeCallback_verifyClockNotified() {
+ clockEventController.clock = clock
+ clockEventController.registerListeners()
+
+ val captor = argumentCaptor<BroadcastReceiver>()
+ verify(broadcastDispatcher).registerReceiver(
+ capture(captor), any(), eq(null), eq(null), anyInt(), eq(null)
+ )
+ captor.value.onReceive(context, mock())
+
+ verify(events).onLocaleChanged(any())
+ }
+
+ @Test
+ fun keyguardCallback_visibilityChanged_clockDozeCalled() {
+ clockEventController.clock = clock
+ clockEventController.registerListeners()
+
+ val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ verify(keyguardUpdateMonitor).registerCallback(capture(captor))
+
+ captor.value.onKeyguardVisibilityChanged(true)
+ verify(animations, never()).doze(0f)
+
+ captor.value.onKeyguardVisibilityChanged(false)
+ verify(animations, times(1)).doze(0f)
+ }
+
+ @Test
+ fun keyguardCallback_timeFormat_clockNotified() {
+ clockEventController.clock = clock
+ clockEventController.registerListeners()
+
+ val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ verify(keyguardUpdateMonitor).registerCallback(capture(captor))
+ captor.value.onTimeFormatChanged("12h")
+
+ verify(events).onTimeFormatChanged(false)
+ }
+
+ @Test
+ fun keyguardCallback_timezoneChanged_clockNotified() {
+ val mockTimeZone = mock<TimeZone>()
+ clockEventController.clock = clock
+ clockEventController.registerListeners()
+
+ val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ verify(keyguardUpdateMonitor).registerCallback(capture(captor))
+ captor.value.onTimeZoneChanged(mockTimeZone)
+
+ verify(events).onTimeZoneChanged(mockTimeZone)
+ }
+
+ @Test
+ fun keyguardCallback_userSwitched_clockNotified() {
+ clockEventController.clock = clock
+ clockEventController.registerListeners()
+
+ val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ verify(keyguardUpdateMonitor).registerCallback(capture(captor))
+ captor.value.onUserSwitchComplete(10)
+
+ verify(events).onTimeFormatChanged(false)
+ }
+
+ @Test
+ fun keyguardCallback_verifyKeyguardChanged() {
+ clockEventController.clock = clock
+ clockEventController.registerListeners()
+
+ val captor = argumentCaptor<StatusBarStateController.StateListener>()
+ verify(statusBarStateController).addCallback(capture(captor))
+ captor.value.onDozeAmountChanged(0.4f, 0.6f)
+
+ verify(animations).doze(0.4f)
+ }
+
+ @Test
+ fun unregisterListeners_validate() {
+ clockEventController.clock = clock
+ clockEventController.unregisterListeners()
+ verify(broadcastDispatcher).unregisterReceiver(any())
+ verify(configurationController).removeCallback(any())
+ verify(batteryController).removeCallback(any())
+ verify(keyguardUpdateMonitor).removeCallback(any())
+ verify(statusBarStateController).removeCallback(any())
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index b2d9219..635ee9e 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -19,7 +19,6 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -41,24 +40,19 @@
import androidx.test.filters.SmallTest;
-import com.android.internal.colorextraction.ColorExtractor;
-import com.android.keyguard.clock.ClockManager;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.plugins.Clock;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.clocks.AnimatableClockView;
+import com.android.systemui.shared.clocks.ClockRegistry;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
-import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.FakeSystemClock;
@@ -80,22 +74,12 @@
@Mock
private StatusBarStateController mStatusBarStateController;
@Mock
- private SysuiColorExtractor mColorExtractor;
- @Mock
- private ClockManager mClockManager;
+ private ClockRegistry mClockRegistry;
@Mock
KeyguardSliceViewController mKeyguardSliceViewController;
@Mock
NotificationIconAreaController mNotificationIconAreaController;
@Mock
- BroadcastDispatcher mBroadcastDispatcher;
- @Mock
- BatteryController mBatteryController;
- @Mock
- KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- @Mock
- KeyguardBypassController mBypassController;
- @Mock
LockscreenSmartspaceController mSmartspaceController;
@Mock
@@ -103,11 +87,11 @@
@Mock
KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
@Mock
- private ClockPlugin mClockPlugin;
- @Mock
- ColorExtractor.GradientColors mGradientColors;
+ private Clock mClock;
@Mock
DumpManager mDumpManager;
+ @Mock
+ ClockEventController mClockEventController;
@Mock
private NotificationIconContainer mNotificationIcons;
@@ -139,8 +123,6 @@
when(mView.getContext()).thenReturn(getContext());
when(mView.getResources()).thenReturn(mResources);
- when(mView.findViewById(R.id.animatable_clock_view)).thenReturn(mClockView);
- when(mView.findViewById(R.id.animatable_clock_view_large)).thenReturn(mLargeClockView);
when(mView.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(mLargeClockFrame);
when(mClockView.getContext()).thenReturn(getContext());
when(mLargeClockView.getContext()).thenReturn(getContext());
@@ -151,23 +133,20 @@
mController = new KeyguardClockSwitchController(
mView,
mStatusBarStateController,
- mColorExtractor,
- mClockManager,
+ mClockRegistry,
mKeyguardSliceViewController,
mNotificationIconAreaController,
- mBroadcastDispatcher,
- mBatteryController,
- mKeyguardUpdateMonitor,
mSmartspaceController,
mKeyguardUnlockAnimationController,
mSecureSettings,
mExecutor,
- mResources,
- mDumpManager
+ mDumpManager,
+ mClockEventController,
+ mFeatureFlags
);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
- when(mColorExtractor.getColors(anyInt())).thenReturn(mGradientColors);
+ when(mClockRegistry.createCurrentClock()).thenReturn(mClock);
mSliceView = new View(getContext());
when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView);
@@ -214,20 +193,20 @@
verifyAttachment(times(1));
listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
- verify(mColorExtractor).removeOnColorsChangedListener(
- any(ColorExtractor.OnColorsChangedListener.class));
+ verify(mClockEventController).unregisterListeners();
}
@Test
public void testPluginPassesStatusBarState() {
- ArgumentCaptor<ClockManager.ClockChangedListener> listenerArgumentCaptor =
- ArgumentCaptor.forClass(ClockManager.ClockChangedListener.class);
+ ArgumentCaptor<ClockRegistry.ClockChangeListener> listenerArgumentCaptor =
+ ArgumentCaptor.forClass(ClockRegistry.ClockChangeListener.class);
mController.init();
- verify(mClockManager).addOnClockChangedListener(listenerArgumentCaptor.capture());
+ verify(mClockRegistry).registerClockChangeListener(listenerArgumentCaptor.capture());
- listenerArgumentCaptor.getValue().onClockChanged(mClockPlugin);
- verify(mView).setClockPlugin(mClockPlugin, StatusBarState.SHADE);
+ listenerArgumentCaptor.getValue().onClockChanged();
+ verify(mView, times(2)).setClock(mClock, StatusBarState.SHADE);
+ verify(mClockEventController, times(2)).setClock(mClock);
}
@Test
@@ -284,10 +263,8 @@
}
private void verifyAttachment(VerificationMode times) {
- verify(mClockManager, times).addOnClockChangedListener(
- any(ClockManager.ClockChangedListener.class));
- verify(mColorExtractor, times).addOnColorsChangedListener(
- any(ColorExtractor.OnColorsChangedListener.class));
- verify(mView, times).updateColors(mGradientColors);
+ verify(mClockRegistry, times).registerClockChangeListener(
+ any(ClockRegistry.ClockChangeListener.class));
+ verify(mClockEventController, times).registerListeners();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index 6c6f0ac..a0295d0 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -16,7 +16,6 @@
package com.android.keyguard;
-import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
@@ -24,56 +23,61 @@
import static com.google.common.truth.Truth.assertThat;
+import static junit.framework.TestCase.assertEquals;
+
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
-import android.graphics.Color;
-import android.graphics.Paint.Style;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.FrameLayout;
-import android.widget.TextClock;
+import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.ClockPlugin;
-import com.android.systemui.shared.clocks.AnimatableClockView;
+import com.android.systemui.plugins.Clock;
import com.android.systemui.statusbar.StatusBarState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
// Need to run on the main thread because KeyguardSliceView$Row init checks for
// the main thread before acquiring a wake lock. This class is constructed when
-// the keyguard_clcok_switch layout is inflated.
+// the keyguard_clock_switch layout is inflated.
@RunWithLooper(setAsMainLooper = true)
public class KeyguardClockSwitchTest extends SysuiTestCase {
- private FrameLayout mClockFrame;
- private FrameLayout mLargeClockFrame;
- private TextClock mBigClock;
+ @Mock
+ ViewGroup mMockKeyguardSliceView;
- private AnimatableClockView mClockView;
- private AnimatableClockView mLargeClockView;
- View mMockKeyguardSliceView;
+ @Mock
+ Clock mClock;
+
+ private FrameLayout mSmallClockFrame;
+ private FrameLayout mLargeClockFrame;
+
KeyguardClockSwitch mKeyguardClockSwitch;
@Before
public void setUp() {
- mMockKeyguardSliceView = mock(KeyguardSliceView.class);
+ MockitoAnnotations.initMocks(this);
when(mMockKeyguardSliceView.getContext()).thenReturn(mContext);
when(mMockKeyguardSliceView.findViewById(R.id.keyguard_status_area))
.thenReturn(mMockKeyguardSliceView);
+ when(mClock.getSmallClock()).thenReturn(new TextView(getContext()));
+ when(mClock.getLargeClock()).thenReturn(new TextView(getContext()));
+
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
layoutInflater.setPrivateFactory(new LayoutInflater.Factory2() {
@@ -93,164 +97,68 @@
});
mKeyguardClockSwitch =
(KeyguardClockSwitch) layoutInflater.inflate(R.layout.keyguard_clock_switch, null);
- mClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view);
- mClockView = mKeyguardClockSwitch.findViewById(R.id.animatable_clock_view);
+ mSmallClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view);
mLargeClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view_large);
- mLargeClockView = mKeyguardClockSwitch.findViewById(R.id.animatable_clock_view_large);
- mBigClock = new TextClock(getContext());
mKeyguardClockSwitch.mChildrenAreLaidOut = true;
- MockitoAnnotations.initMocks(this);
}
@Test
- public void onPluginConnected_showPluginClock() {
- ClockPlugin plugin = mock(ClockPlugin.class);
- TextClock pluginView = new TextClock(getContext());
- when(plugin.getView()).thenReturn(pluginView);
-
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
-
- assertThat(mClockView.getVisibility()).isEqualTo(GONE);
- assertThat(plugin.getView().getParent()).isEqualTo(mClockFrame);
+ public void noPluginConnected_showNothing() {
+ mKeyguardClockSwitch.setClock(null, StatusBarState.KEYGUARD);
+ assertEquals(mLargeClockFrame.getChildCount(), 0);
+ assertEquals(mSmallClockFrame.getChildCount(), 0);
}
@Test
- public void onPluginConnected_showPluginBigClock() {
- // GIVEN the plugin returns a view for the big clock
- ClockPlugin plugin = mock(ClockPlugin.class);
- when(plugin.getBigClockView()).thenReturn(mBigClock);
- // WHEN the plugin is connected
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- // THEN the big clock container is visible and it is the parent of the
- // big clock view.
- assertThat(mLargeClockView.getVisibility()).isEqualTo(View.GONE);
- assertThat(mBigClock.getParent()).isEqualTo(mLargeClockFrame);
+ public void pluginConnectedThenDisconnected_showNothing() {
+ mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD);
+ assertEquals(mLargeClockFrame.getChildCount(), 1);
+ assertEquals(mSmallClockFrame.getChildCount(), 1);
+
+ mKeyguardClockSwitch.setClock(null, StatusBarState.KEYGUARD);
+ assertEquals(mLargeClockFrame.getChildCount(), 0);
+ assertEquals(mSmallClockFrame.getChildCount(), 0);
}
@Test
- public void onPluginConnected_nullView() {
- ClockPlugin plugin = mock(ClockPlugin.class);
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
+ public void onPluginConnected_showClock() {
+ mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD);
+
+ assertEquals(mClock.getSmallClock().getParent(), mSmallClockFrame);
+ assertEquals(mClock.getLargeClock().getParent(), mLargeClockFrame);
}
@Test
public void onPluginConnected_showSecondPluginClock() {
// GIVEN a plugin has already connected
- ClockPlugin plugin1 = mock(ClockPlugin.class);
- when(plugin1.getView()).thenReturn(new TextClock(getContext()));
- mKeyguardClockSwitch.setClockPlugin(plugin1, StatusBarState.KEYGUARD);
- // WHEN a second plugin is connected
- ClockPlugin plugin2 = mock(ClockPlugin.class);
- when(plugin2.getView()).thenReturn(new TextClock(getContext()));
- mKeyguardClockSwitch.setClockPlugin(plugin2, StatusBarState.KEYGUARD);
+ Clock otherClock = mock(Clock.class);
+ when(otherClock.getSmallClock()).thenReturn(new TextView(getContext()));
+ when(otherClock.getLargeClock()).thenReturn(new TextView(getContext()));
+ mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD);
+ mKeyguardClockSwitch.setClock(otherClock, StatusBarState.KEYGUARD);
+
// THEN only the view from the second plugin should be a child of KeyguardClockSwitch.
- assertThat(plugin2.getView().getParent()).isEqualTo(mClockFrame);
- assertThat(plugin1.getView().getParent()).isNull();
- }
-
- @Test
- public void onPluginConnected_darkAmountInitialized() {
- // GIVEN that the dark amount has already been set
- mKeyguardClockSwitch.setDarkAmount(0.5f);
- // WHEN a plugin is connected
- ClockPlugin plugin = mock(ClockPlugin.class);
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- // THEN dark amount should be initalized on the plugin.
- verify(plugin).setDarkAmount(0.5f);
- }
-
- @Test
- public void onPluginDisconnected_showDefaultClock() {
- ClockPlugin plugin = mock(ClockPlugin.class);
- TextClock pluginView = new TextClock(getContext());
- when(plugin.getView()).thenReturn(pluginView);
-
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- assertThat(mClockView.getVisibility()).isEqualTo(GONE);
-
- mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
- assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
-
- assertThat(plugin.getView().getParent()).isNull();
- }
-
- @Test
- public void onPluginDisconnected_hidePluginBigClock() {
- // GIVEN the plugin returns a view for the big clock
- ClockPlugin plugin = mock(ClockPlugin.class);
- TextClock pluginView = new TextClock(getContext());
- when(plugin.getBigClockView()).thenReturn(pluginView);
- // WHEN the plugin is connected and then disconnected
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
- // THEN the big lock container is GONE and the big clock view doesn't have
- // a parent.
- assertThat(mLargeClockView.getVisibility()).isEqualTo(VISIBLE);
- assertThat(pluginView.getParent()).isNull();
- }
-
- @Test
- public void onPluginDisconnected_nullView() {
- ClockPlugin plugin = mock(ClockPlugin.class);
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
- assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
+ assertThat(otherClock.getSmallClock().getParent()).isEqualTo(mSmallClockFrame);
+ assertThat(otherClock.getLargeClock().getParent()).isEqualTo(mLargeClockFrame);
+ assertThat(mClock.getSmallClock().getParent()).isNull();
+ assertThat(mClock.getLargeClock().getParent()).isNull();
}
@Test
public void onPluginDisconnected_secondOfTwoDisconnected() {
// GIVEN two plugins are connected
- ClockPlugin plugin1 = mock(ClockPlugin.class);
- when(plugin1.getView()).thenReturn(new TextClock(getContext()));
- mKeyguardClockSwitch.setClockPlugin(plugin1, StatusBarState.KEYGUARD);
- ClockPlugin plugin2 = mock(ClockPlugin.class);
- when(plugin2.getView()).thenReturn(new TextClock(getContext()));
- mKeyguardClockSwitch.setClockPlugin(plugin2, StatusBarState.KEYGUARD);
+ Clock otherClock = mock(Clock.class);
+ when(otherClock.getSmallClock()).thenReturn(new TextView(getContext()));
+ when(otherClock.getLargeClock()).thenReturn(new TextView(getContext()));
+ mKeyguardClockSwitch.setClock(otherClock, StatusBarState.KEYGUARD);
+ mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD);
// WHEN the second plugin is disconnected
- mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
- // THEN the default clock should be shown.
- assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
- assertThat(plugin1.getView().getParent()).isNull();
- assertThat(plugin2.getView().getParent()).isNull();
- }
-
- @Test
- public void onPluginDisconnected_onDestroyView() {
- // GIVEN a plugin is connected
- ClockPlugin clockPlugin = mock(ClockPlugin.class);
- when(clockPlugin.getView()).thenReturn(new TextClock(getContext()));
- mKeyguardClockSwitch.setClockPlugin(clockPlugin, StatusBarState.KEYGUARD);
- // WHEN the plugin is disconnected
- mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
- // THEN onDestroyView is called on the plugin
- verify(clockPlugin).onDestroyView();
- }
-
- @Test
- public void setTextColor_pluginClockSetTextColor() {
- ClockPlugin plugin = mock(ClockPlugin.class);
- TextClock pluginView = new TextClock(getContext());
- when(plugin.getView()).thenReturn(pluginView);
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
-
- mKeyguardClockSwitch.setTextColor(Color.WHITE);
-
- verify(plugin).setTextColor(Color.WHITE);
- }
-
-
- @Test
- public void setStyle_pluginClockSetStyle() {
- ClockPlugin plugin = mock(ClockPlugin.class);
- TextClock pluginView = new TextClock(getContext());
- when(plugin.getView()).thenReturn(pluginView);
- Style style = mock(Style.class);
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
-
- mKeyguardClockSwitch.setStyle(style);
-
- verify(plugin).setStyle(style);
+ mKeyguardClockSwitch.setClock(null, StatusBarState.KEYGUARD);
+ // THEN nothing should be shown
+ assertThat(otherClock.getSmallClock().getParent()).isNull();
+ assertThat(otherClock.getLargeClock().getParent()).isNull();
+ assertThat(mClock.getSmallClock().getParent()).isNull();
+ assertThat(mClock.getLargeClock().getParent()).isNull();
}
@Test
@@ -262,7 +170,7 @@
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(1);
assertThat(mLargeClockFrame.getVisibility()).isEqualTo(VISIBLE);
- assertThat(mClockFrame.getAlpha()).isEqualTo(0);
+ assertThat(mSmallClockFrame.getAlpha()).isEqualTo(0);
}
@Test
@@ -271,7 +179,7 @@
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(1);
assertThat(mLargeClockFrame.getVisibility()).isEqualTo(VISIBLE);
- assertThat(mClockFrame.getAlpha()).isEqualTo(0);
+ assertThat(mSmallClockFrame.getAlpha()).isEqualTo(0);
}
@Test
@@ -281,8 +189,8 @@
mKeyguardClockSwitch.mClockInAnim.end();
mKeyguardClockSwitch.mClockOutAnim.end();
- assertThat(mClockFrame.getAlpha()).isEqualTo(1);
- assertThat(mClockFrame.getVisibility()).isEqualTo(VISIBLE);
+ assertThat(mSmallClockFrame.getAlpha()).isEqualTo(1);
+ assertThat(mSmallClockFrame.getVisibility()).isEqualTo(VISIBLE);
// only big clock is removed at switch
assertThat(mLargeClockFrame.getParent()).isNull();
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(0);
@@ -292,8 +200,8 @@
public void switchingToSmallClockNoAnimation_makesBigClockDisappear() {
mKeyguardClockSwitch.switchToClock(SMALL, false);
- assertThat(mClockFrame.getAlpha()).isEqualTo(1);
- assertThat(mClockFrame.getVisibility()).isEqualTo(VISIBLE);
+ assertThat(mSmallClockFrame.getAlpha()).isEqualTo(1);
+ assertThat(mSmallClockFrame.getVisibility()).isEqualTo(VISIBLE);
// only big clock is removed at switch
assertThat(mLargeClockFrame.getParent()).isNull();
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(0);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index aecec9d..d68e8bd 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -387,6 +387,33 @@
}
@Test
+ public void onResume_sideFpsHintShouldBeShown_sideFpsHintShown() {
+ setupGetSecurityView();
+ setupConditionsToEnableSideFpsHint();
+ mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
+ reset(mSidefpsController);
+
+ mKeyguardSecurityContainerController.onResume(0);
+
+ verify(mSidefpsController).show();
+ verify(mSidefpsController, never()).hide();
+ }
+
+ @Test
+ public void onResume_sideFpsHintShouldNotBeShown_sideFpsHintHidden() {
+ setupGetSecurityView();
+ setupConditionsToEnableSideFpsHint();
+ setSideFpsHintEnabledFromResources(false);
+ mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
+ reset(mSidefpsController);
+
+ mKeyguardSecurityContainerController.onResume(0);
+
+ verify(mSidefpsController).hide();
+ verify(mSidefpsController, never()).show();
+ }
+
+ @Test
public void showNextSecurityScreenOrFinish_setsSecurityScreenToPinAfterSimPinUnlock() {
// GIVEN the current security method is SimPin
when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index f2ac0c7..28e99da 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -57,7 +57,7 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.UserSwitcherController.UserRecord;
+import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.util.settings.GlobalSettings;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt
new file mode 100644
index 0000000..6b1ef38
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt
@@ -0,0 +1,179 @@
+package com.android.systemui
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.PackageManager
+import android.content.res.Resources
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flag
+import com.android.systemui.flags.FlagListenable
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.UnreleasedFlag
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.kotlinArgumentCaptor
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.test.TestCoroutineDispatcher
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class ChooserSelectorTest : SysuiTestCase() {
+
+ private val flagListener = kotlinArgumentCaptor<FlagListenable.Listener>()
+
+ private val testDispatcher = TestCoroutineDispatcher()
+ private val testScope = CoroutineScope(testDispatcher)
+
+ private lateinit var chooserSelector: ChooserSelector
+
+ @Mock private lateinit var mockContext: Context
+ @Mock private lateinit var mockPackageManager: PackageManager
+ @Mock private lateinit var mockResources: Resources
+ @Mock private lateinit var mockFeatureFlags: FeatureFlags
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+
+ `when`(mockContext.packageManager).thenReturn(mockPackageManager)
+ `when`(mockContext.resources).thenReturn(mockResources)
+ `when`(mockResources.getString(anyInt())).thenReturn(
+ ComponentName("TestPackage", "TestClass").flattenToString())
+
+ chooserSelector = ChooserSelector(mockContext, mockFeatureFlags, testScope, testDispatcher)
+ }
+
+ @After
+ fun tearDown() {
+ testDispatcher.cleanupTestCoroutines()
+ }
+
+ @Test
+ fun initialize_registersFlagListenerUntilScopeCancelled() {
+ // Arrange
+
+ // Act
+ chooserSelector.start()
+
+ // Assert
+ verify(mockFeatureFlags).addListener(
+ eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED), flagListener.capture())
+ verify(mockFeatureFlags, never()).removeListener(any())
+
+ // Act
+ testScope.cancel()
+
+ // Assert
+ verify(mockFeatureFlags).removeListener(eq(flagListener.value))
+ }
+
+ @Test
+ fun initialize_enablesUnbundledChooser_whenFlagEnabled() {
+ // Arrange
+ `when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
+
+ // Act
+ chooserSelector.start()
+
+ // Assert
+ verify(mockPackageManager).setComponentEnabledSetting(
+ eq(ComponentName("TestPackage", "TestClass")),
+ eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED),
+ anyInt())
+ }
+
+ @Test
+ fun initialize_disablesUnbundledChooser_whenFlagDisabled() {
+ // Arrange
+ `when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
+
+ // Act
+ chooserSelector.start()
+
+ // Assert
+ verify(mockPackageManager).setComponentEnabledSetting(
+ eq(ComponentName("TestPackage", "TestClass")),
+ eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED),
+ anyInt())
+ }
+
+ @Test
+ fun enablesUnbundledChooser_whenFlagBecomesEnabled() {
+ // Arrange
+ `when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
+ chooserSelector.start()
+ verify(mockFeatureFlags).addListener(
+ eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED), flagListener.capture())
+ verify(mockPackageManager, never()).setComponentEnabledSetting(
+ any(), eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED), anyInt())
+
+ // Act
+ `when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
+ flagListener.value.onFlagChanged(TestFlagEvent(Flags.CHOOSER_UNBUNDLED.id))
+
+ // Assert
+ verify(mockPackageManager).setComponentEnabledSetting(
+ eq(ComponentName("TestPackage", "TestClass")),
+ eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED),
+ anyInt())
+ }
+
+ @Test
+ fun disablesUnbundledChooser_whenFlagBecomesDisabled() {
+ // Arrange
+ `when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
+ chooserSelector.start()
+ verify(mockFeatureFlags).addListener(
+ eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED), flagListener.capture())
+ verify(mockPackageManager, never()).setComponentEnabledSetting(
+ any(), eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED), anyInt())
+
+ // Act
+ `when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
+ flagListener.value.onFlagChanged(TestFlagEvent(Flags.CHOOSER_UNBUNDLED.id))
+
+ // Assert
+ verify(mockPackageManager).setComponentEnabledSetting(
+ eq(ComponentName("TestPackage", "TestClass")),
+ eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED),
+ anyInt())
+ }
+
+ @Test
+ fun doesNothing_whenAnotherFlagChanges() {
+ // Arrange
+ `when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
+ chooserSelector.start()
+ verify(mockFeatureFlags).addListener(
+ eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED), flagListener.capture())
+ clearInvocations(mockPackageManager)
+
+ // Act
+ `when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
+ flagListener.value.onFlagChanged(TestFlagEvent(Flags.CHOOSER_UNBUNDLED.id + 1))
+
+ // Assert
+ verifyZeroInteractions(mockPackageManager)
+ }
+
+ private class TestFlagEvent(override val flagId: Int) : FlagListenable.FlagEvent {
+ override fun requestNoRestart() {}
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index ba21afd..b47b08c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -44,12 +44,10 @@
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.statusbar.notification.NotificationEntryListener;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.util.time.FakeSystemClock;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import org.junit.Before;
import org.junit.Test;
@@ -64,9 +62,7 @@
public class ForegroundServiceControllerTest extends SysuiTestCase {
private ForegroundServiceController mFsc;
private ForegroundServiceNotificationListener mListener;
- private NotificationEntryListener mEntryListener;
- private final FakeSystemClock mClock = new FakeSystemClock();
- @Mock private NotificationEntryManager mEntryManager;
+ private NotifCollectionListener mCollectionListener;
@Mock private AppOpsController mAppOpsController;
@Mock private Handler mMainHandler;
@Mock private NotifPipeline mNotifPipeline;
@@ -79,12 +75,13 @@
MockitoAnnotations.initMocks(this);
mFsc = new ForegroundServiceController(mAppOpsController, mMainHandler);
mListener = new ForegroundServiceNotificationListener(
- mContext, mFsc, mEntryManager, mNotifPipeline, mClock);
- ArgumentCaptor<NotificationEntryListener> entryListenerCaptor =
- ArgumentCaptor.forClass(NotificationEntryListener.class);
- verify(mEntryManager).addNotificationEntryListener(
+ mContext, mFsc, mNotifPipeline);
+ mListener.init();
+ ArgumentCaptor<NotifCollectionListener> entryListenerCaptor =
+ ArgumentCaptor.forClass(NotifCollectionListener.class);
+ verify(mNotifPipeline).addCollectionListener(
entryListenerCaptor.capture());
- mEntryListener = entryListenerCaptor.getValue();
+ mCollectionListener = entryListenerCaptor.getValue();
}
@Test
@@ -449,7 +446,7 @@
private NotificationEntry addFgEntry() {
NotificationEntry entry = createFgEntry();
- mEntryListener.onPendingEntryAdded(entry);
+ mCollectionListener.onEntryAdded(entry);
return entry;
}
@@ -461,12 +458,10 @@
}
private void entryRemoved(StatusBarNotification notification) {
- mEntryListener.onEntryRemoved(
+ mCollectionListener.onEntryRemoved(
new NotificationEntryBuilder()
.setSbn(notification)
.build(),
- null,
- false,
REASON_APP_CANCEL);
}
@@ -475,7 +470,7 @@
.setSbn(notification)
.setImportance(importance)
.build();
- mEntryListener.onPendingEntryAdded(entry);
+ mCollectionListener.onEntryAdded(entry);
}
private void entryUpdated(StatusBarNotification notification, int importance) {
@@ -483,7 +478,7 @@
.setSbn(notification)
.setImportance(importance)
.build();
- mEntryListener.onPreEntryUpdated(entry);
+ mCollectionListener.onEntryUpdated(entry);
}
@UserIdInt private static final int USERID_ONE = 10; // UserManagerService.MIN_USER_ID;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index 90609fa..df10dfe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -16,7 +16,6 @@
import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM;
import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
-import static android.view.DisplayCutout.BOUNDS_POSITION_LENGTH;
import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT;
import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
@@ -36,6 +35,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -49,7 +49,6 @@
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.TypedArray;
-import android.graphics.Insets;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -60,7 +59,6 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
-import android.util.RotationUtils;
import android.util.Size;
import android.view.Display;
import android.view.DisplayCutout;
@@ -80,6 +78,8 @@
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.decor.CornerDecorProvider;
+import com.android.systemui.decor.CutoutDecorProviderFactory;
+import com.android.systemui.decor.CutoutDecorProviderImpl;
import com.android.systemui.decor.DecorProvider;
import com.android.systemui.decor.DecorProviderFactory;
import com.android.systemui.decor.FaceScanningOverlayProviderImpl;
@@ -157,6 +157,9 @@
@Mock
private DisplayInfo mDisplayInfo;
private PrivacyDotViewController.ShowingListener mPrivacyDotShowingListener;
+ @Mock
+ private CutoutDecorProviderFactory mCutoutFactory;
+ private List<DecorProvider> mMockCutoutList;
@Before
public void setup() {
@@ -206,6 +209,11 @@
DisplayCutout.BOUNDS_POSITION_RIGHT,
R.layout.privacy_dot_bottom_right));
+ // Default no cutout
+ mMockCutoutList = new ArrayList<>();
+ doAnswer(it -> !(mMockCutoutList.isEmpty())).when(mCutoutFactory).getHasProviders();
+ doReturn(mMockCutoutList).when(mCutoutFactory).getProviders();
+
mFaceScanningDecorProvider = spy(new FaceScanningOverlayProviderImpl(
BOUNDS_POSITION_TOP,
mAuthController,
@@ -239,6 +247,11 @@
super.updateOverlayWindowVisibilityIfViewExists(view);
mExecutor.runAllReady();
}
+
+ @Override
+ protected CutoutDecorProviderFactory getCutoutFactory() {
+ return ScreenDecorationsTest.this.mCutoutFactory;
+ }
});
mScreenDecorations.mDisplayInfo = mDisplayInfo;
doReturn(1f).when(mScreenDecorations).getPhysicalPixelDisplaySizeRatio();
@@ -429,11 +442,9 @@
public void testNoRounding_NoCutout_NoPrivacyDot_NoFaceScanning() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
// No views added.
@@ -448,11 +459,9 @@
public void testNoRounding_NoCutout_PrivacyDot_NoFaceScanning() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
@@ -484,11 +493,9 @@
public void testRounding_NoCutout_NoPrivacyDot_NoFaceScanning() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
@@ -516,11 +523,9 @@
public void testRounding_NoCutout_PrivacyDot_NoFaceScanning() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
@@ -555,10 +560,9 @@
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+
+ // no cutout (default)
mScreenDecorations.start();
// Size of corner view should same as rounded_corner_radius{_top|_bottom}
@@ -574,11 +578,9 @@
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
@@ -611,13 +613,10 @@
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.start();
View topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
@@ -647,13 +646,10 @@
public void testNoRounding_CutoutShortEdge_NoPrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Top window is created for top cutout.
@@ -671,13 +667,10 @@
public void testNoRounding_CutoutShortEdge_PrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Top window is created for top cutout.
@@ -706,13 +699,10 @@
public void testNoRounding_CutoutLongEdge_NoPrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.start();
// Left window is created for left cutout.
@@ -734,13 +724,10 @@
public void testNoRounding_CutoutLongEdge_PrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.start();
// Left window is created for left cutout.
@@ -762,13 +749,10 @@
public void testRounding_CutoutShortEdge_NoPrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Top window is created for rounded corner and top cutout.
@@ -791,13 +775,10 @@
public void testRounding_CutoutShortEdge_PrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Top window is created for rounded corner and top cutout.
@@ -823,13 +804,10 @@
public void testRounding_CutoutLongEdge_NoPrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.start();
// Left window is created for rounded corner and left cutout.
@@ -842,13 +820,10 @@
public void testRounding_CutoutLongEdge_PrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.start();
// Left window is created for rounded corner, left cutout, and privacy.
@@ -863,13 +838,11 @@
public void testRounding_CutoutShortAndLongEdge_NoPrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// top and left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Top window is created for rounded corner and top cutout.
@@ -883,13 +856,11 @@
public void testRounding_CutoutShortAndLongEdge_PrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// top and left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Top window is created for rounded corner and top cutout.
@@ -905,21 +876,16 @@
public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_NoPrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// Set to short edge cutout(top).
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
verifyOverlaysExistAndAdded(false, true, false, false, View.VISIBLE);
// Switch to long edge cutout(left).
- final Rect[] newBounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), newBounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.set(0, new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.onConfigurationChanged(new Configuration());
verifyOverlaysExistAndAdded(true, false, false, false, View.VISIBLE);
@@ -929,13 +895,10 @@
public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_PrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// Set to short edge cutout(top).
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
@@ -943,9 +906,7 @@
verify(mDotViewController, times(1)).setShowingListener(null);
// Switch to long edge cutout(left).
- final Rect[] newBounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), newBounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.set(0, new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.onConfigurationChanged(new Configuration());
verifyOverlaysExistAndAdded(true, false, true, false, View.VISIBLE);
@@ -973,20 +934,16 @@
public void testDelayedCutout_NoPrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
- // top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ // No cutout (default)
mScreenDecorations.start();
verifyOverlaysExistAndAdded(false, false, false, false, null);
- when(mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
- .thenReturn(true);
+ // top cutout
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+
mScreenDecorations.onConfigurationChanged(new Configuration());
// Only top windows should be added.
@@ -997,13 +954,9 @@
public void testDelayedCutout_PrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
- // top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
// Both top and bottom windows should be added with INVISIBLE because of only privacy dot,
@@ -1015,9 +968,9 @@
verify(mDotViewController, times(1)).setShowingListener(
mScreenDecorations.mPrivacyDotShowingListener);
- when(mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
- .thenReturn(true);
+ // top cutout
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+
mScreenDecorations.onConfigurationChanged(new Configuration());
// Both top and bottom windows should be added with VISIBLE because of privacy dot and
@@ -1043,8 +996,7 @@
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning*/);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning*/);
mDisplayInfo.rotation = Surface.ROTATION_0;
mScreenDecorations.start();
@@ -1058,8 +1010,7 @@
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning*/);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning*/);
mDisplayInfo.rotation = Surface.ROTATION_270;
mScreenDecorations.onConfigurationChanged(null);
@@ -1072,8 +1023,7 @@
public void testOnlyRoundedCornerRadiusTop() {
setupResources(0 /* radius */, 10 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
mScreenDecorations.start();
@@ -1094,8 +1044,7 @@
public void testOnlyRoundedCornerRadiusBottom() {
setupResources(0 /* radius */, 0 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
mScreenDecorations.start();
@@ -1166,13 +1115,10 @@
public void testSupportHwcLayer_SwitchFrom_NotSupport() {
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// should only inflate mOverlays when the hwc doesn't support screen decoration
@@ -1195,16 +1141,13 @@
public void testNotSupportHwcLayer_SwitchFrom_Support() {
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// should only inflate hwc layer when the hwc supports screen decoration
@@ -1234,16 +1177,13 @@
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- true /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer
@@ -1277,11 +1217,9 @@
public void testAutoShowHideOverlayWindowWhenNoRoundedAndNoCutout() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- true /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
// Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer
@@ -1315,16 +1253,13 @@
public void testHwcLayer_noPrivacyDot_noFaceScanning() {
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
@@ -1337,16 +1272,13 @@
public void testHwcLayer_PrivacyDot_FaceScanning() {
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- true /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
@@ -1364,16 +1296,13 @@
public void testOnDisplayChanged_hwcLayer() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
@@ -1383,39 +1312,36 @@
mScreenDecorations.mDisplayListener.onDisplayChanged(1);
- verify(hwcLayer, times(1)).onDisplayChanged(1);
+ verify(hwcLayer, times(1)).onDisplayChanged(any());
}
@Test
public void testOnDisplayChanged_nonHwcLayer() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
- final ScreenDecorations.DisplayCutoutView cutoutView =
- mScreenDecorations.mCutoutViews[BOUNDS_POSITION_TOP];
+ final ScreenDecorations.DisplayCutoutView cutoutView = (ScreenDecorations.DisplayCutoutView)
+ mScreenDecorations.getOverlayView(R.id.display_cutout);
+ assertNotNull(cutoutView);
spyOn(cutoutView);
doReturn(mDisplay).when(cutoutView).getDisplay();
mScreenDecorations.mDisplayListener.onDisplayChanged(1);
- verify(cutoutView, times(1)).onDisplayChanged(1);
+ verify(cutoutView, times(1)).onDisplayChanged(any());
}
@Test
public void testHasSameProvidersWithNullOverlays() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
mScreenDecorations.start();
@@ -1433,8 +1359,7 @@
public void testHasSameProvidersWithPrivacyDots() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
mScreenDecorations.start();
@@ -1471,7 +1396,7 @@
private void setupResources(int radius, int radiusTop, int radiusBottom,
@Nullable Drawable roundedTopDrawable, @Nullable Drawable roundedBottomDrawable,
- int roundedPadding, boolean fillCutout, boolean privacyDot, boolean faceScanning) {
+ int roundedPadding, boolean privacyDot, boolean faceScanning) {
mContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.array.config_displayUniqueIdArray,
new String[]{});
@@ -1511,8 +1436,6 @@
}
mContext.getOrCreateTestableResources().addOverride(
R.dimen.rounded_corner_content_padding, roundedPadding);
- mContext.getOrCreateTestableResources().addOverride(
- com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout);
mPrivacyDecorProviders = new ArrayList<>();
if (privacyDot) {
@@ -1531,19 +1454,4 @@
when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders);
when(mFaceScanningProviderFactory.getHasProviders()).thenReturn(faceScanning);
}
-
- private DisplayCutout getDisplayCutoutForRotation(Insets safeInsets, Rect[] cutoutBounds) {
- final int rotation = mContext.getDisplay().getRotation();
- final Insets insets = RotationUtils.rotateInsets(safeInsets, rotation);
- final Rect[] sorted = new Rect[BOUNDS_POSITION_LENGTH];
- for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
- final int rotatedPos = ScreenDecorations.getBoundPositionFromRotation(i, rotation);
- if (cutoutBounds[i] != null) {
- RotationUtils.rotateBounds(cutoutBounds[i], new Rect(0, 0, 100, 200), rotation);
- }
- sorted[rotatedPos] = cutoutBounds[i];
- }
- return new DisplayCutout(insets, sorted[BOUNDS_POSITION_LEFT], sorted[BOUNDS_POSITION_TOP],
- sorted[BOUNDS_POSITION_RIGHT], sorted[BOUNDS_POSITION_BOTTOM]);
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
index 0f11241..e2790e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
@@ -10,12 +10,10 @@
import android.os.Looper
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
-import android.util.Log
import android.view.IRemoteAnimationFinishedCallback
import android.view.RemoteAnimationAdapter
import android.view.RemoteAnimationTarget
import android.view.SurfaceControl
-import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.test.filters.SmallTest
@@ -51,7 +49,6 @@
@Mock lateinit var listener: ActivityLaunchAnimator.Listener
@Spy private val controller = TestLaunchAnimatorController(launchContainer)
@Mock lateinit var iCallback: IRemoteAnimationFinishedCallback
- @Mock lateinit var failHandler: Log.TerribleFailureHandler
private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
@get:Rule val rule = MockitoJUnit.rule()
@@ -187,13 +184,6 @@
verify(controller).onLaunchAnimationStart(anyBoolean())
}
- @Test
- fun controllerFromOrphanViewReturnsNullAndIsATerribleFailure() {
- Log.setWtfHandler(failHandler)
- assertNull(ActivityLaunchAnimator.Controller.fromView(View(mContext)))
- verify(failHandler).onTerribleFailure(any(), any(), anyBoolean())
- }
-
private fun fakeWindow(): RemoteAnimationTarget {
val bounds = Rect(10 /* left */, 20 /* top */, 30 /* right */, 40 /* bottom */)
val taskInfo = ActivityManager.RunningTaskInfo()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt
index 328ad39..58d9069 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt
@@ -41,11 +41,13 @@
@SmallTest
class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
- @JvmField @Rule
+ @JvmField
+ @Rule
var mockitoRule = MockitoJUnit.rule()
@Mock
private lateinit var callback: AuthBiometricView.Callback
+
@Mock
private lateinit var panelController: AuthPanelController
@@ -67,6 +69,7 @@
fun fingerprintSuccessDoesNotRequireExplicitConfirmation() {
biometricView.onDialogAnimatedIn()
biometricView.onAuthenticationSucceeded(TYPE_FINGERPRINT)
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
assertThat(biometricView.isAuthenticated).isTrue()
@@ -86,6 +89,7 @@
// icon acts as confirm button
biometricView.mIconView.performClick()
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
assertThat(biometricView.isAuthenticated).isTrue()
@@ -102,6 +106,7 @@
verify(callback, never()).onAction(AuthBiometricView.Callback.ACTION_ERROR)
biometricView.onError(TYPE_FINGERPRINT, "that's a nope")
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
verify(callback).onAction(AuthBiometricView.Callback.ACTION_ERROR)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
index 687cb517..bce98cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
@@ -42,20 +42,23 @@
@SmallTest
class AuthBiometricFingerprintViewTest : SysuiTestCase() {
- @JvmField @Rule
+ @JvmField
+ @Rule
val mockitoRule = MockitoJUnit.rule()
@Mock
private lateinit var callback: AuthBiometricView.Callback
+
@Mock
private lateinit var panelController: AuthPanelController
private lateinit var biometricView: AuthBiometricView
private fun createView(allowDeviceCredential: Boolean = false): AuthBiometricFingerprintView {
- val view = R.layout.auth_biometric_fingerprint_view.asTestAuthBiometricView(
+ val view: AuthBiometricFingerprintView =
+ R.layout.auth_biometric_fingerprint_view.asTestAuthBiometricView(
mContext, callback, panelController, allowDeviceCredential = allowDeviceCredential
- ) as AuthBiometricFingerprintView
+ )
waitForIdleSync()
return view
}
@@ -73,6 +76,7 @@
@Test
fun testOnAuthenticationSucceeded_noConfirmationRequired_sendsActionAuthenticated() {
biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT)
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
assertThat(biometricView.isAuthenticated).isTrue()
@@ -83,6 +87,7 @@
fun testOnAuthenticationSucceeded_confirmationRequired_updatesDialogContents() {
biometricView.setRequireConfirmation(true)
biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT)
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
// TODO: this should be tested in the subclasses
@@ -104,6 +109,7 @@
@Test
fun testPositiveButton_sendsActionAuthenticated() {
biometricView.mConfirmButton.performClick()
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
verify(callback).onAction(AuthBiometricView.Callback.ACTION_AUTHENTICATED)
@@ -114,6 +120,7 @@
fun testNegativeButton_beforeAuthentication_sendsActionButtonNegative() {
biometricView.onDialogAnimatedIn()
biometricView.mNegativeButton.performClick()
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
verify(callback).onAction(AuthBiometricView.Callback.ACTION_BUTTON_NEGATIVE)
@@ -126,6 +133,7 @@
assertThat(biometricView.mNegativeButton.visibility).isEqualTo(View.GONE)
biometricView.mCancelButton.performClick()
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
verify(callback).onAction(AuthBiometricView.Callback.ACTION_USER_CANCELED)
@@ -134,6 +142,7 @@
@Test
fun testTryAgainButton_sendsActionTryAgain() {
biometricView.mTryAgainButton.performClick()
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
verify(callback).onAction(AuthBiometricView.Callback.ACTION_BUTTON_TRY_AGAIN)
@@ -144,6 +153,7 @@
@Test
fun testOnErrorSendsActionError() {
biometricView.onError(BiometricAuthenticator.TYPE_FACE, "testError")
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
verify(callback).onAction(eq(AuthBiometricView.Callback.ACTION_ERROR))
@@ -156,6 +166,7 @@
val message = "another error"
biometricView.onError(BiometricAuthenticator.TYPE_FACE, message)
+ TestableLooper.get(this).moveTimeForward(1000)
waitForIdleSync()
assertThat(biometricView.isAuthenticating).isFalse()
@@ -178,6 +189,7 @@
val view = View(mContext)
biometricView.setBackgroundView(view)
biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT)
+ waitForIdleSync()
view.performClick()
verify(callback, never())
@@ -225,14 +237,14 @@
biometricView.onSaveState(state)
assertThat(biometricView.mTryAgainButton.visibility).isEqualTo(View.GONE)
assertThat(state.getInt(AuthDialog.KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY))
- .isEqualTo(View.GONE)
+ .isEqualTo(View.GONE)
assertThat(state.getInt(AuthDialog.KEY_BIOMETRIC_STATE))
- .isEqualTo(AuthBiometricView.STATE_ERROR)
+ .isEqualTo(AuthBiometricView.STATE_ERROR)
assertThat(biometricView.mIndicatorView.visibility).isEqualTo(View.VISIBLE)
assertThat(state.getBoolean(AuthDialog.KEY_BIOMETRIC_INDICATOR_ERROR_SHOWING)).isTrue()
assertThat(biometricView.mIndicatorView.text).isEqualTo(failureMessage)
assertThat(state.getString(AuthDialog.KEY_BIOMETRIC_INDICATOR_STRING))
- .isEqualTo(failureMessage)
+ .isEqualTo(failureMessage)
// TODO: Test dialog size. Should move requireConfirmation to buildBiometricPromptBundle
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 d158892..a02dfa3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -20,6 +20,8 @@
import static android.hardware.biometrics.BiometricManager.Authenticators;
import static android.hardware.biometrics.BiometricManager.BIOMETRIC_MULTI_SENSOR_FINGERPRINT_AND_FACE;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
@@ -72,6 +74,8 @@
import android.testing.TestableContext;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
+import android.view.DisplayInfo;
+import android.view.Surface;
import android.view.WindowManager;
import androidx.test.filters.SmallTest;
@@ -154,11 +158,13 @@
@Mock
private InteractionJankMonitor mInteractionJankMonitor;
@Captor
- ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
+ private ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
@Captor
- ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor;
+ private ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor;
@Captor
- ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
+ private ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
+ @Captor
+ private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefullnessObserverCaptor;
private TestableContext mContextSpy;
private Execution mExecution;
@@ -222,7 +228,9 @@
mAuthenticatorsRegisteredCaptor.capture());
when(mStatusBarStateController.isDozing()).thenReturn(false);
+ when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE);
verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
+ verify(mWakefulnessLifecycle).addObserver(mWakefullnessObserverCaptor.capture());
mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(props);
@@ -685,13 +693,8 @@
}
@Test
- public void testSubscribesToOrientationChangesWhenShowingDialog() {
- showDialog(new int[]{1} /* sensorIds */, false /* credentialAllowed */);
-
+ public void testSubscribesToOrientationChangesOnStart() {
verify(mDisplayManager).registerDisplayListener(any(), eq(mHandler), anyLong());
-
- mAuthController.hideAuthenticationDialog(REQUEST_ID);
- verify(mDisplayManager).unregisterDisplayListener(any());
}
@Test
@@ -724,19 +727,148 @@
}
@Test
- public void testForwardsDozeEvent() throws RemoteException {
+ public void testForwardsDozeEvents() throws RemoteException {
+ when(mStatusBarStateController.isDozing()).thenReturn(true);
+ when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE);
mAuthController.setBiometicContextListener(mContextListener);
- mStatusBarStateListenerCaptor.getValue().onDozingChanged(false);
mStatusBarStateListenerCaptor.getValue().onDozingChanged(true);
+ mStatusBarStateListenerCaptor.getValue().onDozingChanged(false);
InOrder order = inOrder(mContextListener);
- // invoked twice since the initial state is false
- order.verify(mContextListener, times(2)).onDozeChanged(eq(false));
- order.verify(mContextListener).onDozeChanged(eq(true));
+ order.verify(mContextListener, times(2)).onDozeChanged(eq(true), eq(true));
+ order.verify(mContextListener).onDozeChanged(eq(false), eq(true));
+ order.verifyNoMoreInteractions();
}
- // Helpers
+ @Test
+ public void testForwardsWakeEvents() throws RemoteException {
+ when(mStatusBarStateController.isDozing()).thenReturn(false);
+ when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE);
+ mAuthController.setBiometicContextListener(mContextListener);
+
+ mWakefullnessObserverCaptor.getValue().onStartedGoingToSleep();
+ mWakefullnessObserverCaptor.getValue().onFinishedGoingToSleep();
+ mWakefullnessObserverCaptor.getValue().onStartedWakingUp();
+ mWakefullnessObserverCaptor.getValue().onFinishedWakingUp();
+ mWakefullnessObserverCaptor.getValue().onPostFinishedWakingUp();
+
+ InOrder order = inOrder(mContextListener);
+ order.verify(mContextListener).onDozeChanged(eq(false), eq(true));
+ order.verify(mContextListener).onDozeChanged(eq(false), eq(false));
+ order.verify(mContextListener).onDozeChanged(eq(false), eq(true));
+ order.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testGetFingerprintSensorLocationChanges_differentRotations() {
+ // GIVEN fp default location and mocked device dimensions
+ // Rotation 0, where "o" is the location of the FP sensor, if x or y = 0, it's the edge of
+ // the screen which is why a 1x1 width and height is represented by a 2x2 grid below:
+ // [* o]
+ // [* *]
+ Point fpDefaultLocation = new Point(1, 0);
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.logicalWidth = 1;
+ displayInfo.logicalHeight = 1;
+
+ // WHEN the rotation is 0, THEN no rotation applied
+ displayInfo.rotation = Surface.ROTATION_0;
+ assertEquals(
+ fpDefaultLocation,
+ mAuthController.rotateToCurrentOrientation(
+ new Point(fpDefaultLocation), displayInfo)
+ );
+
+ // WHEN the rotation is 270, THEN rotation is applied
+ // [* *]
+ // [* o]
+ displayInfo.rotation = Surface.ROTATION_270;
+ assertEquals(
+ new Point(1, 1),
+ mAuthController.rotateToCurrentOrientation(
+ new Point(fpDefaultLocation), displayInfo)
+ );
+
+ // WHEN the rotation is 180, THEN rotation is applied
+ // [* *]
+ // [o *]
+ displayInfo.rotation = Surface.ROTATION_180;
+ assertEquals(
+ new Point(0, 1),
+ mAuthController.rotateToCurrentOrientation(
+ new Point(fpDefaultLocation), displayInfo)
+ );
+
+ // WHEN the rotation is 90, THEN rotation is applied
+ // [o *]
+ // [* *]
+ displayInfo.rotation = Surface.ROTATION_90;
+ assertEquals(
+ new Point(0, 0),
+ mAuthController.rotateToCurrentOrientation(
+ new Point(fpDefaultLocation), displayInfo)
+ );
+ }
+
+ @Test
+ public void testGetFingerprintSensorLocationChanges_rotateRectangle() {
+ // GIVEN fp default location and mocked device dimensions
+ // Rotation 0, where "o" is the location of the FP sensor, if x or y = 0, it's the edge of
+ // the screen.
+ // [* * o *]
+ // [* * * *]
+ Point fpDefaultLocation = new Point(2, 0);
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.logicalWidth = 3;
+ displayInfo.logicalHeight = 1;
+
+ // WHEN the rotation is 0, THEN no rotation applied
+ displayInfo.rotation = Surface.ROTATION_0;
+ assertEquals(
+ fpDefaultLocation,
+ mAuthController.rotateToCurrentOrientation(
+ new Point(fpDefaultLocation), displayInfo)
+ );
+
+ // WHEN the rotation is 180, THEN rotation is applied
+ // [* * * *]
+ // [* o * *]
+ displayInfo.rotation = Surface.ROTATION_180;
+ assertEquals(
+ new Point(1, 1),
+ mAuthController.rotateToCurrentOrientation(
+ new Point(fpDefaultLocation), displayInfo)
+ );
+
+ // Rotation 270 & 90 have swapped logical width and heights
+ displayInfo.logicalWidth = 1;
+ displayInfo.logicalHeight = 3;
+
+ // WHEN the rotation is 270, THEN rotation is applied
+ // [* *]
+ // [* *]
+ // [* o]
+ // [* *]
+ displayInfo.rotation = Surface.ROTATION_270;
+ assertEquals(
+ new Point(1, 2),
+ mAuthController.rotateToCurrentOrientation(
+ new Point(fpDefaultLocation), displayInfo)
+ );
+
+ // WHEN the rotation is 90, THEN rotation is applied
+ // [* *]
+ // [o *]
+ // [* *]
+ // [* *]
+ displayInfo.rotation = Surface.ROTATION_90;
+ assertEquals(
+ new Point(0, 1),
+ mAuthController.rotateToCurrentOrientation(
+ new Point(fpDefaultLocation), displayInfo)
+ );
+ }
private void showDialog(int[] sensorIds, boolean credentialAllowed) {
mAuthController.showAuthenticationDialog(createTestPromptInfo(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
index d6afd6d..44ef922 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
@@ -16,7 +16,7 @@
package com.android.systemui.biometrics
-import android.graphics.PointF
+import android.graphics.Point
import android.hardware.biometrics.BiometricSourceType
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
@@ -31,11 +31,12 @@
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.BiometricUnlockController
-import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.CentralSurfaces
+import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.leak.RotationUtils
+import javax.inject.Provider
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
@@ -45,15 +46,14 @@
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.any
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-import javax.inject.Provider
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -116,7 +116,7 @@
@Test
fun testFingerprintTrigger_KeyguardVisible_Ripple() {
// GIVEN fp exists, keyguard is visible, user doesn't need strong auth
- val fpsLocation = PointF(5f, 5f)
+ val fpsLocation = Point(5, 5)
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
@@ -139,7 +139,7 @@
@Test
fun testFingerprintTrigger_Dreaming_Ripple() {
// GIVEN fp exists, keyguard is visible, user doesn't need strong auth
- val fpsLocation = PointF(5f, 5f)
+ val fpsLocation = Point(5, 5)
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(false)
@@ -162,7 +162,7 @@
@Test
fun testFingerprintTrigger_KeyguardNotVisible_NotDreaming_NoRipple() {
// GIVEN fp exists & user doesn't need strong auth
- val fpsLocation = PointF(5f, 5f)
+ val fpsLocation = Point(5, 5)
`when`(authController.udfpsLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
@@ -184,7 +184,7 @@
@Test
fun testFingerprintTrigger_StrongAuthRequired_NoRipple() {
// GIVEN fp exists & keyguard is visible
- val fpsLocation = PointF(5f, 5f)
+ val fpsLocation = Point(5, 5)
`when`(authController.udfpsLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
@@ -205,8 +205,8 @@
@Test
fun testFaceTriggerBypassEnabled_Ripple() {
// GIVEN face auth sensor exists, keyguard is visible & strong auth isn't required
- val faceLocation = PointF(5f, 5f)
- `when`(authController.faceAuthSensorLocation).thenReturn(faceLocation)
+ val faceLocation = Point(5, 5)
+ `when`(authController.faceSensorLocation).thenReturn(faceLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
@@ -229,8 +229,8 @@
@Test
fun testFaceTriggerNonBypass_NoRipple() {
// GIVEN face auth sensor exists
- val faceLocation = PointF(5f, 5f)
- `when`(authController.faceAuthSensorLocation).thenReturn(faceLocation)
+ val faceLocation = Point(5, 5)
+ `when`(authController.faceSensorLocation).thenReturn(faceLocation)
controller.onViewAttached()
// WHEN bypass isn't enabled & face authenticated
@@ -248,7 +248,7 @@
@Test
fun testNullFaceSensorLocationDoesNothing() {
- `when`(authController.faceAuthSensorLocation).thenReturn(null)
+ `when`(authController.faceSensorLocation).thenReturn(null)
controller.onViewAttached()
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
@@ -293,7 +293,7 @@
@Test
@RunWithLooper(setAsMainLooper = true)
fun testAnimatorRunWhenWakeAndUnlock_fingerprint() {
- val fpsLocation = PointF(5f, 5f)
+ val fpsLocation = Point(5, 5)
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
@@ -311,8 +311,8 @@
@Test
@RunWithLooper(setAsMainLooper = true)
fun testAnimatorRunWhenWakeAndUnlock_faceUdfpsFingerDown() {
- val faceLocation = PointF(5f, 5f)
- `when`(authController.faceAuthSensorLocation).thenReturn(faceLocation)
+ val faceLocation = Point(5, 5)
+ `when`(authController.faceSensorLocation).thenReturn(faceLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
index 7795d2c..434cb48 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
@@ -18,6 +18,7 @@
import android.content.BroadcastReceiver
import android.content.Context
+import android.content.Intent
import android.content.IntentFilter
import android.os.Handler
import android.os.Looper
@@ -32,22 +33,27 @@
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Executor
import junit.framework.Assert.assertSame
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.runBlockingTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
-import java.util.concurrent.Executor
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
@@ -381,6 +387,39 @@
.clearPendingRemoval(broadcastReceiver, user1.identifier)
}
+ @Test
+ fun testBroadcastFlow() = runBlockingTest {
+ val flow = broadcastDispatcher.broadcastFlow(intentFilter, user1) { intent, receiver ->
+ intent to receiver
+ }
+
+ // Collect the values into collectedValues.
+ val collectedValues = mutableListOf<Pair<Intent, BroadcastReceiver>>()
+ val job = launch {
+ flow.collect { collectedValues.add(it) }
+ }
+
+ testableLooper.processAllMessages()
+ verify(mockUBRUser1).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))
+ val receiver = argumentCaptor.value.receiver
+
+ // Simulate fake broadcasted intents.
+ val fakeIntents = listOf<Intent>(mock(), mock(), mock())
+ fakeIntents.forEach { receiver.onReceive(mockContext, it) }
+
+ // The intents should have been collected.
+ advanceUntilIdle()
+
+ val expectedValues = fakeIntents.map { it to receiver }
+ assertThat(collectedValues).containsExactlyElementsIn(expectedValues)
+
+ // Stop the collection.
+ job.cancel()
+
+ testableLooper.processAllMessages()
+ verify(mockUBRUser1).unregisterReceiver(receiver)
+ }
+
private fun setUserMock(mockContext: Context, user: UserHandle) {
`when`(mockContext.user).thenReturn(user)
`when`(mockContext.userId).thenReturn(user.identifier)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt
index 3ac28c8..2af0557 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt
@@ -107,11 +107,11 @@
reset(rippleView)
captor.value.onThemeChanged()
- verify(rippleView).setColor(ArgumentMatchers.anyInt())
+ verify(rippleView).setColor(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
reset(rippleView)
captor.value.onUiModeChanged()
- verify(rippleView).setColor(ArgumentMatchers.anyInt())
+ verify(rippleView).setColor(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
index 55ee433..9481349 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
@@ -32,6 +32,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.testing.FakeMetricsLogger;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
@@ -111,5 +112,51 @@
assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isFalse();
}
+ @Test
+ public void testIsProxNear_noProxEvents_defaultsToFalse() {
+ assertThat(mBrightLineFalsingManager.isProximityNear()).isFalse();
+ }
+ @Test
+ public void testIsProxNear_receivesNearEvent() {
+ mBrightLineFalsingManager.onProximityEvent(new FalsingManager.ProximityEvent() {
+ @Override
+ public boolean getCovered() {
+ return true;
+ }
+
+ @Override
+ public long getTimestampNs() {
+ return 0;
+ }
+ });
+ assertThat(mBrightLineFalsingManager.isProximityNear()).isTrue();
+ }
+
+ @Test
+ public void testIsProxNear_receivesNearAndThenFarEvent() {
+ mBrightLineFalsingManager.onProximityEvent(new FalsingManager.ProximityEvent() {
+ @Override
+ public boolean getCovered() {
+ return true;
+ }
+
+ @Override
+ public long getTimestampNs() {
+ return 0;
+ }
+ });
+ mBrightLineFalsingManager.onProximityEvent(new FalsingManager.ProximityEvent() {
+ @Override
+ public boolean getCovered() {
+ return false;
+ }
+
+ @Override
+ public long getTimestampNs() {
+ return 5;
+ }
+ });
+ assertThat(mBrightLineFalsingManager.isProximityNear()).isFalse();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
new file mode 100644
index 0000000..1040ec4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.decor
+
+import android.graphics.Insets
+import android.graphics.Rect
+import android.testing.AndroidTestingRunner
+import android.testing.TestableResources
+import android.util.RotationUtils
+import android.util.Size
+import android.view.Display
+import android.view.DisplayCutout
+import android.view.DisplayCutout.BOUNDS_POSITION_LENGTH
+import android.view.DisplayInfo
+import android.view.Surface
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.any
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.doAnswer
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class CutoutDecorProviderFactoryTest : SysuiTestCase() {
+
+ @Mock private lateinit var display: Display
+ private var testableRes: TestableResources? = null
+ private lateinit var factory: CutoutDecorProviderFactory
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ testableRes = mContext.orCreateTestableResources
+ factory = CutoutDecorProviderFactory(testableRes!!.resources, display)
+ }
+
+ private fun setupFillCutout(fillCutout: Boolean) {
+ testableRes!!.addOverride(
+ com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout
+ )
+ }
+
+ private fun setupDisplayInfo(
+ displayCutout: DisplayCutout? = null,
+ @Surface.Rotation rotation: Int = Surface.ROTATION_0,
+ displayId: Int = -1
+ ) {
+ doAnswer {
+ it.getArgument<DisplayInfo>(0).let { info ->
+ info.displayCutout = displayCutout
+ info.rotation = rotation
+ info.displayId = displayId
+ }
+ true
+ }.`when`(display).getDisplayInfo(any<DisplayInfo>())
+ }
+
+ private fun getCutout(
+ safeInsets: Insets,
+ cutoutBounds: Array<Rect?>,
+ @Surface.Rotation rotation: Int = Surface.ROTATION_0,
+ cutoutParentSizeForRotate: Size = Size(100, 200)
+ ): DisplayCutout {
+ val insets = RotationUtils.rotateInsets(safeInsets, rotation)
+ val sorted = arrayOfNulls<Rect>(BOUNDS_POSITION_LENGTH)
+ for (pos in 0 until BOUNDS_POSITION_LENGTH) {
+ val rotatedPos = (pos - rotation + BOUNDS_POSITION_LENGTH) % BOUNDS_POSITION_LENGTH
+ if (cutoutBounds[pos] != null) {
+ RotationUtils.rotateBounds(
+ cutoutBounds[pos],
+ cutoutParentSizeForRotate.width,
+ cutoutParentSizeForRotate.height,
+ rotation
+ )
+ }
+ sorted[rotatedPos] = cutoutBounds[pos]
+ }
+ return DisplayCutout(
+ insets,
+ sorted[DisplayCutout.BOUNDS_POSITION_LEFT],
+ sorted[DisplayCutout.BOUNDS_POSITION_TOP],
+ sorted[DisplayCutout.BOUNDS_POSITION_RIGHT],
+ sorted[DisplayCutout.BOUNDS_POSITION_BOTTOM]
+ )
+ }
+
+ @Test
+ fun testGetNothingIfNoCutout() {
+ setupFillCutout(false)
+
+ Assert.assertFalse(factory.hasProviders)
+ Assert.assertEquals(0, factory.providers.size)
+ }
+
+ @Test
+ fun testGetTopCutoutProvider() {
+ setupFillCutout(true)
+ setupDisplayInfo(
+ getCutout(
+ safeInsets = Insets.of(0, 1, 0, 0),
+ cutoutBounds = arrayOf(null, Rect(9, 0, 10, 1), null, null)
+ )
+ )
+
+ Assert.assertTrue(factory.hasProviders)
+
+ val providers = factory.providers
+ Assert.assertEquals(1, providers.size)
+ Assert.assertEquals(1, providers[0].numOfAlignedBound)
+ Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_TOP, providers[0].alignedBounds[0])
+ }
+
+ @Test
+ fun testGetBottomCutoutProviderOnLandscape() {
+ setupFillCutout(true)
+ setupDisplayInfo(
+ getCutout(
+ safeInsets = Insets.of(0, 0, 0, 1),
+ cutoutBounds = arrayOf(null, null, null, Rect(45, 199, 55, 200)),
+ rotation = Surface.ROTATION_90
+ ),
+ Surface.ROTATION_90
+ )
+
+ Assert.assertTrue(factory.hasProviders)
+
+ val providers = factory.providers
+ Assert.assertEquals(1, providers.size)
+ Assert.assertEquals(1, providers[0].numOfAlignedBound)
+ Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_BOTTOM, providers[0].alignedBounds[0])
+ }
+
+ @Test
+ fun testGetLeftCutoutProviderOnSeascape() {
+ setupFillCutout(true)
+ setupDisplayInfo(
+ getCutout(
+ safeInsets = Insets.of(1, 0, 0, 0),
+ cutoutBounds = arrayOf(Rect(0, 20, 1, 40), null, null, null),
+ rotation = Surface.ROTATION_270
+ ),
+ Surface.ROTATION_270
+ )
+
+ Assert.assertTrue(factory.hasProviders)
+
+ val providers = factory.providers
+ Assert.assertEquals(1, providers.size)
+ Assert.assertEquals(1, providers[0].numOfAlignedBound)
+ Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_LEFT, providers[0].alignedBounds[0])
+ }
+
+ @Test
+ fun testGetTopRightCutoutProviderOnReverse() {
+ setupFillCutout(true)
+ setupDisplayInfo(
+ getCutout(
+ safeInsets = Insets.of(0, 1, 1, 0),
+ cutoutBounds = arrayOf(
+ null,
+ Rect(9, 0, 10, 1),
+ Rect(99, 40, 100, 60),
+ null
+ ),
+ rotation = Surface.ROTATION_180
+ ),
+ Surface.ROTATION_180
+ )
+
+ Assert.assertTrue(factory.hasProviders)
+
+ val providers = factory.providers
+ Assert.assertEquals(2, providers.size)
+ Assert.assertEquals(1, providers[0].numOfAlignedBound)
+ Assert.assertEquals(1, providers[1].numOfAlignedBound)
+ providers.sortedBy { it.alignedBounds[0] }.let {
+ Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_TOP, it[0].alignedBounds[0])
+ Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_RIGHT, it[1].alignedBounds[0])
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
index 69366fa..8bf17d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.decor
+import android.graphics.Color
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import android.view.DisplayCutout
@@ -51,35 +52,45 @@
@Before
fun setUp() {
- decorProvider1 = spy(PrivacyDotCornerDecorProviderImpl(
+ decorProvider1 = spy(
+ PrivacyDotCornerDecorProviderImpl(
viewId = TEST_DECOR_VIEW_ID_1,
alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
- layoutId = R.layout.privacy_dot_top_left))
- decorProvider2 = spy(PrivacyDotCornerDecorProviderImpl(
+ layoutId = R.layout.privacy_dot_top_left
+ )
+ )
+ decorProvider2 = spy(
+ PrivacyDotCornerDecorProviderImpl(
viewId = TEST_DECOR_VIEW_ID_2,
alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
- layoutId = R.layout.privacy_dot_bottom_left))
- decorProvider3 = spy(PrivacyDotCornerDecorProviderImpl(
+ layoutId = R.layout.privacy_dot_bottom_left
+ )
+ )
+ decorProvider3 = spy(
+ PrivacyDotCornerDecorProviderImpl(
viewId = TEST_DECOR_VIEW_ID_3,
alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
- layoutId = R.layout.privacy_dot_bottom_right))
-
+ layoutId = R.layout.privacy_dot_bottom_right
+ )
+ )
overlay = OverlayWindow(mContext)
}
@Test
fun testAddProvider() {
@Surface.Rotation val rotation = Surface.ROTATION_270
- overlay.addDecorProvider(decorProvider1, rotation)
- overlay.addDecorProvider(decorProvider2, rotation)
+ overlay.addDecorProvider(decorProvider1, rotation, Color.BLACK)
+ overlay.addDecorProvider(decorProvider2, rotation, Color.YELLOW)
verify(decorProvider1, times(1)).inflateView(
- mContext, overlay.rootView, rotation)
+ mContext, overlay.rootView, rotation, Color.BLACK
+ )
verify(decorProvider2, times(1)).inflateView(
- mContext, overlay.rootView, rotation)
+ mContext, overlay.rootView, rotation, Color.YELLOW
+ )
val view1FoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
Assert.assertNotNull(view1FoundFromRootView)
@@ -91,8 +102,8 @@
@Test
fun testRemoveView() {
- overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
- overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
+ overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270, Color.BLACK)
+ overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270, Color.BLACK)
overlay.removeView(TEST_DECOR_VIEW_ID_1)
val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
@@ -102,39 +113,47 @@
@Test
fun testOnReloadResAndMeasureWithoutIds() {
- overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
- overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
+ overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0, Color.BLACK)
+ overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0, Color.BLACK)
overlay.onReloadResAndMeasure(
- reloadToken = 1,
- rotation = Surface.ROTATION_90,
- displayUniqueId = null)
+ reloadToken = 1,
+ rotation = Surface.ROTATION_90,
+ tintColor = Color.BLACK,
+ displayUniqueId = null
+ )
verify(decorProvider1, times(1)).onReloadResAndMeasure(
- overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null)
+ overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, Color.BLACK, null
+ )
verify(decorProvider2, times(1)).onReloadResAndMeasure(
- overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null)
+ overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, Color.BLACK, null
+ )
}
@Test
fun testOnReloadResAndMeasureWithIds() {
- overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
- overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
+ overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0, Color.BLACK)
+ overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0, Color.BLACK)
overlay.onReloadResAndMeasure(
- filterIds = arrayOf(TEST_DECOR_VIEW_ID_2),
- reloadToken = 1,
- rotation = Surface.ROTATION_90,
- displayUniqueId = null)
+ filterIds = arrayOf(TEST_DECOR_VIEW_ID_2),
+ reloadToken = 1,
+ rotation = Surface.ROTATION_90,
+ tintColor = Color.BLACK,
+ displayUniqueId = null
+ )
verify(decorProvider1, never()).onReloadResAndMeasure(
- overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null)
+ overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, Color.BLACK, null
+ )
verify(decorProvider2, times(1)).onReloadResAndMeasure(
- overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null)
+ overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, Color.BLACK, null
+ )
}
@Test
fun testRemoveRedundantViewsWithNullParameter() {
- overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
- overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
+ overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270, Color.BLACK)
+ overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270, Color.BLACK)
overlay.removeRedundantViews(null)
@@ -146,13 +165,15 @@
@Test
fun testRemoveRedundantViewsWith2Providers() {
- overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
- overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
+ overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270, Color.BLACK)
+ overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270, Color.BLACK)
- overlay.removeRedundantViews(IntArray(2).apply {
- this[0] = TEST_DECOR_VIEW_ID_3
- this[1] = TEST_DECOR_VIEW_ID_1
- })
+ overlay.removeRedundantViews(
+ IntArray(2).apply {
+ this[0] = TEST_DECOR_VIEW_ID_3
+ this[1] = TEST_DECOR_VIEW_ID_1
+ }
+ )
Assert.assertNotNull(overlay.getView(TEST_DECOR_VIEW_ID_1))
Assert.assertNotNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_1))
@@ -167,16 +188,16 @@
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
- overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
+ overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0, Color.BLACK)
Assert.assertFalse(overlay.hasSameProviders(emptyList()))
Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider1)))
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
- overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
+ overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0, Color.BLACK)
Assert.assertFalse(overlay.hasSameProviders(emptyList()))
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider1)))
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index abe7ae1..6a55a60 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -448,7 +448,7 @@
@Test
public void testWakeUp_wakesUp() {
- mMachine.wakeUp();
+ mMachine.wakeUp(DozeLog.REASON_SENSOR_PICKUP);
assertTrue(mServiceFake.requestedWakeup);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
index 903e4a1..6b3ec68 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
@@ -75,9 +75,9 @@
}
@Test
- public void forwards_requestWakeUp() throws Exception {
- mWrapper.requestWakeUp();
- verify(mInner).requestWakeUp();
+ public void forwards_requestWakeUp() {
+ mWrapper.requestWakeUp(DozeLog.REASON_SENSOR_PICKUP);
+ verify(mInner).requestWakeUp(DozeLog.REASON_SENSOR_PICKUP);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
index 75f97a2..928b314 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
@@ -48,7 +48,7 @@
}
@Override
- public void requestWakeUp() {
+ public void requestWakeUp(@DozeLog.Reason int reason) {
requestedWakeup = true;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java
index fac58a0..9ae7217 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java
@@ -81,9 +81,9 @@
}
@Test
- public void forwards_requestWakeUp() throws Exception {
- mWrapper.requestWakeUp();
- verify(mInner).requestWakeUp();
+ public void forwards_requestWakeUp() {
+ mWrapper.requestWakeUp(DozeLog.REASON_SENSOR_PICKUP);
+ verify(mInner).requestWakeUp(DozeLog.REASON_SENSOR_PICKUP);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 01a1a37..6436981 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -32,6 +32,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.StatusBarManager;
import android.hardware.Sensor;
import android.hardware.display.AmbientDisplayConfiguration;
import android.testing.AndroidTestingRunner;
@@ -40,12 +41,14 @@
import androidx.test.filters.SmallTest;
+import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dock.DockManager;
import com.android.systemui.doze.DozeTriggers.DozingUpdateUiEvent;
+import com.android.systemui.log.SessionTracker;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -92,12 +95,14 @@
private KeyguardStateController mKeyguardStateController;
@Mock
private DevicePostureController mDevicePostureController;
+ @Mock
+ private SessionTracker mSessionTracker;
private DozeTriggers mTriggers;
private FakeSensorManager mSensors;
private Sensor mTapSensor;
private FakeProximitySensor mProximitySensor;
- private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
+ private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setUp() throws Exception {
@@ -123,14 +128,14 @@
mTriggers = new DozeTriggers(mContext, mHost, config, dozeParameters,
asyncSensorManager, wakeLock, mDockManager, mProximitySensor,
mProximityCheck, mock(DozeLog.class), mBroadcastDispatcher, new FakeSettings(),
- mAuthController, mExecutor, mUiEventLogger, mKeyguardStateController,
+ mAuthController, mUiEventLogger, mSessionTracker, mKeyguardStateController,
mDevicePostureController);
mTriggers.setDozeMachine(mMachine);
waitForSensorManager();
}
@Test
- public void testOnNotification_stillWorksAfterOneFailedProxCheck() throws Exception {
+ public void testOnNotification_stillWorksAfterOneFailedProxCheck() {
when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
ArgumentCaptor<DozeHost.Callback> captor = ArgumentCaptor.forClass(DozeHost.Callback.class);
doAnswer(invocation -> null).when(mHost).addCallback(captor.capture());
@@ -216,7 +221,7 @@
}
@Test
- public void testProximitySensorNotAvailablel() {
+ public void testProximitySensorNotAvailable() {
mProximitySensor.setSensorAvailable(false);
mTriggers.onSensor(DozeLog.PULSE_REASON_SENSOR_LONG_PRESS, 100, 100, null);
mTriggers.onSensor(DozeLog.PULSE_REASON_SENSOR_WAKE_REACH, 100, 100,
@@ -228,6 +233,9 @@
public void testQuickPickup() {
// GIVEN device is in doze (screen blank, but running doze sensors)
when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
+ InstanceId keyguardSessionId = InstanceId.fakeInstanceId(99);
+ when(mSessionTracker.getSessionId(StatusBarManager.SESSION_KEYGUARD))
+ .thenReturn(keyguardSessionId);
// WHEN quick pick up is triggered
mTriggers.onSensor(DozeLog.REASON_SENSOR_QUICK_PICKUP, 100, 100, null);
@@ -236,7 +244,8 @@
verify(mMachine).requestPulse(anyInt());
// THEN a log is taken that quick pick up was triggered
- verify(mUiEventLogger).log(DozingUpdateUiEvent.DOZING_UPDATE_QUICK_PICKUP);
+ verify(mUiEventLogger)
+ .log(DozingUpdateUiEvent.DOZING_UPDATE_QUICK_PICKUP, keyguardSessionId);
}
@Test
@@ -249,7 +258,7 @@
mTriggers.onSensor(DozeLog.REASON_SENSOR_PICKUP, 100, 100, null);
// THEN wakeup
- verify(mMachine).wakeUp();
+ verify(mMachine).wakeUp(DozeLog.REASON_SENSOR_PICKUP);
}
@Test
@@ -262,7 +271,7 @@
mTriggers.onSensor(DozeLog.REASON_SENSOR_PICKUP, 100, 100, null);
// THEN never wakeup
- verify(mMachine, never()).wakeUp();
+ verify(mMachine, never()).wakeUp(DozeLog.REASON_SENSOR_PICKUP);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationTypesUpdaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationTypesUpdaterTest.java
index 09976e0..571dd3d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationTypesUpdaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationTypesUpdaterTest.java
@@ -106,7 +106,7 @@
private ContentObserver captureSettingsObserver() {
verify(mSecureSettings).registerContentObserverForUser(
- eq(Settings.Secure.SCREENSAVER_ENABLED_COMPLICATIONS),
+ eq(Settings.Secure.SCREENSAVER_COMPLICATIONS_ENABLED),
mSettingsObserverCaptor.capture(), eq(UserHandle.myUserId()));
return mSettingsObserverCaptor.getValue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamMediaEntryComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamMediaEntryComplicationTest.java
new file mode 100644
index 0000000..bc94440
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamMediaEntryComplicationTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication;
+
+import static org.mockito.Mockito.verify;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.View;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.media.dream.MediaDreamComplication;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class DreamMediaEntryComplicationTest extends SysuiTestCase {
+ @Mock
+ private View mView;
+
+ @Mock
+ private DreamOverlayStateController mDreamOverlayStateController;
+
+ @Mock
+ private MediaDreamComplication mMediaComplication;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ /**
+ * Ensures clicking media entry chip adds/removes media complication.
+ */
+ @Test
+ public void testClick() {
+ final DreamMediaEntryComplication.DreamMediaEntryViewController viewController =
+ new DreamMediaEntryComplication.DreamMediaEntryViewController(
+ mView,
+ mDreamOverlayStateController,
+ mMediaComplication);
+
+ final ArgumentCaptor<View.OnClickListener> clickListenerCaptor =
+ ArgumentCaptor.forClass(View.OnClickListener.class);
+ verify(mView).setOnClickListener(clickListenerCaptor.capture());
+
+ clickListenerCaptor.getValue().onClick(mView);
+ verify(mView).setSelected(true);
+ verify(mDreamOverlayStateController).addComplication(mMediaComplication);
+ clickListenerCaptor.getValue().onClick(mView);
+ verify(mView).setSelected(false);
+ verify(mDreamOverlayStateController).removeComplication(mMediaComplication);
+ }
+
+ /**
+ * Ensures media complication is removed when the view is detached.
+ */
+ @Test
+ public void testOnViewDetached() {
+ final DreamMediaEntryComplication.DreamMediaEntryViewController viewController =
+ new DreamMediaEntryComplication.DreamMediaEntryViewController(
+ mView,
+ mDreamOverlayStateController,
+ mMediaComplication);
+
+ viewController.onViewDetached();
+ verify(mView).setSelected(false);
+ verify(mDreamOverlayStateController).removeComplication(mMediaComplication);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
index 7d54758..fa8f88a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
@@ -43,7 +43,7 @@
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
-import java.util.Arrays;
+import java.util.Collections;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -61,9 +61,6 @@
private SmartSpaceComplication mComplication;
@Mock
- private ComplicationViewModel mComplicationViewModel;
-
- @Mock
private View mBcSmartspaceView;
@Before
@@ -125,12 +122,12 @@
// Test
final SmartspaceTarget target = Mockito.mock(SmartspaceTarget.class);
- listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList(target));
+ listenerCaptor.getValue().onSmartspaceTargetsUpdated(Collections.singletonList(target));
verify(mDreamOverlayStateController).addComplication(eq(mComplication));
}
@Test
- public void testOverlayActive_targetsEmpty_removesComplication() {
+ public void testOverlayActive_targetsEmpty_addsComplication() {
final SmartSpaceComplication.Registrant registrant = getRegistrant();
registrant.start();
@@ -145,13 +142,9 @@
ArgumentCaptor.forClass(BcSmartspaceDataPlugin.SmartspaceTargetListener.class);
verify(mSmartspaceController).addListener(listenerCaptor.capture());
- final SmartspaceTarget target = Mockito.mock(SmartspaceTarget.class);
- listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList(target));
- verify(mDreamOverlayStateController).addComplication(eq(mComplication));
-
// Test
- listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList());
- verify(mDreamOverlayStateController).removeComplication(eq(mComplication));
+ listenerCaptor.getValue().onSmartspaceTargetsUpdated(Collections.emptyList());
+ verify(mDreamOverlayStateController).addComplication(eq(mComplication));
}
@Test
@@ -170,8 +163,7 @@
ArgumentCaptor.forClass(BcSmartspaceDataPlugin.SmartspaceTargetListener.class);
verify(mSmartspaceController).addListener(listenerCaptor.capture());
- final SmartspaceTarget target = Mockito.mock(SmartspaceTarget.class);
- listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList(target));
+ listenerCaptor.getValue().onSmartspaceTargetsUpdated(Collections.emptyList());
verify(mDreamOverlayStateController).addComplication(eq(mComplication));
// Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlags.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlags.kt
deleted file mode 100644
index 7b1455c..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlags.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.flags
-
-import android.util.SparseArray
-import android.util.SparseBooleanArray
-import androidx.core.util.containsKey
-
-class FakeFeatureFlags : FeatureFlags {
- private val booleanFlags = SparseBooleanArray()
- private val stringFlags = SparseArray<String>()
- private val knownFlagNames = mutableMapOf<Int, String>()
-
- init {
- Flags.getFlagFields().forEach { field ->
- val flag: Flag<*> = field.get(null) as Flag<*>
- knownFlagNames[flag.id] = field.name
- }
- }
-
- fun set(flag: BooleanFlag, value: Boolean) {
- booleanFlags.put(flag.id, value)
- }
-
- fun set(flag: DeviceConfigBooleanFlag, value: Boolean) {
- booleanFlags.put(flag.id, value)
- }
-
- fun set(flag: ResourceBooleanFlag, value: Boolean) {
- booleanFlags.put(flag.id, value)
- }
-
- fun set(flag: SysPropBooleanFlag, value: Boolean) {
- booleanFlags.put(flag.id, value)
- }
-
- fun set(flag: StringFlag, value: String) {
- stringFlags.put(flag.id, value)
- }
-
- fun set(flag: ResourceStringFlag, value: String) {
- stringFlags.put(flag.id, value)
- }
-
-
- override fun isEnabled(flag: UnreleasedFlag): Boolean = requireBooleanValue(flag.id)
-
- override fun isEnabled(flag: ReleasedFlag): Boolean = requireBooleanValue(flag.id)
-
- override fun isEnabled(flag: ResourceBooleanFlag): Boolean = requireBooleanValue(flag.id)
-
- override fun isEnabled(flag: DeviceConfigBooleanFlag): Boolean = requireBooleanValue(flag.id)
-
- override fun isEnabled(flag: SysPropBooleanFlag): Boolean = requireBooleanValue(flag.id)
-
- override fun getString(flag: StringFlag): String = requireStringValue(flag.id)
-
- override fun getString(flag: ResourceStringFlag): String = requireStringValue(flag.id)
-
- override fun addListener(flag: Flag<*>, listener: FlagListenable.Listener) {}
-
- override fun removeListener(listener: FlagListenable.Listener) {}
-
- private fun flagName(flagId: Int): String {
- return knownFlagNames[flagId] ?: "UNKNOWN(id=$flagId)"
- }
-
- private fun requireBooleanValue(flagId: Int): Boolean {
- if (!booleanFlags.containsKey(flagId)) {
- throw IllegalStateException("Flag ${flagName(flagId)} was accessed but not specified.")
- }
- return booleanFlags[flagId]
- }
-
- private fun requireStringValue(flagId: Int): String {
- if (!stringFlags.containsKey(flagId)) {
- throw IllegalStateException("Flag ${flagName(flagId)} was accessed but not specified.")
- }
- return stringFlags[flagId]
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt
index ff579a1..318f2bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt
@@ -41,7 +41,7 @@
* specified. If not, an exception is thrown.
*/
@Test
- fun throwsIfUnspecifiedFlagIsAccessed() {
+ fun accessingUnspecifiedFlags_throwsException() {
val flags: FeatureFlags = FakeFeatureFlags()
try {
assertThat(flags.isEnabled(Flags.TEAMFOOD)).isFalse()
@@ -88,7 +88,7 @@
}
@Test
- fun specifiedFlagsReturnCorrectValues() {
+ fun specifiedFlags_returnCorrectValues() {
val flags = FakeFeatureFlags()
flags.set(unreleasedFlag, false)
flags.set(releasedFlag, false)
@@ -114,4 +114,125 @@
assertThat(flags.isEnabled(sysPropBooleanFlag)).isTrue()
assertThat(flags.getString(resourceStringFlag)).isEqualTo("Android")
}
+
+ @Test
+ fun listenerForBooleanFlag_calledOnlyWhenFlagChanged() {
+ val flags = FakeFeatureFlags()
+ val listener = VerifyingListener()
+ flags.addListener(unreleasedFlag, listener)
+
+ flags.set(unreleasedFlag, true)
+ flags.set(unreleasedFlag, true)
+ flags.set(unreleasedFlag, false)
+ flags.set(unreleasedFlag, false)
+
+ listener.verifyInOrder(unreleasedFlag.id, unreleasedFlag.id)
+ }
+
+ @Test
+ fun listenerForStringFlag_calledOnlyWhenFlagChanged() {
+ val flags = FakeFeatureFlags()
+ val listener = VerifyingListener()
+ flags.addListener(stringFlag, listener)
+
+ flags.set(stringFlag, "Test")
+ flags.set(stringFlag, "Test")
+
+ listener.verifyInOrder(stringFlag.id)
+ }
+
+ @Test
+ fun listenerForBooleanFlag_notCalledAfterRemoved() {
+ val flags = FakeFeatureFlags()
+ val listener = VerifyingListener()
+ flags.addListener(unreleasedFlag, listener)
+ flags.set(unreleasedFlag, true)
+ flags.removeListener(listener)
+ flags.set(unreleasedFlag, false)
+
+ listener.verifyInOrder(unreleasedFlag.id)
+ }
+
+ @Test
+ fun listenerForStringFlag_notCalledAfterRemoved() {
+ val flags = FakeFeatureFlags()
+ val listener = VerifyingListener()
+
+ flags.addListener(stringFlag, listener)
+ flags.set(stringFlag, "Test")
+ flags.removeListener(listener)
+ flags.set(stringFlag, "Other")
+
+ listener.verifyInOrder(stringFlag.id)
+ }
+
+ @Test
+ fun listenerForMultipleFlags_calledWhenFlagsChange() {
+ val flags = FakeFeatureFlags()
+ val listener = VerifyingListener()
+ flags.addListener(unreleasedFlag, listener)
+ flags.addListener(releasedFlag, listener)
+
+ flags.set(releasedFlag, true)
+ flags.set(unreleasedFlag, true)
+
+ listener.verifyInOrder(releasedFlag.id, unreleasedFlag.id)
+ }
+
+ @Test
+ fun listenerForMultipleFlags_notCalledAfterRemoved() {
+ val flags = FakeFeatureFlags()
+ val listener = VerifyingListener()
+
+ flags.addListener(unreleasedFlag, listener)
+ flags.addListener(releasedFlag, listener)
+ flags.set(releasedFlag, true)
+ flags.set(unreleasedFlag, true)
+ flags.removeListener(listener)
+ flags.set(releasedFlag, false)
+ flags.set(unreleasedFlag, false)
+
+ listener.verifyInOrder(releasedFlag.id, unreleasedFlag.id)
+ }
+
+ @Test
+ fun multipleListenersForSingleFlag_allAreCalledWhenChanged() {
+ val flags = FakeFeatureFlags()
+ val listener1 = VerifyingListener()
+ val listener2 = VerifyingListener()
+ flags.addListener(releasedFlag, listener1)
+ flags.addListener(releasedFlag, listener2)
+
+ flags.set(releasedFlag, true)
+
+ listener1.verifyInOrder(releasedFlag.id)
+ listener2.verifyInOrder(releasedFlag.id)
+ }
+
+ @Test
+ fun multipleListenersForSingleFlag_removedListenerNotCalledAfterRemoval() {
+ val flags = FakeFeatureFlags()
+ val listener1 = VerifyingListener()
+ val listener2 = VerifyingListener()
+ flags.addListener(releasedFlag, listener1)
+ flags.addListener(releasedFlag, listener2)
+
+ flags.set(releasedFlag, true)
+ flags.removeListener(listener2)
+ flags.set(releasedFlag, false)
+
+ listener1.verifyInOrder(releasedFlag.id, releasedFlag.id)
+ listener2.verifyInOrder(releasedFlag.id)
+ }
+
+ class VerifyingListener : FlagListenable.Listener {
+ var flagEventIds = mutableListOf<Int>()
+ override fun onFlagChanged(event: FlagListenable.FlagEvent) {
+ flagEventIds.add(event.flagId)
+ }
+
+ fun verifyInOrder(vararg eventIds: Int) {
+ assertThat(flagEventIds).containsExactlyElementsIn(eventIds.asList())
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/AnimatableClockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/AnimatableClockControllerTest.java
index df506b4..b5e9e8d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/AnimatableClockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/AnimatableClockControllerTest.java
@@ -38,6 +38,7 @@
import com.android.settingslib.Utils;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.clocks.AnimatableClockView;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -53,6 +54,8 @@
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
+import java.util.concurrent.Executor;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -69,6 +72,12 @@
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock
private Resources mResources;
+ @Mock
+ private Executor mMainExecutor;
+ @Mock
+ private Executor mBgExecutor;
+ @Mock
+ private FeatureFlags mFeatureFlags;
private MockitoSession mStaticMockSession;
private AnimatableClockController mAnimatableClockController;
@@ -96,7 +105,10 @@
mBroadcastDispatcher,
mBatteryController,
mKeyguardUpdateMonitor,
- mResources
+ mResources,
+ mMainExecutor,
+ mBgExecutor,
+ mFeatureFlags
);
mAnimatableClockController.init();
captureAttachListener();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java
index 24d0515..cefd68d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java
@@ -30,7 +30,7 @@
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.PointF;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.AnimatedStateListDrawable;
import android.hardware.biometrics.BiometricSourceType;
@@ -125,7 +125,7 @@
ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
private KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback;
- @Captor private ArgumentCaptor<PointF> mPointCaptor;
+ @Captor private ArgumentCaptor<Point> mPointCaptor;
@Before
public void setUp() throws Exception {
@@ -176,7 +176,7 @@
@Test
public void testUpdateFingerprintLocationOnInit() {
// GIVEN fp sensor location is available pre-attached
- Pair<Float, PointF> udfps = setupUdfps(); // first = radius, second = udfps location
+ Pair<Float, Point> udfps = setupUdfps(); // first = radius, second = udfps location
// WHEN lock icon view controller is initialized and attached
mLockIconViewController.init();
@@ -191,7 +191,7 @@
@Test
public void testUpdatePaddingBasedOnResolutionScale() {
// GIVEN fp sensor location is available pre-attached & scaled resolution factor is 5
- Pair<Float, PointF> udfps = setupUdfps(); // first = radius, second = udfps location
+ Pair<Float, Point> udfps = setupUdfps(); // first = radius, second = udfps location
when(mAuthController.getScaleFactor()).thenReturn(5f);
// WHEN lock icon view controller is initialized and attached
@@ -216,7 +216,7 @@
// GIVEN fp sensor location is available post-attached
captureAuthControllerCallback();
- Pair<Float, PointF> udfps = setupUdfps();
+ Pair<Float, Point> udfps = setupUdfps();
// WHEN all authenticators are registered
mAuthControllerCallback.onAllAuthenticatorsRegistered();
@@ -239,7 +239,7 @@
// GIVEN fp sensor location is available post-attached
captureAuthControllerCallback();
- Pair<Float, PointF> udfps = setupUdfps();
+ Pair<Float, Point> udfps = setupUdfps();
// WHEN udfps location changes
mAuthControllerCallback.onUdfpsLocationChanged();
@@ -419,9 +419,9 @@
verify(mLockIconView).setTranslationX(0);
}
- private Pair<Float, PointF> setupUdfps() {
+ private Pair<Float, Point> setupUdfps() {
when(mKeyguardUpdateMonitor.isUdfpsSupported()).thenReturn(true);
- final PointF udfpsLocation = new PointF(50, 75);
+ final Point udfpsLocation = new Point(50, 75);
final float radius = 33f;
when(mAuthController.getUdfpsLocation()).thenReturn(udfpsLocation);
when(mAuthController.getUdfpsRadius()).thenReturn(radius);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
index 219b3c8..1bc1972 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
@@ -28,9 +28,11 @@
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider
import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.util.animation.TransitionLayout
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
+import javax.inject.Provider
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertTrue
import org.junit.Before
@@ -38,8 +40,9 @@
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
-import javax.inject.Provider
private val DATA = MediaTestUtils.emptyMediaData
@@ -64,6 +67,10 @@
@Mock lateinit var dumpManager: DumpManager
@Mock lateinit var logger: MediaUiEventLogger
@Mock lateinit var debugLogger: MediaCarouselControllerLogger
+ @Mock lateinit var mediaViewHolder: MediaViewHolder
+ @Mock lateinit var player: TransitionLayout
+ @Mock lateinit var recommendationViewHolder: RecommendationViewHolder
+ @Mock lateinit var recommendations: TransitionLayout
private val clock = FakeSystemClock()
private lateinit var mediaCarouselController: MediaCarouselController
@@ -258,4 +265,44 @@
verify(logger).logRecommendationRemoved(eq(packageName), eq(instanceId!!))
}
-}
\ No newline at end of file
+
+ @Test
+ fun testSetSquishinessFractionForMedia_setPlayerBottom() {
+ whenever(panel.mediaViewHolder).thenReturn(mediaViewHolder)
+ whenever(mediaViewHolder.player).thenReturn(player)
+ whenever(player.measuredHeight).thenReturn(100)
+
+ val playingLocal = Triple("playing local",
+ DATA.copy(active = true, isPlaying = true,
+ playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false),
+ 4500L)
+ MediaPlayerData.addMediaPlayer(playingLocal.first, playingLocal.second, panel, clock,
+ false, debugLogger)
+
+ mediaCarouselController.squishinessFraction = 0.0f
+ verify(player).bottom = 50
+ verifyNoMoreInteractions(recommendationViewHolder)
+
+ mediaCarouselController.squishinessFraction = 0.5f
+ verify(player).bottom = 75
+ verifyNoMoreInteractions(recommendationViewHolder)
+ }
+
+ @Test
+ fun testSetSquishinessFractionForRecommendation_setPlayerBottom() {
+ whenever(panel.recommendationViewHolder).thenReturn(recommendationViewHolder)
+ whenever(recommendationViewHolder.recommendations).thenReturn(recommendations)
+ whenever(recommendations.measuredHeight).thenReturn(100)
+
+ MediaPlayerData.addMediaRecommendation(SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA, panel,
+ false, clock)
+
+ mediaCarouselController.squishinessFraction = 0.0f
+ verifyNoMoreInteractions(mediaViewHolder)
+ verify(recommendationViewHolder.recommendations).bottom = 50
+
+ mediaCarouselController.squishinessFraction = 0.5f
+ verifyNoMoreInteractions(mediaViewHolder)
+ verify(recommendationViewHolder.recommendations).bottom = 75
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index 1785022..bef4695 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -1051,6 +1051,17 @@
}
@Test
+ fun bindDeviceWithNullName() {
+ val fallbackString = context.getResources().getString(R.string.media_seamless_other_device)
+ player.attachPlayer(viewHolder)
+ val state = mediaData.copy(device = device.copy(name = null))
+ player.bindPlayer(state, PACKAGE)
+ assertThat(seamless.isEnabled()).isTrue()
+ assertThat(seamlessText.getText()).isEqualTo(fallbackString)
+ assertThat(seamless.contentDescription).isEqualTo(fallbackString)
+ }
+
+ @Test
fun bindDeviceResumptionPlayer() {
player.attachPlayer(viewHolder)
val state = mediaData.copy(resumption = true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
index d1ed8e9..f9c7d2d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -31,7 +31,6 @@
import com.android.systemui.tuner.TunerService
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
@@ -108,6 +107,7 @@
private val clock = FakeSystemClock()
@Mock private lateinit var tunerService: TunerService
@Captor lateinit var tunableCaptor: ArgumentCaptor<TunerService.Tunable>
+ @Captor lateinit var callbackCaptor: ArgumentCaptor<(String, PlaybackState) -> Unit>
private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20)
@@ -974,7 +974,6 @@
fun testPlaybackStateChange_keyExists_callsListener() {
// Notification has been added
addNotificationAndLoad()
- val callbackCaptor = argumentCaptor<(String, PlaybackState) -> Unit>()
verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor)
// Callback gets an updated state
@@ -992,7 +991,6 @@
@Test
fun testPlaybackStateChange_keyDoesNotExist_doesNothing() {
val state = PlaybackState.Builder().build()
- val callbackCaptor = argumentCaptor<(String, PlaybackState) -> Unit>()
verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor)
// No media added with this key
@@ -1013,7 +1011,6 @@
// And then get a state update
val state = PlaybackState.Builder().build()
- val callbackCaptor = argumentCaptor<(String, PlaybackState) -> Unit>()
verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor)
// Then no changes are made
@@ -1022,6 +1019,83 @@
anyBoolean())
}
+ @Test
+ fun testPlaybackState_PauseWhenFlagTrue_keyExists_callsListener() {
+ whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
+ val state = PlaybackState.Builder()
+ .setState(PlaybackState.STATE_PAUSED, 0L, 1f)
+ .build()
+ whenever(controller.playbackState).thenReturn(state)
+
+ addNotificationAndLoad()
+ verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor)
+ callbackCaptor.value.invoke(KEY, state)
+
+ verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY),
+ capture(mediaDataCaptor), eq(true), eq(0), eq(false))
+ assertThat(mediaDataCaptor.value.isPlaying).isFalse()
+ assertThat(mediaDataCaptor.value.semanticActions).isNotNull()
+ }
+
+ @Test
+ fun testPlaybackState_PauseStateAfterAddingResumption_keyExists_callsListener() {
+ val desc = MediaDescription.Builder().run {
+ setTitle(SESSION_TITLE)
+ build()
+ }
+ val state = PlaybackState.Builder()
+ .setState(PlaybackState.STATE_PAUSED, 0L, 1f)
+ .setActions(PlaybackState.ACTION_PLAY_PAUSE)
+ .build()
+
+ // Add resumption controls in order to have semantic actions.
+ // To make sure that they are not null after changing state.
+ mediaDataManager.addResumptionControls(
+ USER_ID,
+ desc,
+ Runnable {},
+ session.sessionToken,
+ APP_NAME,
+ pendingIntent,
+ PACKAGE_NAME
+ )
+ backgroundExecutor.runAllReady()
+ foregroundExecutor.runAllReady()
+
+ verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor)
+ callbackCaptor.value.invoke(PACKAGE_NAME, state)
+
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(PACKAGE_NAME),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ assertThat(mediaDataCaptor.value.isPlaying).isFalse()
+ assertThat(mediaDataCaptor.value.semanticActions).isNotNull()
+ }
+
+ @Test
+ fun testPlaybackStateNull_Pause_keyExists_callsListener() {
+ whenever(controller.playbackState).thenReturn(null)
+ val state = PlaybackState.Builder()
+ .setState(PlaybackState.STATE_PAUSED, 0L, 1f)
+ .setActions(PlaybackState.ACTION_PLAY_PAUSE)
+ .build()
+
+ addNotificationAndLoad()
+ verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor)
+ callbackCaptor.value.invoke(KEY, state)
+
+ verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY),
+ capture(mediaDataCaptor), eq(true), eq(0), eq(false))
+ assertThat(mediaDataCaptor.value.isPlaying).isFalse()
+ assertThat(mediaDataCaptor.value.semanticActions).isNull()
+ }
+
/**
* Helper function to add a media notification and capture the resulting MediaData
*/
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
index ee10426..121c894 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
@@ -59,8 +59,8 @@
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
+import org.mockito.junit.MockitoJUnit
private const val KEY = "TEST_KEY"
private const val KEY_OLD = "TEST_KEY_OLD"
@@ -402,9 +402,10 @@
manager.onMediaDataLoaded(KEY, null, mediaData)
fakeBgExecutor.runAllReady()
fakeFgExecutor.runAllReady()
- // THEN the device is disabled
+ // THEN the device is disabled and name is set to null
val data = captureDeviceData(KEY)
assertThat(data.enabled).isFalse()
+ assertThat(data.name).isNull()
}
@Test
@@ -421,9 +422,10 @@
deviceCallback.onSelectedDeviceStateChanged(device, 1)
fakeBgExecutor.runAllReady()
fakeFgExecutor.runAllReady()
- // THEN the device is disabled
+ // THEN the device is disabled and name is set to null
val data = captureDeviceData(KEY)
assertThat(data.enabled).isFalse()
+ assertThat(data.name).isNull()
}
@Test
@@ -440,9 +442,24 @@
deviceCallback.onDeviceListUpdate(mutableListOf(device))
fakeBgExecutor.runAllReady()
fakeFgExecutor.runAllReady()
- // THEN the device is disabled
+ // THEN the device is disabled and name is set to null
val data = captureDeviceData(KEY)
assertThat(data.enabled).isFalse()
+ assertThat(data.name).isNull()
+ }
+
+ @Test
+ fun mr2ReturnsRouteWithNullName_useLocalDeviceName() {
+ // GIVEN that MR2Manager returns a routing session that does not have a name
+ whenever(route.name).thenReturn(null)
+ // WHEN a notification is added
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+ // THEN the device is enabled and uses the current connected device name
+ val data = captureDeviceData(KEY)
+ assertThat(data.name).isEqualTo(DEVICE_NAME)
+ assertThat(data.enabled).isTrue()
}
@Test
@@ -647,12 +664,14 @@
override fun onPlaybackStopped(reason: Int, broadcastId: Int) {}
override fun onBroadcastUpdated(reason: Int, broadcastId: Int) {}
override fun onBroadcastUpdateFailed(reason: Int, broadcastId: Int) {}
- override fun onBroadcastMetadataChanged(broadcastId: Int,
- metadata: BluetoothLeBroadcastMetadata) {}
+ override fun onBroadcastMetadataChanged(
+ broadcastId: Int,
+ metadata: BluetoothLeBroadcastMetadata
+ ) {}
}
bluetoothLeBroadcast.registerCallback(fakeFgExecutor, callback)
- return callback;
+ return callback
}
fun setupLeAudioConfiguration(isLeAudio: Boolean) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 260bb87..22ecb4b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -78,7 +78,7 @@
when(mMediaOutputController.getMediaDevices()).thenReturn(mMediaDevices);
when(mMediaOutputController.hasAdjustVolumeUserRestriction()).thenReturn(false);
- when(mMediaOutputController.isTransferring()).thenReturn(false);
+ when(mMediaOutputController.isAnyDeviceTransferring()).thenReturn(false);
when(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).thenReturn(mIconCompat);
when(mMediaOutputController.getDeviceIconCompat(mMediaDevice2)).thenReturn(mIconCompat);
when(mMediaOutputController.getCurrentConnectedMediaDevice()).thenReturn(mMediaDevice1);
@@ -208,7 +208,7 @@
@Test
public void onBindViewHolder_inTransferring_bindTransferringDevice_verifyView() {
- when(mMediaOutputController.isTransferring()).thenReturn(true);
+ when(mMediaOutputController.isAnyDeviceTransferring()).thenReturn(true);
when(mMediaDevice1.getState()).thenReturn(
LocalMediaManager.MediaDeviceState.STATE_CONNECTING);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
@@ -224,7 +224,7 @@
@Test
public void onBindViewHolder_inTransferring_bindNonTransferringDevice_verifyView() {
- when(mMediaOutputController.isTransferring()).thenReturn(true);
+ when(mMediaOutputController.isAnyDeviceTransferring()).thenReturn(true);
when(mMediaDevice2.getState()).thenReturn(
LocalMediaManager.MediaDeviceState.STATE_CONNECTING);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 1131a7e..eb8ecae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -224,6 +224,14 @@
}
@Test
+ public void refresh_inDragging_directSetRefreshingToFalse() {
+ when(mMediaOutputBaseAdapter.isDragging()).thenReturn(true);
+ mMediaOutputBaseDialogImpl.refresh();
+
+ assertThat(mMediaOutputController.isRefreshing()).isFalse();
+ }
+
+ @Test
public void refresh_notInDragging_verifyUpdateAdapter() {
when(mMediaOutputBaseAdapter.getCurrentActivePosition()).thenReturn(-1);
when(mMediaOutputBaseAdapter.isDragging()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java
index c101b9f..2e864dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java
@@ -18,6 +18,7 @@
import static com.android.systemui.flags.Flags.MEDIA_DREAM_COMPLICATION;
+import static org.mockito.AdditionalMatchers.not;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
@@ -30,6 +31,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.dreams.complication.DreamMediaEntryComplication;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.MediaData;
import com.android.systemui.media.MediaDataManager;
@@ -51,7 +53,7 @@
DreamOverlayStateController mDreamOverlayStateController;
@Mock
- MediaDreamComplication mComplication;
+ DreamMediaEntryComplication mMediaEntryComplication;
@Mock
FeatureFlags mFeatureFlags;
@@ -72,7 +74,7 @@
@Test
public void testComplicationAddition() {
final MediaDreamSentinel sentinel = new MediaDreamSentinel(mContext, mMediaDataManager,
- mDreamOverlayStateController, mComplication, mFeatureFlags);
+ mDreamOverlayStateController, mMediaEntryComplication, mFeatureFlags);
sentinel.start();
@@ -85,14 +87,16 @@
when(mMediaDataManager.hasActiveMedia()).thenReturn(true);
listener.onMediaDataLoaded(mKey, mOldKey, mData, /* immediately= */true,
/* receivedSmartspaceCardLatency= */0, /* isSsReactived= */ false);
- verify(mDreamOverlayStateController).addComplication(eq(mComplication));
+ verify(mDreamOverlayStateController).addComplication(eq(mMediaEntryComplication));
+ verify(mDreamOverlayStateController, never()).addComplication(
+ not(eq(mMediaEntryComplication)));
listener.onMediaDataRemoved(mKey);
verify(mDreamOverlayStateController, never()).removeComplication(any());
when(mMediaDataManager.hasActiveMedia()).thenReturn(false);
listener.onMediaDataRemoved(mKey);
- verify(mDreamOverlayStateController).removeComplication(eq(mComplication));
+ verify(mDreamOverlayStateController).removeComplication(eq(mMediaEntryComplication));
}
@Test
@@ -100,7 +104,7 @@
when(mFeatureFlags.isEnabled(MEDIA_DREAM_COMPLICATION)).thenReturn(false);
final MediaDreamSentinel sentinel = new MediaDreamSentinel(mContext, mMediaDataManager,
- mDreamOverlayStateController, mComplication, mFeatureFlags);
+ mDreamOverlayStateController, mMediaEntryComplication, mFeatureFlags);
sentinel.start();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java
index 2927669..7bae115 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.qs;
+import static android.os.PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE;
+
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
@@ -34,6 +36,7 @@
import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -185,9 +188,9 @@
public void testChangesSinceLastDialog() throws RemoteException {
setUserProfiles(0);
- Assert.assertFalse(mFmc.getChangesSinceDialog());
+ Assert.assertFalse(mFmc.getNewChangesSinceDialogWasDismissed());
mIForegroundServiceObserver.onForegroundStateChanged(new Binder(), "pkg", 0, true);
- Assert.assertTrue(mFmc.getChangesSinceDialog());
+ Assert.assertTrue(mFmc.getNewChangesSinceDialogWasDismissed());
}
@Test
@@ -222,7 +225,41 @@
Assert.assertEquals(2, mFmc.getNumRunningPackages());
}
+ @Test
+ public void testButtonVisibilityOnShowAllowlistButtonFlagChange() throws Exception {
+ setUserProfiles(0);
+ setBackgroundRestrictionExemptionReason("pkg", 12345, REASON_ALLOWLISTED_PACKAGE);
+ final Binder binder = new Binder();
+ setShowStopButtonForUserAllowlistedApps(true);
+ mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, true);
+ Assert.assertEquals(1, mFmc.visibleButtonsCount());
+
+ mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, false);
+ Assert.assertEquals(0, mFmc.visibleButtonsCount());
+
+ setShowStopButtonForUserAllowlistedApps(false);
+ mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, true);
+ Assert.assertEquals(0, mFmc.visibleButtonsCount());
+ }
+
+ private void setShowStopButtonForUserAllowlistedApps(boolean enable) {
+ mDeviceConfigProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
+ enable ? "true" : "false", false);
+ mBackgroundExecutor.advanceClockToLast();
+ mBackgroundExecutor.runAllReady();
+ }
+
+ private void setBackgroundRestrictionExemptionReason(String pkgName, int uid, int reason)
+ throws Exception {
+ Mockito.doReturn(uid)
+ .when(mPackageManager)
+ .getPackageUidAsUser(pkgName, UserHandle.getUserId(uid));
+ Mockito.doReturn(reason)
+ .when(mIActivityManager)
+ .getBackgroundRestrictionExemptionReason(uid);
+ }
FgsManagerController createFgsManagerController() throws RemoteException {
ArgumentCaptor<IForegroundServiceObserver> iForegroundServiceObserverArgumentCaptor =
@@ -232,7 +269,7 @@
ArgumentCaptor<BroadcastReceiver> showFgsManagerReceiverArgumentCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
- FgsManagerController result = new FgsManagerController(
+ FgsManagerController result = new FgsManagerControllerImpl(
mContext,
mMainExecutor,
mBackgroundExecutor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 10f6ce8..f08ad24 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -45,12 +45,15 @@
import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSFragmentComponent;
import com.android.systemui.qs.external.TileServiceRequestController;
+import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -390,6 +393,8 @@
setUpMedia();
setUpOther();
+ FakeFeatureFlags featureFlags = new FakeFeatureFlags();
+ featureFlags.set(Flags.NEW_FOOTER_ACTIONS, false);
return new QSFragment(
new RemoteInputQuickSettingsDisabler(
context, commandQueue, mock(ConfigurationController.class)),
@@ -402,7 +407,10 @@
mQsComponentFactory,
mock(QSFragmentDisableFlagsLogger.class),
mFalsingManager,
- mock(DumpManager.class));
+ mock(DumpManager.class),
+ featureFlags,
+ mock(NewFooterActionsController.class),
+ mock(FooterActionsViewModel.Factory.class));
}
private void setUpOther() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index c127a6b..ecc8457 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -44,6 +44,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaCarouselController;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
@@ -86,6 +87,7 @@
@Mock
private QSLogger mQSLogger;
private DumpManager mDumpManager = new DumpManager();
+ private MediaCarouselController mMediaCarouselController;
@Mock
QSTileImpl mQSTile;
@Mock
@@ -108,9 +110,9 @@
protected TestableQSPanelControllerBase(QSPanel view, QSTileHost host,
QSCustomizerController qsCustomizerController, MediaHost mediaHost,
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
- DumpManager dumpManager) {
+ DumpManager dumpManager, MediaCarouselController mediaCarouselController) {
super(view, host, qsCustomizerController, true, mediaHost, metricsLogger, uiEventLogger,
- qsLogger, dumpManager);
+ qsLogger, dumpManager, mediaCarouselController);
}
@Override
@@ -144,7 +146,7 @@
mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
mQSCustomizerController, mMediaHost,
- mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
+ mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mMediaCarouselController);
mController.init();
reset(mQSTileRevealController);
@@ -156,7 +158,7 @@
QSPanelControllerBase<QSPanel> controller = new TestableQSPanelControllerBase(mQSPanel,
mQSTileHost, mQSCustomizerController, mMediaHost,
- mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager) {
+ mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mMediaCarouselController) {
@Override
protected QSTileRevealController createTileRevealController() {
return mQSTileRevealController;
@@ -249,7 +251,7 @@
when(mQSPanel.getDumpableTag()).thenReturn("QSPanelLandscape");
mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
mQSCustomizerController, mMediaHost,
- mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
+ mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mMediaCarouselController);
mController.init();
assertThat(mController.shouldUseHorizontalLayout()).isTrue();
@@ -258,7 +260,7 @@
when(mQSPanel.getDumpableTag()).thenReturn("QSPanelPortrait");
mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
mQSCustomizerController, mMediaHost,
- mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
+ mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mMediaCarouselController);
mController.init();
assertThat(mController.shouldUseHorizontalLayout()).isFalse();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
index c0944ef..98d499a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
@@ -6,6 +6,7 @@
import com.android.internal.logging.UiEventLogger
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
+import com.android.systemui.media.MediaCarouselController
import com.android.systemui.media.MediaHost
import com.android.systemui.media.MediaHostState
import com.android.systemui.plugins.FalsingManager
@@ -27,8 +28,8 @@
import org.mockito.Mockito.any
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -40,6 +41,7 @@
@Mock private lateinit var qsCustomizerController: QSCustomizerController
@Mock private lateinit var qsTileRevealControllerFactory: QSTileRevealController.Factory
@Mock private lateinit var dumpManager: DumpManager
+ @Mock private lateinit var mediaCarouselController: MediaCarouselController
@Mock private lateinit var metricsLogger: MetricsLogger
@Mock private lateinit var uiEventLogger: UiEventLogger
@Mock private lateinit var qsLogger: QSLogger
@@ -76,6 +78,7 @@
mediaHost,
qsTileRevealControllerFactory,
dumpManager,
+ mediaCarouselController,
metricsLogger,
uiEventLogger,
qsLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index c1c0f78..233c267 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -100,6 +100,7 @@
private TextView mFooterText;
private TestableImageView mPrimaryFooterIcon;
private QSSecurityFooter mFooter;
+ private QSSecurityFooterUtils mFooterUtils;
@Mock
private SecurityController mSecurityController;
@Mock
@@ -118,13 +119,16 @@
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
Looper looper = mTestableLooper.getLooper();
+ Handler mainHandler = new Handler(looper);
when(mUserTracker.getUserInfo()).thenReturn(mock(UserInfo.class));
mRootView = (ViewGroup) new LayoutInflaterBuilder(mContext)
.replace("ImageView", TestableImageView.class)
.build().inflate(R.layout.quick_settings_security_footer, null, false);
- mFooter = new QSSecurityFooter(mRootView, mUserTracker, new Handler(looper),
- mActivityStarter, mSecurityController, mDialogLaunchAnimator, looper,
- mBroadcastDispatcher);
+ mFooterUtils = new QSSecurityFooterUtils(getContext(),
+ getContext().getSystemService(DevicePolicyManager.class), mUserTracker,
+ mainHandler, mActivityStarter, mSecurityController, looper, mDialogLaunchAnimator);
+ mFooter = new QSSecurityFooter(mRootView, mainHandler, mSecurityController, looper,
+ mBroadcastDispatcher, mFooterUtils);
mFooterText = mRootView.findViewById(R.id.footer_text);
mPrimaryFooterIcon = mRootView.findViewById(R.id.primary_footer_icon);
@@ -520,7 +524,7 @@
when(mSecurityController.isDeviceManaged()).thenReturn(true);
assertEquals(mContext.getString(R.string.monitoring_title_device_owned),
- mFooter.getManagementTitle(MANAGING_ORGANIZATION));
+ mFooterUtils.getManagementTitle(MANAGING_ORGANIZATION));
}
@Test
@@ -531,12 +535,12 @@
assertEquals(mContext.getString(R.string.monitoring_title_financed_device,
MANAGING_ORGANIZATION),
- mFooter.getManagementTitle(MANAGING_ORGANIZATION));
+ mFooterUtils.getManagementTitle(MANAGING_ORGANIZATION));
}
@Test
public void testGetManagementMessage_noManagement() {
- assertEquals(null, mFooter.getManagementMessage(
+ assertEquals(null, mFooterUtils.getManagementMessage(
/* isDeviceManaged= */ false, MANAGING_ORGANIZATION));
}
@@ -544,10 +548,10 @@
public void testGetManagementMessage_deviceOwner() {
assertEquals(mContext.getString(R.string.monitoring_description_named_management,
MANAGING_ORGANIZATION),
- mFooter.getManagementMessage(
+ mFooterUtils.getManagementMessage(
/* isDeviceManaged= */ true, MANAGING_ORGANIZATION));
assertEquals(mContext.getString(R.string.monitoring_description_management),
- mFooter.getManagementMessage(
+ mFooterUtils.getManagementMessage(
/* isDeviceManaged= */ true,
/* organizationName= */ null));
}
@@ -560,68 +564,68 @@
assertEquals(mContext.getString(R.string.monitoring_financed_description_named_management,
MANAGING_ORGANIZATION, MANAGING_ORGANIZATION),
- mFooter.getManagementMessage(
+ mFooterUtils.getManagementMessage(
/* isDeviceManaged= */ true, MANAGING_ORGANIZATION));
}
@Test
public void testGetCaCertsMessage() {
- assertEquals(null, mFooter.getCaCertsMessage(true, false, false));
- assertEquals(null, mFooter.getCaCertsMessage(false, false, false));
+ assertEquals(null, mFooterUtils.getCaCertsMessage(true, false, false));
+ assertEquals(null, mFooterUtils.getCaCertsMessage(false, false, false));
assertEquals(mContext.getString(R.string.monitoring_description_management_ca_certificate),
- mFooter.getCaCertsMessage(true, true, true));
+ mFooterUtils.getCaCertsMessage(true, true, true));
assertEquals(mContext.getString(R.string.monitoring_description_management_ca_certificate),
- mFooter.getCaCertsMessage(true, false, true));
+ mFooterUtils.getCaCertsMessage(true, false, true));
assertEquals(mContext.getString(
R.string.monitoring_description_managed_profile_ca_certificate),
- mFooter.getCaCertsMessage(false, false, true));
+ mFooterUtils.getCaCertsMessage(false, false, true));
assertEquals(mContext.getString(
R.string.monitoring_description_ca_certificate),
- mFooter.getCaCertsMessage(false, true, false));
+ mFooterUtils.getCaCertsMessage(false, true, false));
}
@Test
public void testGetNetworkLoggingMessage() {
// Test network logging message on a device with a device owner.
// Network traffic may be monitored on the device.
- assertEquals(null, mFooter.getNetworkLoggingMessage(true, false));
+ assertEquals(null, mFooterUtils.getNetworkLoggingMessage(true, false));
assertEquals(mContext.getString(R.string.monitoring_description_management_network_logging),
- mFooter.getNetworkLoggingMessage(true, true));
+ mFooterUtils.getNetworkLoggingMessage(true, true));
// Test network logging message on a device with a managed profile owner
// Network traffic may be monitored on the work profile.
- assertEquals(null, mFooter.getNetworkLoggingMessage(false, false));
+ assertEquals(null, mFooterUtils.getNetworkLoggingMessage(false, false));
assertEquals(
mContext.getString(R.string.monitoring_description_managed_profile_network_logging),
- mFooter.getNetworkLoggingMessage(false, true));
+ mFooterUtils.getNetworkLoggingMessage(false, true));
}
@Test
public void testGetVpnMessage() {
- assertEquals(null, mFooter.getVpnMessage(true, true, null, null));
+ assertEquals(null, mFooterUtils.getVpnMessage(true, true, null, null));
assertEquals(addLink(mContext.getString(R.string.monitoring_description_two_named_vpns,
VPN_PACKAGE, VPN_PACKAGE_2)),
- mFooter.getVpnMessage(true, true, VPN_PACKAGE, VPN_PACKAGE_2));
+ mFooterUtils.getVpnMessage(true, true, VPN_PACKAGE, VPN_PACKAGE_2));
assertEquals(addLink(mContext.getString(R.string.monitoring_description_two_named_vpns,
VPN_PACKAGE, VPN_PACKAGE_2)),
- mFooter.getVpnMessage(false, true, VPN_PACKAGE, VPN_PACKAGE_2));
+ mFooterUtils.getVpnMessage(false, true, VPN_PACKAGE, VPN_PACKAGE_2));
assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
VPN_PACKAGE)),
- mFooter.getVpnMessage(true, false, VPN_PACKAGE, null));
+ mFooterUtils.getVpnMessage(true, false, VPN_PACKAGE, null));
assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
VPN_PACKAGE)),
- mFooter.getVpnMessage(false, false, VPN_PACKAGE, null));
+ mFooterUtils.getVpnMessage(false, false, VPN_PACKAGE, null));
assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
VPN_PACKAGE_2)),
- mFooter.getVpnMessage(true, true, null, VPN_PACKAGE_2));
+ mFooterUtils.getVpnMessage(true, true, null, VPN_PACKAGE_2));
assertEquals(addLink(mContext.getString(
R.string.monitoring_description_managed_profile_named_vpn,
VPN_PACKAGE_2)),
- mFooter.getVpnMessage(false, true, null, VPN_PACKAGE_2));
+ mFooterUtils.getVpnMessage(false, true, null, VPN_PACKAGE_2));
assertEquals(addLink(mContext.getString(
R.string.monitoring_description_personal_profile_named_vpn,
VPN_PACKAGE)),
- mFooter.getVpnMessage(false, true, VPN_PACKAGE, null));
+ mFooterUtils.getVpnMessage(false, true, VPN_PACKAGE, null));
}
@Test
@@ -631,19 +635,19 @@
// Device Management subtitle should be shown when there is Device Management section only
// Other sections visibility will be set somewhere else so it will not be tested here
- mFooter.configSubtitleVisibility(true, false, false, false, view);
+ mFooterUtils.configSubtitleVisibility(true, false, false, false, view);
assertEquals(View.VISIBLE,
view.findViewById(R.id.device_management_subtitle).getVisibility());
// If there are multiple sections, all subtitles should be shown
- mFooter.configSubtitleVisibility(true, true, false, false, view);
+ mFooterUtils.configSubtitleVisibility(true, true, false, false, view);
assertEquals(View.VISIBLE,
view.findViewById(R.id.device_management_subtitle).getVisibility());
assertEquals(View.VISIBLE,
view.findViewById(R.id.ca_certs_subtitle).getVisibility());
// If there are multiple sections, all subtitles should be shown
- mFooter.configSubtitleVisibility(true, true, true, true, view);
+ mFooterUtils.configSubtitleVisibility(true, true, true, true, view);
assertEquals(View.VISIBLE,
view.findViewById(R.id.device_management_subtitle).getVisibility());
assertEquals(View.VISIBLE,
@@ -655,7 +659,7 @@
// If there are multiple sections, all subtitles should be shown, event if there is no
// Device Management section
- mFooter.configSubtitleVisibility(false, true, true, true, view);
+ mFooterUtils.configSubtitleVisibility(false, true, true, true, view);
assertEquals(View.VISIBLE,
view.findViewById(R.id.ca_certs_subtitle).getVisibility());
assertEquals(View.VISIBLE,
@@ -664,13 +668,13 @@
view.findViewById(R.id.vpn_subtitle).getVisibility());
// If there is only 1 section, the title should be hidden
- mFooter.configSubtitleVisibility(false, true, false, false, view);
+ mFooterUtils.configSubtitleVisibility(false, true, false, false, view);
assertEquals(View.GONE,
view.findViewById(R.id.ca_certs_subtitle).getVisibility());
- mFooter.configSubtitleVisibility(false, false, true, false, view);
+ mFooterUtils.configSubtitleVisibility(false, false, true, false, view);
assertEquals(View.GONE,
view.findViewById(R.id.network_logging_subtitle).getVisibility());
- mFooter.configSubtitleVisibility(false, false, false, true, view);
+ mFooterUtils.configSubtitleVisibility(false, false, false, true, view);
assertEquals(View.GONE,
view.findViewById(R.id.vpn_subtitle).getVisibility());
}
@@ -690,6 +694,9 @@
@Test
public void testParentalControls() {
+ // Make sure the security footer is visible, so that the images are updated.
+ when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
+
when(mSecurityController.isParentalControlsEnabled()).thenReturn(true);
Drawable testDrawable = new VectorDrawable();
@@ -719,7 +726,7 @@
when(mSecurityController.isParentalControlsEnabled()).thenReturn(true);
when(mSecurityController.getLabel(any())).thenReturn(PARENTAL_CONTROLS_LABEL);
- View view = mFooter.createDialogView();
+ View view = mFooterUtils.createDialogView();
TextView textView = (TextView) view.findViewById(R.id.parental_controls_title);
assertEquals(PARENTAL_CONTROLS_LABEL, textView.getText());
}
@@ -742,7 +749,7 @@
when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
.thenReturn(DEVICE_OWNER_TYPE_FINANCED);
- View view = mFooter.createDialogView();
+ View view = mFooterUtils.createDialogView();
TextView managementSubtitle = view.findViewById(R.id.device_management_subtitle);
assertEquals(View.VISIBLE, managementSubtitle.getVisibility());
@@ -753,7 +760,7 @@
assertEquals(mContext.getString(R.string.monitoring_financed_description_named_management,
MANAGING_ORGANIZATION, MANAGING_ORGANIZATION), managementMessage.getText());
assertEquals(mContext.getString(R.string.monitoring_button_view_policies),
- mFooter.getSettingsButton());
+ mFooterUtils.getSettingsButton());
}
@Test
@@ -773,7 +780,7 @@
AlertDialog dialog = dialogCaptor.getValue();
dialog.create();
- assertEquals(mFooter.getSettingsButton(),
+ assertEquals(mFooterUtils.getSettingsButton(),
dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getText());
dialog.dismiss();
@@ -816,8 +823,8 @@
new Intent(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG));
mTestableLooper.processAllMessages();
- assertTrue(mFooter.getDialog().isShowing());
- mFooter.getDialog().dismiss();
+ assertTrue(mFooterUtils.getDialog().isShowing());
+ mFooterUtils.getDialog().dismiss();
}
private CharSequence addLink(CharSequence description) {
@@ -825,7 +832,7 @@
message.append(description);
message.append(mContext.getString(R.string.monitoring_description_vpn_settings_separator));
message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
- mFooter.new VpnSpan(), 0);
+ mFooterUtils.new VpnSpan(), 0);
return message;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index e4f47fd..39f27d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -23,6 +23,7 @@
import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
+import com.android.systemui.media.MediaCarouselController
import com.android.systemui.media.MediaHost
import com.android.systemui.media.MediaHostState
import com.android.systemui.plugins.qs.QSTile
@@ -59,6 +60,7 @@
@Mock private lateinit var tileLayout: TileLayout
@Mock private lateinit var tileView: QSTileView
@Captor private lateinit var captor: ArgumentCaptor<QSPanel.OnConfigurationChangedListener>
+ @Mock private lateinit var mediaCarouselController: MediaCarouselController
private val uiEventLogger = UiEventLoggerFake()
private val dumpManager = DumpManager()
@@ -88,7 +90,8 @@
metricsLogger,
uiEventLogger,
qsLogger,
- dumpManager)
+ dumpManager,
+ mediaCarouselController)
controller.init()
}
@@ -157,7 +160,8 @@
metricsLogger: MetricsLogger,
uiEventLogger: UiEventLoggerFake,
qsLogger: QSLogger,
- dumpManager: DumpManager
+ dumpManager: DumpManager,
+ mediaCarouselController: MediaCarouselController
) :
QuickQSPanelController(
view,
@@ -169,7 +173,8 @@
metricsLogger,
uiEventLogger,
qsLogger,
- dumpManager) {
+ dumpManager,
+ mediaCarouselController) {
private var rotation = RotationUtils.ROTATION_NONE
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
index cb4f08e..eb907bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
@@ -192,6 +192,14 @@
verify(view).setIsSingleCarrier(false)
}
+ @Test
+ fun testAlarmIconIgnored() {
+ controller.init()
+
+ verify(iconContainer).addIgnoredSlot(
+ mContext.getString(com.android.internal.R.string.status_bar_alarm_clock))
+ }
+
private fun stubViews() {
`when`(view.findViewById<View>(anyInt())).thenReturn(mockView)
`when`(view.findViewById<QSCarrierGroup>(R.id.carrier_group)).thenReturn(qsCarrierGroup)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt
new file mode 100644
index 0000000..3c25807
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.footer.domain.interactor
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.os.UserHandle
+import android.provider.Settings
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.nano.MetricsProto
+import com.android.internal.logging.testing.FakeMetricsLogger
+import com.android.internal.logging.testing.UiEventLoggerFake
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.ActivityLaunchAnimator
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.qs.QSSecurityFooterUtils
+import com.android.systemui.qs.footer.FooterActionsTestUtils
+import com.android.systemui.qs.user.UserSwitchDialogController
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.truth.correspondence.FakeUiEvent
+import com.android.systemui.truth.correspondence.LogMaker
+import com.android.systemui.user.UserSwitcherActivity
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.nullable
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class FooterActionsInteractorTest : SysuiTestCase() {
+ private lateinit var utils: FooterActionsTestUtils
+
+ @Before
+ fun setUp() {
+ utils = FooterActionsTestUtils(context, TestableLooper.get(this))
+ }
+
+ @Test
+ fun showDeviceMonitoringDialog() {
+ val qsSecurityFooterUtils = mock<QSSecurityFooterUtils>()
+ val underTest = utils.footerActionsInteractor(qsSecurityFooterUtils = qsSecurityFooterUtils)
+
+ val quickSettingsContext = mock<Context>()
+ underTest.showDeviceMonitoringDialog(quickSettingsContext)
+ verify(qsSecurityFooterUtils).showDeviceMonitoringDialog(quickSettingsContext, null)
+
+ val view = mock<View>()
+ whenever(view.context).thenReturn(quickSettingsContext)
+ underTest.showDeviceMonitoringDialog(view)
+ verify(qsSecurityFooterUtils).showDeviceMonitoringDialog(quickSettingsContext, null)
+ }
+
+ @Test
+ fun showPowerMenuDialog() {
+ val uiEventLogger = UiEventLoggerFake()
+ val underTest = utils.footerActionsInteractor(uiEventLogger = uiEventLogger)
+
+ val globalActionsDialogLite = mock<GlobalActionsDialogLite>()
+ val view = mock<View>()
+ underTest.showPowerMenuDialog(globalActionsDialogLite, view)
+
+ // Event is logged.
+ val logs = uiEventLogger.logs
+ assertThat(logs)
+ .comparingElementsUsing(FakeUiEvent.EVENT_ID)
+ .containsExactly(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS.id)
+
+ // Dialog is shown.
+ verify(globalActionsDialogLite)
+ .showOrHideDialog(
+ /* keyguardShowing= */ false,
+ /* isDeviceProvisioned= */ true,
+ view,
+ )
+ }
+
+ @Test
+ fun showSettings_userSetUp() {
+ val activityStarter = mock<ActivityStarter>()
+ val deviceProvisionedController = mock<DeviceProvisionedController>()
+ val metricsLogger = FakeMetricsLogger()
+
+ // User is set up.
+ whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(true)
+
+ val underTest =
+ utils.footerActionsInteractor(
+ activityStarter = activityStarter,
+ deviceProvisionedController = deviceProvisionedController,
+ metricsLogger = metricsLogger,
+ )
+
+ underTest.showSettings(mock())
+
+ // Event is logged.
+ assertThat(metricsLogger.logs.toList())
+ .comparingElementsUsing(LogMaker.CATEGORY)
+ .containsExactly(MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH)
+
+ // Activity is started.
+ val intentCaptor = argumentCaptor<Intent>()
+ verify(activityStarter)
+ .startActivity(
+ intentCaptor.capture(),
+ /* dismissShade= */ eq(true),
+ nullable() as? ActivityLaunchAnimator.Controller,
+ )
+ assertThat(intentCaptor.value.action).isEqualTo(Settings.ACTION_SETTINGS)
+ }
+
+ @Test
+ fun showSettings_userNotSetUp() {
+ val activityStarter = mock<ActivityStarter>()
+ val deviceProvisionedController = mock<DeviceProvisionedController>()
+
+ // User is not set up.
+ whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(false)
+
+ val underTest =
+ utils.footerActionsInteractor(
+ activityStarter = activityStarter,
+ deviceProvisionedController = deviceProvisionedController,
+ )
+
+ underTest.showSettings(mock())
+
+ // We only unlock the device.
+ verify(activityStarter).postQSRunnableDismissingKeyguard(any())
+ }
+
+ @Test
+ fun showUserSwitcher_fullScreenDisabled() {
+ val featureFlags = FakeFeatureFlags().apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
+ val userSwitchDialogController = mock<UserSwitchDialogController>()
+ val underTest =
+ utils.footerActionsInteractor(
+ featureFlags = featureFlags,
+ userSwitchDialogController = userSwitchDialogController,
+ )
+
+ val view = mock<View>()
+ underTest.showUserSwitcher(view)
+
+ // Dialog is shown.
+ verify(userSwitchDialogController).showDialog(view)
+ }
+
+ @Test
+ fun showUserSwitcher_fullScreenEnabled() {
+ val featureFlags = FakeFeatureFlags().apply { set(Flags.FULL_SCREEN_USER_SWITCHER, true) }
+ val activityStarter = mock<ActivityStarter>()
+ val underTest =
+ utils.footerActionsInteractor(
+ featureFlags = featureFlags,
+ activityStarter = activityStarter,
+ )
+
+ // The clicked view. The context is necessary because it's used to build the intent, that
+ // we check below.
+ val view = mock<View>()
+ whenever(view.context).thenReturn(context)
+
+ underTest.showUserSwitcher(view)
+
+ // Dialog is shown.
+ val intentCaptor = argumentCaptor<Intent>()
+ verify(activityStarter)
+ .startActivity(
+ intentCaptor.capture(),
+ /* dismissShade= */ eq(true),
+ /* ActivityLaunchAnimator.Controller= */ nullable(),
+ /* showOverLockscreenWhenLocked= */ eq(true),
+ eq(UserHandle.SYSTEM),
+ )
+ assertThat(intentCaptor.value.component)
+ .isEqualTo(
+ ComponentName(
+ context,
+ UserSwitcherActivity::class.java,
+ )
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt
new file mode 100644
index 0000000..e4751d1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.footer.ui.viewmodel
+
+import android.graphics.drawable.Drawable
+import android.os.UserManager
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.settingslib.Utils
+import com.android.settingslib.drawable.UserIconDrawable
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.common.shared.model.ContentDescription
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.qs.FakeFgsManagerController
+import com.android.systemui.qs.QSSecurityFooterUtils
+import com.android.systemui.qs.footer.FooterActionsTestUtils
+import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
+import com.android.systemui.security.data.model.SecurityModel
+import com.android.systemui.settings.FakeUserTracker
+import com.android.systemui.statusbar.policy.FakeSecurityController
+import com.android.systemui.statusbar.policy.FakeUserInfoController
+import com.android.systemui.statusbar.policy.FakeUserInfoController.FakeInfo
+import com.android.systemui.statusbar.policy.MockUserSwitcherControllerWrapper
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.nullable
+import com.android.systemui.util.settings.FakeSettings
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.runBlockingTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class FooterActionsViewModelTest : SysuiTestCase() {
+ private lateinit var utils: FooterActionsTestUtils
+
+ @Before
+ fun setUp() {
+ utils = FooterActionsTestUtils(context, TestableLooper.get(this))
+ }
+
+ @Test
+ fun settingsButton() = runBlockingTest {
+ val underTest = utils.footerActionsViewModel(showPowerButton = false)
+ val settings = underTest.settings
+
+ assertThat(settings.contentDescription)
+ .isEqualTo(ContentDescription.Resource(R.string.accessibility_quick_settings_settings))
+ assertThat(settings.icon).isEqualTo(Icon.Resource(R.drawable.ic_settings))
+ assertThat(settings.background).isEqualTo(R.drawable.qs_footer_action_circle)
+ assertThat(settings.iconTint).isNull()
+ }
+
+ @Test
+ fun powerButton() = runBlockingTest {
+ // Without power button.
+ val underTestWithoutPower = utils.footerActionsViewModel(showPowerButton = false)
+ assertThat(underTestWithoutPower.power).isNull()
+
+ // With power button.
+ val underTestWithPower = utils.footerActionsViewModel(showPowerButton = true)
+ val power = underTestWithPower.power
+ assertThat(power).isNotNull()
+ assertThat(power!!.contentDescription)
+ .isEqualTo(
+ ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu)
+ )
+ assertThat(power.icon).isEqualTo(Icon.Resource(android.R.drawable.ic_lock_power_off))
+ assertThat(power.background).isEqualTo(R.drawable.qs_footer_action_circle_color)
+ assertThat(power.iconTint)
+ .isEqualTo(
+ Utils.getColorAttrDefaultColor(
+ context,
+ com.android.internal.R.attr.textColorOnAccent,
+ ),
+ )
+ }
+
+ @Test
+ fun userSwitcher() = runBlockingTest {
+ val picture: Drawable = mock()
+ val userInfoController = FakeUserInfoController(FakeInfo(picture = picture))
+ val settings = FakeSettings()
+ val userId = 42
+ val userTracker = FakeUserTracker(userId)
+ val userSwitcherControllerWrapper =
+ MockUserSwitcherControllerWrapper(currentUserName = "foo")
+
+ // Mock UserManager.
+ val userManager = mock<UserManager>()
+ var isUserSwitcherEnabled = false
+ var isGuestUser = false
+ whenever(userManager.isUserSwitcherEnabled(any())).thenAnswer { isUserSwitcherEnabled }
+ whenever(userManager.isGuestUser(any())).thenAnswer { isGuestUser }
+
+ val underTest =
+ utils.footerActionsViewModel(
+ showPowerButton = false,
+ footerActionsInteractor =
+ utils.footerActionsInteractor(
+ userSwitcherRepository =
+ utils.userSwitcherRepository(
+ userTracker = userTracker,
+ settings = settings,
+ userManager = userManager,
+ userInfoController = userInfoController,
+ userSwitcherController = userSwitcherControllerWrapper.controller,
+ ),
+ )
+ )
+
+ // Collect the user switcher into currentUserSwitcher.
+ var currentUserSwitcher: FooterActionsButtonViewModel? = null
+ val job = launch { underTest.userSwitcher.collect { currentUserSwitcher = it } }
+ fun currentUserSwitcher(): FooterActionsButtonViewModel? {
+ // Make sure we finish collecting the current user switcher. This is necessary because
+ // combined flows launch multiple coroutines in the current scope so we need to make
+ // sure we process all coroutines triggered by our flow collection before we make
+ // assertions on the current buttons.
+ advanceUntilIdle()
+ return currentUserSwitcher
+ }
+
+ // The user switcher is disabled.
+ assertThat(currentUserSwitcher()).isNull()
+
+ // Make the user manager return that the User Switcher is enabled. A change of the setting
+ // for the current user will be fired to notify us of that change.
+ isUserSwitcherEnabled = true
+
+ // Update the setting for a random user: nothing should change, given that at this point we
+ // weren't notified of the change yet.
+ utils.setUserSwitcherEnabled(settings, true, 3)
+ assertThat(currentUserSwitcher()).isNull()
+
+ // Update the setting for the observed user: now we will be notified and the button should
+ // be there.
+ utils.setUserSwitcherEnabled(settings, true, userId)
+ val userSwitcher = currentUserSwitcher()
+ assertThat(userSwitcher).isNotNull()
+ assertThat(userSwitcher!!.contentDescription)
+ .isEqualTo(ContentDescription.Loaded("Signed in as foo"))
+ assertThat(userSwitcher.icon).isEqualTo(Icon.Loaded(picture))
+ assertThat(userSwitcher.background).isEqualTo(R.drawable.qs_footer_action_circle)
+
+ // Change the current user name.
+ userSwitcherControllerWrapper.currentUserName = "bar"
+ assertThat(currentUserSwitcher()?.contentDescription)
+ .isEqualTo(ContentDescription.Loaded("Signed in as bar"))
+
+ fun iconTint(): Int? = currentUserSwitcher()!!.iconTint
+
+ // We tint the icon if the current user is not the guest.
+ assertThat(iconTint()).isNull()
+
+ // Make the UserManager return that the current user is the guest. A change of the user
+ // info will be fired to notify us of that change.
+ isGuestUser = true
+
+ // At this point, there was no change of the user info yet so we still didn't pick the
+ // UserManager change.
+ assertThat(iconTint()).isNull()
+
+ // Trigger a user info change: there should now be a tint.
+ userInfoController.updateInfo { userAccount = "doe" }
+ assertThat(iconTint())
+ .isEqualTo(
+ Utils.getColorAttrDefaultColor(
+ context,
+ android.R.attr.colorForeground,
+ )
+ )
+
+ // Make sure we don't tint the icon if it is a user image (and not the default image), even
+ // in guest mode.
+ userInfoController.updateInfo { this.picture = mock<UserIconDrawable>() }
+ assertThat(iconTint()).isNull()
+
+ job.cancel()
+ }
+
+ @Test
+ fun security() = runBlockingTest {
+ val securityController = FakeSecurityController()
+ val qsSecurityFooterUtils = mock<QSSecurityFooterUtils>()
+
+ // Mock QSSecurityFooter to map a SecurityModel into a SecurityButtonConfig using the
+ // logic in securityToConfig.
+ var securityToConfig: (SecurityModel) -> SecurityButtonConfig? = { null }
+ whenever(qsSecurityFooterUtils.getButtonConfig(any())).thenAnswer {
+ securityToConfig(it.arguments.first() as SecurityModel)
+ }
+
+ val underTest =
+ utils.footerActionsViewModel(
+ footerActionsInteractor =
+ utils.footerActionsInteractor(
+ qsSecurityFooterUtils = qsSecurityFooterUtils,
+ securityRepository =
+ utils.securityRepository(
+ securityController = securityController,
+ ),
+ ),
+ )
+
+ // Collect the security model into currentSecurity.
+ var currentSecurity: FooterActionsSecurityButtonViewModel? = null
+ val job = launch { underTest.security.collect { currentSecurity = it } }
+ fun currentSecurity(): FooterActionsSecurityButtonViewModel? {
+ advanceUntilIdle()
+ return currentSecurity
+ }
+
+ // By default, we always return a null SecurityButtonConfig.
+ assertThat(currentSecurity()).isNull()
+
+ // Map any SecurityModel into a non-null SecurityButtonConfig.
+ val buttonConfig =
+ SecurityButtonConfig(
+ icon = Icon.Resource(0),
+ text = "foo",
+ isClickable = true,
+ )
+ securityToConfig = { buttonConfig }
+
+ // There was no change of the security info yet, so the mapper was not called yet.
+ assertThat(currentSecurity()).isNull()
+
+ // Trigger a SecurityModel change, which will call the mapper and add a button.
+ securityController.updateState {}
+ var security = currentSecurity()
+ assertThat(security).isNotNull()
+ assertThat(security!!.icon).isEqualTo(buttonConfig.icon)
+ assertThat(security.text).isEqualTo(buttonConfig.text)
+ assertThat(security.onClick).isNotNull()
+
+ // If the config.clickable = false, then onClick should be null.
+ securityToConfig = { buttonConfig.copy(isClickable = false) }
+ securityController.updateState {}
+ security = currentSecurity()
+ assertThat(security).isNotNull()
+ assertThat(security!!.onClick).isNull()
+
+ job.cancel()
+ }
+
+ @Test
+ fun foregroundServices() = runBlockingTest {
+ val securityController = FakeSecurityController()
+ val fgsManagerController =
+ FakeFgsManagerController(
+ isAvailable = true,
+ showFooterDot = false,
+ numRunningPackages = 0,
+ )
+ val qsSecurityFooterUtils = mock<QSSecurityFooterUtils>()
+
+ // Mock QSSecurityFooter to map a SecurityModel into a SecurityButtonConfig using the
+ // logic in securityToConfig.
+ var securityToConfig: (SecurityModel) -> SecurityButtonConfig? = { null }
+ whenever(qsSecurityFooterUtils.getButtonConfig(any())).thenAnswer {
+ securityToConfig(it.arguments.first() as SecurityModel)
+ }
+
+ val underTest =
+ utils.footerActionsViewModel(
+ footerActionsInteractor =
+ utils.footerActionsInteractor(
+ qsSecurityFooterUtils = qsSecurityFooterUtils,
+ securityRepository = utils.securityRepository(securityController),
+ foregroundServicesRepository =
+ utils.foregroundServicesRepository(fgsManagerController),
+ ),
+ )
+
+ // Collect the security model into currentSecurity.
+ var currentForegroundServices: FooterActionsForegroundServicesButtonViewModel? = null
+ val job = launch { underTest.foregroundServices.collect { currentForegroundServices = it } }
+ fun currentForegroundServices(): FooterActionsForegroundServicesButtonViewModel? {
+ advanceUntilIdle()
+ return currentForegroundServices
+ }
+
+ // We don't show the foreground services button if the number of running packages is not
+ // > 1.
+ assertThat(currentForegroundServices()).isNull()
+
+ // We show it at soon as the number of services is at least 1. Given that there is no
+ // security, it should be displayed with text.
+ fgsManagerController.numRunningPackages = 1
+ val foregroundServices = currentForegroundServices()
+ assertThat(foregroundServices).isNotNull()
+ assertThat(foregroundServices!!.foregroundServicesCount).isEqualTo(1)
+ assertThat(foregroundServices.text).isEqualTo("1 app is active")
+ assertThat(foregroundServices.displayText).isTrue()
+ assertThat(foregroundServices.onClick).isNotNull()
+
+ // We handle plurals correctly.
+ fgsManagerController.numRunningPackages = 3
+ assertThat(currentForegroundServices()?.text).isEqualTo("3 apps are active")
+
+ // Showing new changes (the footer dot) is currently disabled.
+ assertThat(foregroundServices.hasNewChanges).isFalse()
+
+ // Enabling it will show the new changes.
+ fgsManagerController.showFooterDot.value = true
+ assertThat(currentForegroundServices()?.hasNewChanges).isTrue()
+
+ // Dismissing the dialog should remove the new changes dot.
+ fgsManagerController.simulateDialogDismiss()
+ assertThat(currentForegroundServices()?.hasNewChanges).isFalse()
+
+ // Showing the security button will make this show as a simple button without text.
+ assertThat(foregroundServices.displayText).isTrue()
+ securityToConfig = {
+ SecurityButtonConfig(
+ icon = Icon.Resource(0),
+ text = "foo",
+ isClickable = true,
+ )
+ }
+ securityController.updateState {}
+ assertThat(currentForegroundServices()?.displayText).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun observeDeviceMonitoringDialogRequests() = runBlockingTest {
+ val qsSecurityFooterUtils = mock<QSSecurityFooterUtils>()
+ val broadcastDispatcher = mock<BroadcastDispatcher>()
+
+ // Return a fake broadcastFlow that emits 3 fake events when collected.
+ val broadcastFlow = flowOf(Unit, Unit, Unit)
+ whenever(
+ broadcastDispatcher.broadcastFlow(
+ any(),
+ nullable(),
+ anyInt(),
+ nullable(),
+ )
+ )
+ .thenAnswer { broadcastFlow }
+
+ // Increment nDialogRequests whenever a request to show the dialog is made by the
+ // FooterActionsInteractor.
+ var nDialogRequests = 0
+ whenever(qsSecurityFooterUtils.showDeviceMonitoringDialog(any(), nullable())).then {
+ nDialogRequests++
+ }
+
+ val underTest =
+ utils.footerActionsViewModel(
+ footerActionsInteractor =
+ utils.footerActionsInteractor(
+ qsSecurityFooterUtils = qsSecurityFooterUtils,
+ broadcastDispatcher = broadcastDispatcher,
+ ),
+ )
+
+ val job = launch {
+ underTest.observeDeviceMonitoringDialogRequests(quickSettingsContext = mock())
+ }
+
+ advanceUntilIdle()
+ assertThat(nDialogRequests).isEqualTo(3)
+
+ job.cancel()
+ }
+
+ @Test
+ fun isVisible() {
+ val underTest = utils.footerActionsViewModel()
+ assertThat(underTest.isVisible.value).isTrue()
+
+ underTest.onVisibilityChangeRequested(visible = false)
+ assertThat(underTest.isVisible.value).isFalse()
+
+ underTest.onVisibilityChangeRequested(visible = true)
+ assertThat(underTest.isVisible.value).isTrue()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
new file mode 100644
index 0000000..d91baa5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+import android.os.Handler;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.tiles.dialog.InternetDialogFactory;
+import com.android.systemui.statusbar.connectivity.AccessPointController;
+import com.android.systemui.statusbar.connectivity.NetworkController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@SmallTest
+public class InternetTileTest extends SysuiTestCase {
+
+ @Mock
+ private QSTileHost mHost;
+ @Mock
+ private NetworkController mNetworkController;
+ @Mock
+ private AccessPointController mAccessPointController;
+ @Mock
+ private InternetDialogFactory mInternetDialogFactory;
+
+ private TestableLooper mTestableLooper;
+ private InternetTile mTile;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mTestableLooper = TestableLooper.get(this);
+ when(mHost.getContext()).thenReturn(mContext);
+ when(mHost.getUserContext()).thenReturn(mContext);
+
+ mTile = new InternetTile(
+ mHost,
+ mTestableLooper.getLooper(),
+ new Handler(mTestableLooper.getLooper()),
+ new FalsingManagerFake(),
+ mock(MetricsLogger.class),
+ mock(StatusBarStateController.class),
+ mock(ActivityStarter.class),
+ mock(QSLogger.class),
+ mNetworkController,
+ mAccessPointController,
+ mInternetDialogFactory
+ );
+
+ mTile.initialize();
+ mTestableLooper.processAllMessages();
+ }
+
+ @Test
+ public void setConnectivityStatus_defaultNetworkNotExists_updateTile() {
+ mTile.mSignalCallback.setConnectivityStatus(
+ /* noDefaultNetwork= */ true,
+ /* noValidatedNetwork= */ true,
+ /* noNetworksAvailable= */ true);
+ mTestableLooper.processAllMessages();
+ assertThat(String.valueOf(mTile.getState().secondaryLabel))
+ .isEqualTo(mContext.getString(R.string.quick_settings_networks_unavailable));
+ assertThat(mTile.getLastTileState()).isEqualTo(1);
+ }
+
+ @Test
+ public void setConnectivityStatus_defaultNetworkExists_notUpdateTile() {
+ mTile.mSignalCallback.setConnectivityStatus(
+ /* noDefaultNetwork= */ false,
+ /* noValidatedNetwork= */ true,
+ /* noNetworksAvailable= */ true);
+ mTestableLooper.processAllMessages();
+ assertThat(String.valueOf(mTile.getState().secondaryLabel))
+ .isNotEqualTo(mContext.getString(R.string.quick_settings_networks_unavailable));
+ assertThat(String.valueOf(mTile.getState().secondaryLabel))
+ .isNotEqualTo(mContext.getString(R.string.quick_settings_networks_available));
+ assertThat(mTile.getLastTileState()).isEqualTo(-1);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
index 9b0142d..5db3b9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
@@ -31,6 +31,7 @@
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.qs.QSUserSwitcherEvent
import com.android.systemui.statusbar.policy.UserSwitcherController
+import com.android.systemui.user.data.source.UserRecord
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
@@ -39,8 +40,8 @@
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@@ -140,13 +141,14 @@
}
private fun createUserRecord(current: Boolean, guest: Boolean) =
- UserSwitcherController.UserRecord(
- mUserInfo,
- mPicture,
- guest,
- current,
- false /* isAddUser */,
- false /* isRestricted */,
- true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ UserRecord(
+ mUserInfo,
+ mPicture,
+ guest,
+ current,
+ false /* isAddUser */,
+ false /* isRestricted */,
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */
+ )
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
index 48fbd35..073c23c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
@@ -23,6 +23,7 @@
import android.graphics.Rect
import android.hardware.HardwareBuffer
import android.os.Bundle
+import android.os.UserHandle
import android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD
import android.view.WindowManager.ScreenshotSource.SCREENSHOT_OTHER
import android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN
@@ -97,7 +98,7 @@
policy.setManagedProfile(USER_ID, false)
policy.setDisplayContentInfo(
policy.getDefaultDisplayId(),
- DisplayContentInfo(component, bounds, USER_ID, TASK_ID))
+ DisplayContentInfo(component, bounds, UserHandle.of(USER_ID), TASK_ID))
val request = ScreenshotRequest(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD)
val processor = RequestProcessor(imageCapture, policy, flags, scope)
@@ -120,7 +121,7 @@
// Indicate that the primary content belongs to a manged profile
policy.setManagedProfile(USER_ID, true)
policy.setDisplayContentInfo(policy.getDefaultDisplayId(),
- DisplayContentInfo(component, bounds, USER_ID, TASK_ID))
+ DisplayContentInfo(component, bounds, UserHandle.of(USER_ID), TASK_ID))
val request = ScreenshotRequest(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD)
val processor = RequestProcessor(imageCapture, policy, flags, scope)
@@ -160,7 +161,7 @@
policy.setManagedProfile(USER_ID, false)
policy.setDisplayContentInfo(policy.getDefaultDisplayId(),
- DisplayContentInfo(component, bounds, USER_ID, TASK_ID))
+ DisplayContentInfo(component, bounds, UserHandle.of(USER_ID), TASK_ID))
val processedRequest = processor.process(request)
@@ -183,7 +184,7 @@
// Indicate that the primary content belongs to a manged profile
policy.setManagedProfile(USER_ID, true)
policy.setDisplayContentInfo(policy.getDefaultDisplayId(),
- DisplayContentInfo(component, bounds, USER_ID, TASK_ID))
+ DisplayContentInfo(component, bounds, UserHandle.of(USER_ID), TASK_ID))
val processedRequest = processor.process(request)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
new file mode 100644
index 0000000..17396b1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot
+
+import android.app.ActivityTaskManager.RootTaskInfo
+import android.app.IActivityTaskManager
+import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME
+import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
+import android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED
+import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
+import android.app.WindowConfiguration.WINDOWING_MODE_PINNED
+import android.content.ComponentName
+import android.content.Context
+import android.graphics.Rect
+import android.os.UserHandle
+import android.os.UserManager
+import android.testing.AndroidTestingRunner
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.screenshot.ScreenshotPolicy.DisplayContentInfo
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+
+// The following values are chosen to be distinct from commonly seen real values
+private const val DISPLAY_ID = 100
+private const val PRIMARY_USER = 2000
+private const val MANAGED_PROFILE_USER = 3000
+
+@RunWith(AndroidTestingRunner::class)
+class ScreenshotPolicyImplTest : SysuiTestCase() {
+
+ @Test
+ fun testToDisplayContentInfo() {
+ assertThat(fullScreenWorkProfileTask.toDisplayContentInfo())
+ .isEqualTo(
+ DisplayContentInfo(
+ ComponentName(
+ "com.google.android.apps.nbu.files",
+ "com.google.android.apps.nbu.files.home.HomeActivity"
+ ),
+ Rect(0, 0, 1080, 2400),
+ UserHandle.of(MANAGED_PROFILE_USER),
+ 65))
+ }
+
+ @Test
+ fun findPrimaryContent_ignoresPipTask() = runBlocking {
+ val policy = fakeTasksPolicyImpl(
+ mContext,
+ shadeExpanded = false,
+ tasks = listOf(
+ pipTask,
+ fullScreenWorkProfileTask,
+ launcherTask,
+ emptyTask)
+ )
+
+ val info = policy.findPrimaryContent(DISPLAY_ID)
+ assertThat(info).isEqualTo(fullScreenWorkProfileTask.toDisplayContentInfo())
+ }
+
+ @Test
+ fun findPrimaryContent_shadeExpanded_ignoresTopTask() = runBlocking {
+ val policy = fakeTasksPolicyImpl(
+ mContext,
+ shadeExpanded = true,
+ tasks = listOf(
+ fullScreenWorkProfileTask,
+ launcherTask,
+ emptyTask)
+ )
+
+ val info = policy.findPrimaryContent(DISPLAY_ID)
+ assertThat(info).isEqualTo(policy.systemUiContent)
+ }
+
+ @Test
+ fun findPrimaryContent_emptyTaskList() = runBlocking {
+ val policy = fakeTasksPolicyImpl(
+ mContext,
+ shadeExpanded = false,
+ tasks = listOf()
+ )
+
+ val info = policy.findPrimaryContent(DISPLAY_ID)
+ assertThat(info).isEqualTo(policy.systemUiContent)
+ }
+
+ @Test
+ fun findPrimaryContent_workProfileNotOnTop() = runBlocking {
+ val policy = fakeTasksPolicyImpl(
+ mContext,
+ shadeExpanded = false,
+ tasks = listOf(
+ launcherTask,
+ fullScreenWorkProfileTask,
+ emptyTask)
+ )
+
+ val info = policy.findPrimaryContent(DISPLAY_ID)
+ assertThat(info).isEqualTo(launcherTask.toDisplayContentInfo())
+ }
+
+ private fun fakeTasksPolicyImpl(
+ context: Context,
+ shadeExpanded: Boolean,
+ tasks: List<RootTaskInfo>
+ ): ScreenshotPolicyImpl {
+ val userManager = mock<UserManager>()
+ val atmService = mock<IActivityTaskManager>()
+ val dispatcher = Dispatchers.Unconfined
+
+ return object : ScreenshotPolicyImpl(context, userManager, atmService, dispatcher) {
+ override suspend fun isManagedProfile(userId: Int) = (userId == MANAGED_PROFILE_USER)
+ override suspend fun getAllRootTaskInfosOnDisplay(displayId: Int) = tasks
+ override suspend fun isNotificationShadeExpanded() = shadeExpanded
+ }
+ }
+
+ private val pipTask = RootTaskInfo().apply {
+ configuration.windowConfiguration.apply {
+ windowingMode = WINDOWING_MODE_PINNED
+ bounds = Rect(628, 1885, 1038, 2295)
+ activityType = ACTIVITY_TYPE_STANDARD
+ }
+ displayId = DISPLAY_ID
+ userId = PRIMARY_USER
+ taskId = 66
+ visible = true
+ isVisible = true
+ isRunning = true
+ numActivities = 1
+ topActivity = ComponentName(
+ "com.google.android.youtube",
+ "com.google.android.apps.youtube.app.watchwhile.WatchWhileActivity"
+ )
+ childTaskIds = intArrayOf(66)
+ childTaskNames = arrayOf("com.google.android.youtube/" +
+ "com.google.android.youtube.app.honeycomb.Shell\$HomeActivity")
+ childTaskUserIds = intArrayOf(0)
+ childTaskBounds = arrayOf(Rect(628, 1885, 1038, 2295))
+ }
+
+ private val fullScreenWorkProfileTask = RootTaskInfo().apply {
+ configuration.windowConfiguration.apply {
+ windowingMode = WINDOWING_MODE_FULLSCREEN
+ bounds = Rect(0, 0, 1080, 2400)
+ activityType = ACTIVITY_TYPE_STANDARD
+ }
+ displayId = DISPLAY_ID
+ userId = MANAGED_PROFILE_USER
+ taskId = 65
+ visible = true
+ isVisible = true
+ isRunning = true
+ numActivities = 1
+ topActivity = ComponentName(
+ "com.google.android.apps.nbu.files",
+ "com.google.android.apps.nbu.files.home.HomeActivity"
+ )
+ childTaskIds = intArrayOf(65)
+ childTaskNames = arrayOf("com.google.android.apps.nbu.files/" +
+ "com.google.android.apps.nbu.files.home.HomeActivity")
+ childTaskUserIds = intArrayOf(MANAGED_PROFILE_USER)
+ childTaskBounds = arrayOf(Rect(0, 0, 1080, 2400))
+ }
+
+ private val launcherTask = RootTaskInfo().apply {
+ configuration.windowConfiguration.apply {
+ windowingMode = WINDOWING_MODE_FULLSCREEN
+ bounds = Rect(0, 0, 1080, 2400)
+ activityType = ACTIVITY_TYPE_HOME
+ }
+ displayId = DISPLAY_ID
+ taskId = 1
+ userId = PRIMARY_USER
+ visible = true
+ isVisible = true
+ isRunning = true
+ numActivities = 1
+ topActivity = ComponentName(
+ "com.google.android.apps.nexuslauncher",
+ "com.google.android.apps.nexuslauncher.NexusLauncherActivity",
+ )
+ childTaskIds = intArrayOf(1)
+ childTaskNames = arrayOf("com.google.android.apps.nexuslauncher/" +
+ "com.google.android.apps.nexuslauncher.NexusLauncherActivity")
+ childTaskUserIds = intArrayOf(0)
+ childTaskBounds = arrayOf(Rect(0, 0, 1080, 2400))
+ }
+
+ private val emptyTask = RootTaskInfo().apply {
+ configuration.windowConfiguration.apply {
+ windowingMode = WINDOWING_MODE_FULLSCREEN
+ bounds = Rect(0, 0, 1080, 2400)
+ activityType = ACTIVITY_TYPE_UNDEFINED
+ }
+ displayId = DISPLAY_ID
+ taskId = 2
+ userId = PRIMARY_USER
+ visible = false
+ isVisible = false
+ isRunning = false
+ numActivities = 0
+ childTaskIds = intArrayOf(3, 4)
+ childTaskNames = arrayOf("", "")
+ childTaskUserIds = intArrayOf(0, 0)
+ childTaskBounds = arrayOf(Rect(0, 0, 1080, 2400), Rect(0, 2400, 1080, 4800))
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
new file mode 100644
index 0000000..6ce9cff
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.screenshot
+
+import android.app.Application
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyResources.Strings.SystemUi.SCREENSHOT_BLOCKED_BY_ADMIN
+import android.app.admin.DevicePolicyResourcesManager
+import android.content.ComponentName
+import android.graphics.Bitmap
+import android.graphics.Bitmap.Config.HARDWARE
+import android.graphics.ColorSpace
+import android.graphics.Insets
+import android.graphics.Rect
+import android.hardware.HardwareBuffer
+import android.os.UserHandle
+import android.os.UserManager
+import android.testing.AndroidTestingRunner
+import android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD
+import android.view.WindowManager.ScreenshotSource.SCREENSHOT_OVERVIEW
+import android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN
+import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
+import android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION
+import com.android.internal.logging.testing.UiEventLoggerFake
+import com.android.internal.util.ScreenshotHelper
+import com.android.internal.util.ScreenshotHelper.ScreenshotRequest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags.SCREENSHOT_REQUEST_PROCESSOR
+import com.android.systemui.flags.Flags.SCREENSHOT_WORK_PROFILE_POLICY
+import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_REQUESTED_KEY_CHORD
+import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_REQUESTED_OVERVIEW
+import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argThat
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import java.util.function.Consumer
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.isNull
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.Mockito.`when` as whenever
+
+private const val USER_ID = 1
+private const val TASK_ID = 1
+
+@RunWith(AndroidTestingRunner::class)
+class TakeScreenshotServiceTest : SysuiTestCase() {
+
+ private val application = mock<Application>()
+ private val controller = mock<ScreenshotController>()
+ private val userManager = mock<UserManager>()
+ private val requestProcessor = mock<RequestProcessor>()
+ private val devicePolicyManager = mock<DevicePolicyManager>()
+ private val devicePolicyResourcesManager = mock<DevicePolicyResourcesManager>()
+ private val notificationsController = mock<ScreenshotNotificationsController>()
+ private val callback = mock<RequestCallback>()
+
+ private val eventLogger = UiEventLoggerFake()
+ private val flags = FakeFeatureFlags()
+ private val topComponent = ComponentName(mContext, TakeScreenshotServiceTest::class.java)
+
+ private val service = TakeScreenshotService(
+ controller, userManager, devicePolicyManager, eventLogger,
+ notificationsController, mContext, Runnable::run, flags, requestProcessor)
+
+ @Before
+ fun setUp() {
+ whenever(devicePolicyManager.resources).thenReturn(devicePolicyResourcesManager)
+ whenever(devicePolicyManager.getScreenCaptureDisabled(
+ /* admin component (null: any admin) */ isNull(), eq(UserHandle.USER_ALL)))
+ .thenReturn(false)
+ whenever(userManager.isUserUnlocked).thenReturn(true)
+
+ // Stub request processor as a synchronous no-op for tests with the flag enabled
+ doAnswer {
+ val request: ScreenshotRequest = it.getArgument(0) as ScreenshotRequest
+ val consumer: Consumer<ScreenshotRequest> = it.getArgument(1)
+ consumer.accept(request)
+ }.`when`(requestProcessor).processAsync(/* request= */ any(), /* callback= */ any())
+
+ // Flipped in selected test cases
+ flags.set(SCREENSHOT_REQUEST_PROCESSOR, false)
+ flags.set(SCREENSHOT_WORK_PROFILE_POLICY, false)
+
+ service.attach(
+ mContext,
+ /* thread = */ null,
+ /* className = */ null,
+ /* token = */ null,
+ application,
+ /* activityManager = */ null)
+ }
+
+ @Test
+ fun testServiceLifecycle() {
+ service.onCreate()
+ service.onBind(null /* unused: Intent */)
+
+ service.onUnbind(null /* unused: Intent */)
+ verify(controller, times(1)).removeWindow()
+
+ service.onDestroy()
+ verify(controller, times(1)).onDestroy()
+ }
+
+ @Test
+ fun takeScreenshotFullscreen() {
+ val request = ScreenshotRequest(
+ TAKE_SCREENSHOT_FULLSCREEN,
+ SCREENSHOT_KEY_CHORD,
+ topComponent)
+
+ service.handleRequest(request, { /* onSaved */ }, callback)
+
+ verify(controller, times(1)).takeScreenshotFullscreen(
+ eq(topComponent),
+ /* onSavedListener = */ any(),
+ /* requestCallback = */ any())
+
+ assertEquals("Expected one UiEvent", eventLogger.numLogs(), 1)
+ val logEvent = eventLogger.get(0)
+
+ assertEquals("Expected SCREENSHOT_REQUESTED UiEvent",
+ logEvent.eventId, SCREENSHOT_REQUESTED_KEY_CHORD.id)
+ assertEquals("Expected supplied package name",
+ topComponent.packageName, eventLogger.get(0).packageName)
+ }
+
+ @Test
+ fun takeScreenshot_requestProcessorEnabled() {
+ flags.set(SCREENSHOT_REQUEST_PROCESSOR, true)
+
+ val request = ScreenshotRequest(
+ TAKE_SCREENSHOT_FULLSCREEN,
+ SCREENSHOT_KEY_CHORD,
+ topComponent)
+
+ service.handleRequest(request, { /* onSaved */ }, callback)
+
+ verify(controller, times(1)).takeScreenshotFullscreen(
+ eq(topComponent),
+ /* onSavedListener = */ any(),
+ /* requestCallback = */ any())
+
+ assertEquals("Expected one UiEvent", eventLogger.numLogs(), 1)
+ val logEvent = eventLogger.get(0)
+
+ assertEquals("Expected SCREENSHOT_REQUESTED UiEvent",
+ logEvent.eventId, SCREENSHOT_REQUESTED_KEY_CHORD.id)
+ assertEquals("Expected supplied package name",
+ topComponent.packageName, eventLogger.get(0).packageName)
+ }
+
+ @Test
+ fun takeScreenshotPartial() {
+ val request = ScreenshotRequest(
+ TAKE_SCREENSHOT_SELECTED_REGION,
+ SCREENSHOT_KEY_CHORD,
+ /* topComponent = */ null)
+
+ service.handleRequest(request, { /* onSaved */ }, callback)
+
+ verify(controller, times(1)).takeScreenshotPartial(
+ /* topComponent = */ isNull(),
+ /* onSavedListener = */ any(),
+ /* requestCallback = */ any())
+
+ assertEquals("Expected one UiEvent", eventLogger.numLogs(), 1)
+ val logEvent = eventLogger.get(0)
+
+ assertEquals("Expected SCREENSHOT_REQUESTED UiEvent",
+ logEvent.eventId, SCREENSHOT_REQUESTED_KEY_CHORD.id)
+ assertEquals("Expected empty package name in UiEvent", "", eventLogger.get(0).packageName)
+ }
+
+ @Test
+ fun takeScreenshotProvidedImage() {
+ val bounds = Rect(50, 50, 150, 150)
+ val bitmap = makeHardwareBitmap(100, 100)
+ val bitmapBundle = ScreenshotHelper.HardwareBitmapBundler.hardwareBitmapToBundle(bitmap)
+
+ val request = ScreenshotRequest(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OVERVIEW,
+ bitmapBundle, bounds, Insets.NONE, TASK_ID, USER_ID, topComponent)
+
+ service.handleRequest(request, { /* onSaved */ }, callback)
+
+ verify(controller, times(1)).handleImageAsScreenshot(
+ argThat { b -> b.equalsHardwareBitmap(bitmap) },
+ eq(bounds),
+ eq(Insets.NONE), eq(TASK_ID), eq(USER_ID), eq(topComponent),
+ /* onSavedListener = */ any(), /* requestCallback = */ any())
+
+ assertEquals("Expected one UiEvent", eventLogger.numLogs(), 1)
+ val logEvent = eventLogger.get(0)
+
+ assertEquals("Expected SCREENSHOT_REQUESTED_* UiEvent",
+ logEvent.eventId, SCREENSHOT_REQUESTED_OVERVIEW.id)
+ assertEquals("Expected supplied package name",
+ topComponent.packageName, eventLogger.get(0).packageName)
+ }
+
+ @Test
+ fun takeScreenshotFullscreen_userLocked() {
+ whenever(userManager.isUserUnlocked).thenReturn(false)
+
+ val request = ScreenshotRequest(
+ TAKE_SCREENSHOT_FULLSCREEN,
+ SCREENSHOT_KEY_CHORD,
+ topComponent)
+
+ service.handleRequest(request, { /* onSaved */ }, callback)
+
+ verify(notificationsController, times(1)).notifyScreenshotError(anyInt())
+ verify(callback, times(1)).reportError()
+ verifyZeroInteractions(controller)
+ }
+
+ @Test
+ fun takeScreenshotFullscreen_screenCaptureDisabled_allUsers() {
+ whenever(devicePolicyManager.getScreenCaptureDisabled(
+ isNull(), eq(UserHandle.USER_ALL))
+ ).thenReturn(true)
+
+ whenever(devicePolicyResourcesManager.getString(
+ eq(SCREENSHOT_BLOCKED_BY_ADMIN),
+ /* Supplier<String> */ any(),
+ )).thenReturn("SCREENSHOT_BLOCKED_BY_ADMIN")
+
+ val request = ScreenshotRequest(
+ TAKE_SCREENSHOT_FULLSCREEN,
+ SCREENSHOT_KEY_CHORD,
+ topComponent)
+
+ service.handleRequest(request, { /* onSaved */ }, callback)
+
+ // error shown: Toast.makeText(...).show(), untestable
+ verify(callback, times(1)).reportError()
+ verifyZeroInteractions(controller)
+ }
+}
+
+private fun Bitmap.equalsHardwareBitmap(other: Bitmap): Boolean {
+ return config == HARDWARE &&
+ other.config == HARDWARE &&
+ hardwareBuffer == other.hardwareBuffer &&
+ colorSpace == other.colorSpace
+}
+
+/** A hardware Bitmap is mandated by use of ScreenshotHelper.HardwareBitmapBundler */
+private fun makeHardwareBitmap(width: Int, height: Int): Bitmap {
+ val buffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888, 1,
+ HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE)
+ return Bitmap.wrapHardwareBuffer(buffer, ColorSpace.get(ColorSpace.Named.SRGB))!!
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
index 20c6d9a..e85ffb6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
@@ -607,6 +607,13 @@
verify(mockConstraintsChanges.largeScreenConstraintsChanges)!!.invoke(any())
}
+ @Test
+ fun alarmIconNotIgnored() {
+ verify(statusIcons, never()).addIgnoredSlot(
+ context.getString(com.android.internal.R.string.status_bar_alarm_clock)
+ )
+ }
+
private fun createWindowInsets(
topCutout: Rect? = Rect()
): WindowInsets {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
index eeb61bc..8511443 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
@@ -191,4 +191,11 @@
verify(date).setTextAppearance(R.style.TextAppearance_QS_Status)
verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status_Carriers)
}
+
+ @Test
+ fun alarmIconIgnored() {
+ verify(statusIcons).addIgnoredSlot(
+ context.getString(com.android.internal.R.string.status_bar_alarm_clock)
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 7d28871..f267013 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -124,7 +124,6 @@
import com.android.systemui.statusbar.events.PrivacyDotViewController;
import com.android.systemui.statusbar.notification.ConversationNotificationManager;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
@@ -229,8 +228,6 @@
@Mock
private DynamicPrivacyController mDynamicPrivacyController;
@Mock
- private NotificationEntryManager mNotificationEntryManager;
- @Mock
private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
@Mock
private KeyguardStateController mKeyguardStateController;
@@ -259,7 +256,7 @@
private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
@Mock
private KeyguardClockSwitch mKeyguardClockSwitch;
- private PanelViewController.TouchHandler mTouchHandler;
+ private NotificationPanelViewController.TouchHandler mTouchHandler;
private ConfigurationController mConfigurationController;
@Mock
private MediaHierarchyManager mMediaHiearchyManager;
@@ -454,11 +451,10 @@
doAnswer((Answer<Void>) invocation -> {
mTouchHandler = invocation.getArgument(0);
return null;
- }).when(mView).setOnTouchListener(any(PanelViewController.TouchHandler.class));
+ }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class));
NotificationWakeUpCoordinator coordinator =
new NotificationWakeUpCoordinator(
- mDumpManager,
mock(HeadsUpManagerPhone.class),
new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
mInteractionJankMonitor),
@@ -518,7 +514,6 @@
mFeatureFlags,
coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
mFalsingManager, new FalsingCollectorFake(),
- mNotificationEntryManager,
mKeyguardStateController,
mStatusBarStateController,
mStatusBarWindowStateController,
@@ -1407,7 +1402,7 @@
when(mQsFrame.getWidth()).thenReturn(1000);
when(mQsHeader.getTop()).thenReturn(0);
when(mQsHeader.getBottom()).thenReturn(1000);
- PanelViewController.TouchHandler touchHandler =
+ NotificationPanelViewController.TouchHandler touchHandler =
mNotificationPanelViewController.createTouchHandler();
mNotificationPanelViewController.setExpandedFraction(1f);
@@ -1427,7 +1422,7 @@
when(mQsFrame.getWidth()).thenReturn(1000);
when(mQsHeader.getTop()).thenReturn(0);
when(mQsHeader.getBottom()).thenReturn(1000);
- PanelViewController.TouchHandler touchHandler =
+ NotificationPanelViewController.TouchHandler touchHandler =
mNotificationPanelViewController.createTouchHandler();
mNotificationPanelViewController.setExpandedFraction(1f);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index 471918c..6d059b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -26,19 +26,18 @@
import com.android.systemui.dock.DockManager
import com.android.systemui.keyguard.KeyguardUnlockAnimationController
import com.android.systemui.lowlightclock.LowLightClockController
+import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
import com.android.systemui.statusbar.LockscreenShadeTransitionController
import com.android.systemui.statusbar.NotificationShadeDepthController
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.stack.AmbientState
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.PhoneStatusBarViewController
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager
import com.android.systemui.statusbar.window.StatusBarWindowStateController
-import com.android.systemui.tuner.TunerService
import com.google.common.truth.Truth.assertThat
import java.util.Optional
import org.junit.Before
@@ -60,8 +59,6 @@
@Mock
private lateinit var view: NotificationShadeWindowView
@Mock
- private lateinit var tunserService: TunerService
- @Mock
private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
@Mock
private lateinit var centralSurfaces: CentralSurfaces
@@ -91,6 +88,8 @@
private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
@Mock
private lateinit var lowLightClockController: LowLightClockController
+ @Mock
+ private lateinit var pulsingGestureListener: PulsingGestureListener
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
private lateinit var interactionEventHandler: InteractionEventHandler
@@ -105,7 +104,6 @@
underTest = NotificationShadeWindowViewController(
lockscreenShadeTransitionController,
FalsingCollectorFake(),
- tunserService,
sysuiStatusBarStateController,
dockManager,
notificationShadeDepthController,
@@ -120,7 +118,8 @@
centralSurfaces,
notificationShadeWindowController,
keyguardUnlockAnimationController,
- ambientState
+ ambientState,
+ pulsingGestureListener
)
underTest.setupExpandedStatusBar()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
index fa16fef..89a2518 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
@@ -89,6 +89,7 @@
@Mock private LowLightClockController mLowLightClockController;
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
@Mock private AmbientState mAmbientState;
+ @Mock private PulsingGestureListener mPulsingGestureListener;
@Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
mInteractionEventHandlerCaptor;
@@ -110,7 +111,6 @@
mController = new NotificationShadeWindowViewController(
mLockscreenShadeTransitionController,
new FalsingCollectorFake(),
- mTunerService,
mStatusBarStateController,
mDockManager,
mNotificationShadeDepthController,
@@ -125,7 +125,9 @@
mCentralSurfaces,
mNotificationShadeWindowController,
mKeyguardUnlockAnimationController,
- mAmbientState);
+ mAmbientState,
+ mPulsingGestureListener
+ );
mController.setupExpandedStatusBar();
mController.setDragDownHelper(mDragDownHelper);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
new file mode 100644
index 0000000..d2970a6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade
+
+import android.hardware.display.AmbientDisplayConfiguration
+import android.provider.Settings.Secure.DOZE_DOUBLE_TAP_GESTURE
+import android.provider.Settings.Secure.DOZE_TAP_SCREEN_GESTURE
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.view.MotionEvent
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dock.DockManager
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.statusbar.phone.CentralSurfaces
+import com.android.systemui.tuner.TunerService
+import com.android.systemui.tuner.TunerService.Tunable
+import com.android.systemui.util.mockito.eq
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyLong
+import org.mockito.ArgumentMatchers.anyObject
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper(setAsMainLooper = true)
+@SmallTest
+class PulsingGestureListenerTest : SysuiTestCase() {
+ @Mock
+ private lateinit var view: NotificationShadeWindowView
+ @Mock
+ private lateinit var centralSurfaces: CentralSurfaces
+ @Mock
+ private lateinit var dockManager: DockManager
+ @Mock
+ private lateinit var falsingManager: FalsingManager
+ @Mock
+ private lateinit var ambientDisplayConfiguration: AmbientDisplayConfiguration
+ @Mock
+ private lateinit var tunerService: TunerService
+ @Mock
+ private lateinit var dumpManager: DumpManager
+
+ private lateinit var tunableCaptor: ArgumentCaptor<Tunable>
+ private lateinit var underTest: PulsingGestureListener
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ underTest = PulsingGestureListener(
+ view,
+ falsingManager,
+ dockManager,
+ centralSurfaces,
+ ambientDisplayConfiguration,
+ tunerService,
+ dumpManager
+ )
+ whenever(dockManager.isDocked).thenReturn(false)
+ }
+
+ @Test
+ fun testGestureDetector_singleTapEnabled() {
+ // GIVEN tap is enabled, prox not covered
+ whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true)
+ updateSettings()
+ whenever(falsingManager.isProximityNear).thenReturn(false)
+
+ // GIVEN the falsing manager does NOT think the tap is a false tap
+ whenever(falsingManager.isFalseTap(anyInt())).thenReturn(false)
+
+ // WHEN there's a tap
+ underTest.onSingleTapConfirmed(downEv)
+
+ // THEN wake up device if dozing
+ verify(centralSurfaces).wakeUpIfDozing(anyLong(), anyObject(), anyString())
+ }
+
+ @Test
+ fun testGestureDetector_doubleTapEnabled() {
+ // GIVEN double tap is enabled, prox not covered
+ whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true)
+ updateSettings()
+ whenever(falsingManager.isProximityNear).thenReturn(false)
+
+ // GIVEN the falsing manager does NOT think the tap is a false tap
+ whenever(falsingManager.isFalseDoubleTap).thenReturn(false)
+
+ // WHEN there's a double tap
+ underTest.onDoubleTap(downEv)
+
+ // THEN wake up device if dozing
+ verify(centralSurfaces).wakeUpIfDozing(anyLong(), anyObject(), anyString())
+ }
+
+ @Test
+ fun testGestureDetector_singleTapEnabled_falsing() {
+ // GIVEN tap is enabled, prox not covered
+ whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true)
+ updateSettings()
+ whenever(falsingManager.isProximityNear).thenReturn(false)
+
+ // GIVEN the falsing manager thinks the tap is a false tap
+ whenever(falsingManager.isFalseTap(anyInt())).thenReturn(true)
+
+ // WHEN there's a tap
+ underTest.onSingleTapConfirmed(downEv)
+
+ // THEN the device doesn't wake up
+ verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString())
+ }
+
+ @Test
+ fun testGestureDetector_doubleTapEnabled_falsing() {
+ // GIVEN double tap is enabled, prox not covered
+ whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true)
+ updateSettings()
+ whenever(falsingManager.isProximityNear).thenReturn(false)
+
+ // GIVEN the falsing manager thinks the tap is a false tap
+ whenever(falsingManager.isFalseDoubleTap).thenReturn(true)
+
+ // WHEN there's a tap
+ underTest.onDoubleTap(downEv)
+
+ // THEN the device doesn't wake up
+ verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString())
+ }
+
+ @Test
+ fun testGestureDetector_singleTapEnabled_proxCovered() {
+ // GIVEN tap is enabled, not a false tap based on classifiers
+ whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true)
+ updateSettings()
+ whenever(falsingManager.isFalseTap(anyInt())).thenReturn(false)
+
+ // GIVEN prox is covered
+ whenever(falsingManager.isProximityNear()).thenReturn(true)
+
+ // WHEN there's a tap
+ underTest.onSingleTapConfirmed(downEv)
+
+ // THEN the device doesn't wake up
+ verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString())
+ }
+
+ @Test
+ fun testGestureDetector_doubleTapEnabled_proxCovered() {
+ // GIVEN double tap is enabled, not a false tap based on classifiers
+ whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true)
+ updateSettings()
+ whenever(falsingManager.isFalseDoubleTap).thenReturn(false)
+
+ // GIVEN prox is covered
+ whenever(falsingManager.isProximityNear()).thenReturn(true)
+
+ // WHEN there's a tap
+ underTest.onDoubleTap(downEv)
+
+ // THEN the device doesn't wake up
+ verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString())
+ }
+
+ fun updateSettings() {
+ tunableCaptor = ArgumentCaptor.forClass(Tunable::class.java)
+ verify(tunerService).addTunable(
+ tunableCaptor.capture(),
+ eq(DOZE_DOUBLE_TAP_GESTURE),
+ eq(DOZE_TAP_SCREEN_GESTURE))
+ tunableCaptor.value.onTuningChanged(DOZE_DOUBLE_TAP_GESTURE, "")
+ tunableCaptor.value.onTuningChanged(DOZE_TAP_SCREEN_GESTURE, "")
+ }
+}
+
+private val downEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index 1cbb8d0..131eac6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -130,13 +130,16 @@
pluginListener.onPluginConnected(plugin1, mockContext)
pluginListener.onPluginConnected(plugin2, mockContext)
val list = registry.getClocks()
- assertEquals(list, listOf(
- ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
- ClockMetadata("clock_1", "clock 1"),
- ClockMetadata("clock_2", "clock 2"),
- ClockMetadata("clock_3", "clock 3"),
- ClockMetadata("clock_4", "clock 4")
- ))
+ assertEquals(
+ list,
+ listOf(
+ ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
+ ClockMetadata("clock_1", "clock 1"),
+ ClockMetadata("clock_2", "clock 2"),
+ ClockMetadata("clock_3", "clock 3"),
+ ClockMetadata("clock_4", "clock 4")
+ )
+ )
}
@Test
@@ -158,11 +161,14 @@
pluginListener.onPluginConnected(plugin1, mockContext)
pluginListener.onPluginConnected(plugin2, mockContext)
val list = registry.getClocks()
- assertEquals(list, listOf(
- ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
- ClockMetadata("clock_1", "clock 1"),
- ClockMetadata("clock_2", "clock 2")
- ))
+ assertEquals(
+ list,
+ listOf(
+ ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
+ ClockMetadata("clock_1", "clock 1"),
+ ClockMetadata("clock_2", "clock 2")
+ )
+ )
assertEquals(registry.createExampleClock("clock_1"), mockClock)
assertEquals(registry.createExampleClock("clock_2"), mockClock)
@@ -222,7 +228,7 @@
pluginListener.onPluginConnected(plugin2, mockContext)
var changeCallCount = 0
- registry.registerClockChangeListener({ changeCallCount++ })
+ registry.registerClockChangeListener { changeCallCount++ }
pluginListener.onPluginDisconnected(plugin1)
assertEquals(0, changeCallCount)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index 7869448..2b4a109 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -19,17 +19,31 @@
import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.testing.AndroidTestingRunner
+import android.util.TypedValue
import android.view.LayoutInflater
+import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.shared.clocks.DefaultClock.Companion.DOZE_COLOR
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import java.util.Locale
+import java.util.TimeZone
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertNotNull
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyFloat
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.notNull
import org.mockito.Mock
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
@@ -39,7 +53,8 @@
@JvmField @Rule val mockito = MockitoJUnit.rule()
- @Mock private lateinit var mockClockView: AnimatableClockView
+ @Mock private lateinit var mockSmallClockView: AnimatableClockView
+ @Mock private lateinit var mockLargeClockView: AnimatableClockView
@Mock private lateinit var layoutInflater: LayoutInflater
@Mock private lateinit var mockClockThumbnail: Drawable
@Mock private lateinit var resources: Resources
@@ -47,14 +62,16 @@
@Before
fun setUp() {
- whenever(layoutInflater.inflate(R.layout.clock_default_small, null))
- .thenReturn(mockClockView)
- whenever(layoutInflater.inflate(R.layout.clock_default_large, null))
- .thenReturn(mockClockView)
+ whenever(layoutInflater.inflate(eq(R.layout.clock_default_small), any(), anyBoolean()))
+ .thenReturn(mockSmallClockView)
+ whenever(layoutInflater.inflate(eq(R.layout.clock_default_large), any(), anyBoolean()))
+ .thenReturn(mockLargeClockView)
whenever(resources.getDrawable(R.drawable.clock_default_thumbnail, null))
.thenReturn(mockClockThumbnail)
+ whenever(mockSmallClockView.getLayoutParams()).thenReturn(FrameLayout.LayoutParams(10, 10))
+ whenever(mockLargeClockView.getLayoutParams()).thenReturn(FrameLayout.LayoutParams(10, 10))
- provider = DefaultClockProvider(layoutInflater, resources)
+ provider = DefaultClockProvider(context, layoutInflater, resources)
}
@Test
@@ -71,7 +88,79 @@
// Default clock provider must always provide the default clock
val clock = provider.createClock(DEFAULT_CLOCK_ID)
assertNotNull(clock)
- assertEquals(clock.smallClock, mockClockView)
- assertEquals(clock.largeClock, mockClockView)
+ assertEquals(clock.smallClock, mockSmallClockView)
+ assertEquals(clock.largeClock, mockLargeClockView)
+ }
+
+ @Test
+ fun defaultClock_initialize() {
+ val clock = provider.createClock(DEFAULT_CLOCK_ID)
+ clock.initialize(resources, 0f, 0f)
+
+ verify(mockSmallClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt())
+ verify(mockLargeClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt())
+ verify(mockSmallClockView).onTimeZoneChanged(notNull())
+ verify(mockLargeClockView).onTimeZoneChanged(notNull())
+ verify(mockSmallClockView).refreshTime()
+ verify(mockLargeClockView).refreshTime()
+ verify(mockLargeClockView).setLayoutParams(any())
+ }
+
+ @Test
+ fun defaultClock_events_onTimeTick() {
+ val clock = provider.createClock(DEFAULT_CLOCK_ID)
+ clock.events.onTimeTick()
+
+ verify(mockSmallClockView).refreshTime()
+ verify(mockLargeClockView).refreshTime()
+ }
+
+ @Test
+ fun defaultClock_events_onTimeFormatChanged() {
+ val clock = provider.createClock(DEFAULT_CLOCK_ID)
+ clock.events.onTimeFormatChanged(true)
+
+ verify(mockSmallClockView).refreshFormat(true)
+ verify(mockLargeClockView).refreshFormat(true)
+ }
+
+ @Test
+ fun defaultClock_events_onTimeZoneChanged() {
+ val timeZone = mock<TimeZone>()
+ val clock = provider.createClock(DEFAULT_CLOCK_ID)
+ clock.events.onTimeZoneChanged(timeZone)
+
+ verify(mockSmallClockView).onTimeZoneChanged(timeZone)
+ verify(mockLargeClockView).onTimeZoneChanged(timeZone)
+ }
+
+ @Test
+ fun defaultClock_events_onFontSettingChanged() {
+ val clock = provider.createClock(DEFAULT_CLOCK_ID)
+ clock.events.onFontSettingChanged()
+
+ verify(mockSmallClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), anyFloat())
+ verify(mockLargeClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), anyFloat())
+ verify(mockLargeClockView).setLayoutParams(any())
+ }
+
+ @Test
+ fun defaultClock_events_onColorPaletteChanged() {
+ val clock = provider.createClock(DEFAULT_CLOCK_ID)
+ clock.events.onColorPaletteChanged(resources, true, true)
+
+ verify(mockSmallClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt())
+ verify(mockLargeClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt())
+ }
+
+ @Test
+ fun defaultClock_events_onLocaleChanged() {
+ val clock = provider.createClock(DEFAULT_CLOCK_ID)
+ clock.events.onLocaleChanged(Locale.getDefault())
+
+ verify(mockSmallClockView, times(2)).setLineSpacingScale(anyFloat())
+ verify(mockLargeClockView, times(2)).setLineSpacingScale(anyFloat())
+ verify(mockSmallClockView, times(2)).refreshFormat()
+ verify(mockLargeClockView, times(2)).refreshFormat()
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
index 98de176..c6207e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
@@ -82,12 +82,10 @@
private final class TestableAlertingNotificationManager extends AlertingNotificationManager {
private AlertEntry mLastCreatedEntry;
- private TestableAlertingNotificationManager() {
- super(mock(HeadsUpManagerLogger.class));
+ private TestableAlertingNotificationManager(Handler handler) {
+ super(mock(HeadsUpManagerLogger.class), handler);
mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
- mHandler.removeCallbacksAndMessages(null);
- mHandler = mTestHandler;
}
@Override
@@ -108,8 +106,8 @@
}
}
- protected AlertingNotificationManager createAlertingNotificationManager() {
- return new TestableAlertingNotificationManager();
+ protected AlertingNotificationManager createAlertingNotificationManager(Handler handler) {
+ return new TestableAlertingNotificationManager(handler);
}
protected StatusBarNotification createNewSbn(int id, Notification.Builder n) {
@@ -143,7 +141,7 @@
.build();
mEntry.setRow(mRow);
- mAlertingNotificationManager = createAlertingNotificationManager();
+ mAlertingNotificationManager = createAlertingNotificationManager(mTestHandler);
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 8473c37..798f47d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -20,6 +20,7 @@
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
+import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE;
@@ -31,6 +32,7 @@
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRANSIENT;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRUST;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_USER_LOCKED;
+import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_OFF;
import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON;
import static com.google.common.truth.Truth.assertThat;
@@ -178,9 +180,12 @@
private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor;
@Captor
private ArgumentCaptor<KeyguardStateController.Callback> mKeyguardStateControllerCallbackCaptor;
+ @Captor
+ private ArgumentCaptor<ScreenLifecycle.Observer> mScreenObserverCaptor;
private KeyguardStateController.Callback mKeyguardStateControllerCallback;
private KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback;
private StatusBarStateController.StateListener mStatusBarStateListener;
+ private ScreenLifecycle.Observer mScreenObserver;
private BroadcastReceiver mBroadcastReceiver;
private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
private TestableLooper mTestableLooper;
@@ -273,6 +278,9 @@
mKeyguardUpdateMonitorCallbackCaptor.capture());
mKeyguardUpdateMonitorCallback = mKeyguardUpdateMonitorCallbackCaptor.getValue();
+ verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
+ mScreenObserver = mScreenObserverCaptor.getValue();
+
mExecutor.runAllReady();
reset(mRotateTextViewController);
}
@@ -537,6 +545,58 @@
}
@Test
+ public void transientIndication_visibleWhenWokenUp() {
+ createController();
+ when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
+ final String message = "helpMsg";
+
+ // GIVEN screen is off
+ when(mScreenLifecycle.getScreenState()).thenReturn(SCREEN_OFF);
+
+ // WHEN fingeprint help message received
+ mController.setVisible(true);
+ mController.getKeyguardCallback().onBiometricHelp(BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED,
+ message, BiometricSourceType.FINGERPRINT);
+
+ // THEN message isn't shown right away
+ verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE);
+
+ // WHEN the screen turns on
+ mScreenObserver.onScreenTurnedOn();
+ mTestableLooper.processAllMessages();
+
+ // THEN the message is shown
+ verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, message);
+ }
+
+ @Test
+ public void onBiometricHelp_coEx_faceFailure() {
+ createController();
+
+ // GIVEN unlocking with fingerprint is possible
+ when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(anyInt()))
+ .thenReturn(true);
+
+ String message = "A message";
+ mController.setVisible(true);
+
+ // WHEN there's a face not recognized message
+ mController.getKeyguardCallback().onBiometricHelp(
+ KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED,
+ message,
+ BiometricSourceType.FACE);
+
+ // THEN show sequential messages such as: 'face not recognized' and
+ // 'try fingerprint instead'
+ verifyIndicationMessage(
+ INDICATION_TYPE_BIOMETRIC_MESSAGE,
+ mContext.getString(R.string.keyguard_face_failed));
+ verifyIndicationMessage(
+ INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
+ mContext.getString(R.string.keyguard_suggest_fingerprint));
+ }
+
+ @Test
public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromError() {
createController();
String message = mContext.getString(R.string.keyguard_unlock);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
index 0fd2e38..5432a74 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
@@ -28,12 +28,9 @@
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.shade.ShadeController;
-import com.android.systemui.statusbar.notification.NotificationEntryListener;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
-import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import org.junit.Before;
@@ -54,10 +51,8 @@
public class NonPhoneDependencyTest extends SysuiTestCase {
@Mock private NotificationPresenter mPresenter;
@Mock private NotificationListContainer mListContainer;
- @Mock private NotificationEntryListener mEntryListener;
@Mock private RemoteInputController.Delegate mDelegate;
@Mock private NotificationRemoteInputManager.Callback mRemoteInputManagerCallback;
- @Mock private CheckSaveListener mCheckSaveListener;
@Mock private OnSettingsClickListener mOnSettingsClickListener;
@Before
@@ -72,7 +67,6 @@
@Test
public void testNotificationManagementCodeHasNoDependencyOnStatusBarWindowManager() {
mDependency.injectMockDependency(ShadeController.class);
- NotificationEntryManager entryManager = Dependency.get(NotificationEntryManager.class);
NotificationGutsManager gutsManager = Dependency.get(NotificationGutsManager.class);
NotificationLogger notificationLogger = Dependency.get(NotificationLogger.class);
NotificationMediaManager mediaManager = Dependency.get(NotificationMediaManager.class);
@@ -80,7 +74,6 @@
Dependency.get(NotificationRemoteInputManager.class);
NotificationLockscreenUserManager lockscreenUserManager =
Dependency.get(NotificationLockscreenUserManager.class);
- entryManager.addNotificationEntryListener(mEntryListener);
gutsManager.setUpWithPresenter(mPresenter, mListContainer,
mOnSettingsClickListener);
notificationLogger.setUpWithContainer(mListContainer);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index dd2b667..853d1df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -16,19 +16,11 @@
package com.android.systemui.statusbar;
-import static android.app.NotificationManager.IMPORTANCE_HIGH;
-import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.content.Intent.ACTION_USER_SWITCHED;
-import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_ALERTING;
-import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_MEDIA_CONTROLS;
-import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_PEOPLE;
-import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
-
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -60,9 +52,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager.KeyguardNotificationSuppressor;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.NotificationStateChangedListener;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
@@ -92,8 +82,6 @@
@Mock
private NotificationVisibilityProvider mVisibilityProvider;
@Mock
- private NotificationEntryManager mEntryManager;
- @Mock
private CommonNotifCollection mNotifCollection;
@Mock
private DevicePolicyManager mDevicePolicyManager;
@@ -122,7 +110,6 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
int currentUserId = ActivityManager.getCurrentUser();
mSettings = new FakeSettings();
@@ -157,12 +144,6 @@
}
@Test
- public void testLockScreenShowNotificationsChangeUpdatesNotifications() {
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
- verify(mEntryManager, times(1)).updateNotifications(anyString());
- }
-
- @Test
public void testLockScreenShowNotificationsFalse() {
mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0);
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
@@ -305,13 +286,6 @@
}
@Test
- public void testSettingsObserverUpdatesNotifications() {
- when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
- mLockscreenUserManager.getSettingsObserverForTest().onChange(false);
- verify(mEntryManager, times(1)).updateNotifications(anyString());
- }
-
- @Test
public void testActionUserSwitchedCallsOnUserSwitched() {
Intent intent = new Intent()
.setAction(ACTION_USER_SWITCHED)
@@ -359,93 +333,6 @@
verify(listener, never()).onNotificationStateChanged();
}
- @Test
- public void testShowSilentNotifications_settingSaysShow() {
- mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
- mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
-
- NotificationEntry entry = new NotificationEntryBuilder()
- .setImportance(IMPORTANCE_LOW)
- .build();
- entry.setBucket(BUCKET_SILENT);
-
- assertTrue(mLockscreenUserManager.shouldShowOnKeyguard(entry));
- }
-
- @Test
- public void testShowSilentNotifications_settingSaysHide() {
- mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
- mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
-
- final Notification notification = mock(Notification.class);
- when(notification.isForegroundService()).thenReturn(true);
- NotificationEntry entry = new NotificationEntryBuilder()
- .setImportance(IMPORTANCE_LOW)
- .setNotification(notification)
- .build();
- entry.setBucket(BUCKET_SILENT);
- assertFalse(mLockscreenUserManager.shouldShowOnKeyguard(entry));
- }
-
- @Test
- public void testShowSilentNotificationsPeopleBucket_settingSaysHide() {
- mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
- mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
-
- final Notification notification = mock(Notification.class);
- when(notification.isForegroundService()).thenReturn(true);
- NotificationEntry entry = new NotificationEntryBuilder()
- .setImportance(IMPORTANCE_LOW)
- .setNotification(notification)
- .build();
- entry.setBucket(BUCKET_PEOPLE);
- assertFalse(mLockscreenUserManager.shouldShowOnKeyguard(entry));
- }
-
- @Test
- public void testShowSilentNotificationsMediaBucket_settingSaysHide() {
- mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
- mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
-
- final Notification notification = mock(Notification.class);
- when(notification.isForegroundService()).thenReturn(true);
- NotificationEntry entry = new NotificationEntryBuilder()
- .setImportance(IMPORTANCE_LOW)
- .setNotification(notification)
- .build();
- entry.setBucket(BUCKET_MEDIA_CONTROLS);
- // always show media controls, even if they're silent
- assertTrue(mLockscreenUserManager.shouldShowOnKeyguard(entry));
- }
-
- @Test
- public void testKeyguardNotificationSuppressors() {
- // GIVEN a notification that should be shown on the lockscreen
- mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
- mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
- final NotificationEntry entry = new NotificationEntryBuilder()
- .setImportance(IMPORTANCE_HIGH)
- .build();
- entry.setBucket(BUCKET_ALERTING);
-
- // WHEN a suppressor is added that filters out all entries
- FakeKeyguardSuppressor suppressor = new FakeKeyguardSuppressor();
- mLockscreenUserManager.addKeyguardNotificationSuppressor(suppressor);
-
- // THEN it's filtered out
- assertFalse(mLockscreenUserManager.shouldShowOnKeyguard(entry));
-
- // WHEN the suppressor no longer filters out entries
- suppressor.setShouldSuppress(false);
-
- // THEN it's no longer filtered out
- assertTrue(mLockscreenUserManager.shouldShowOnKeyguard(entry));
- }
-
private class TestNotificationLockscreenUserManager
extends NotificationLockscreenUserManagerImpl {
public TestNotificationLockscreenUserManager(Context context) {
@@ -478,17 +365,4 @@
return mSettingsObserver;
}
}
-
- private static class FakeKeyguardSuppressor implements KeyguardNotificationSuppressor {
- private boolean mShouldSuppress = true;
-
- @Override
- public boolean shouldSuppressOnKeyguard(NotificationEntry entry) {
- return mShouldSuppress;
- }
-
- public void setShouldSuppress(boolean shouldSuppress) {
- mShouldSuppress = shouldSuppress;
- }
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
index 6e29669..5170678 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -23,8 +23,6 @@
import android.app.Notification;
import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
import android.os.SystemClock;
import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
@@ -36,7 +34,6 @@
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
@@ -70,7 +67,6 @@
@Mock private StatusBarStateController mStateController;
@Mock private RemoteInputUriController mRemoteInputUriController;
@Mock private NotificationClickNotifier mClickNotifier;
- @Mock private NotificationEntryManager mEntryManager;
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
private TestableNotificationRemoteInputManager mRemoteInputManager;
@@ -85,11 +81,8 @@
mLockscreenUserManager,
mSmartReplyController,
mVisibilityProvider,
- mEntryManager,
- mock(RemoteInputNotificationRebuilder.class),
() -> Optional.of(mock(CentralSurfaces.class)),
mStateController,
- Handler.createAsync(Looper.myLooper()),
mRemoteInputUriController,
mClickNotifier,
mock(ActionClickLogger.class),
@@ -145,11 +138,8 @@
NotificationLockscreenUserManager lockscreenUserManager,
SmartReplyController smartReplyController,
NotificationVisibilityProvider visibilityProvider,
- NotificationEntryManager notificationEntryManager,
- RemoteInputNotificationRebuilder rebuilder,
Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy,
StatusBarStateController statusBarStateController,
- Handler mainHandler,
RemoteInputUriController remoteInputUriController,
NotificationClickNotifier clickNotifier,
ActionClickLogger actionClickLogger,
@@ -160,7 +150,6 @@
lockscreenUserManager,
smartReplyController,
visibilityProvider,
- notificationEntryManager,
centralSurfacesOptionalLazy,
statusBarStateController,
remoteInputUriController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt
new file mode 100644
index 0000000..215afb2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.disableflags
+
+import android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS
+import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS
+import android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS
+import android.app.StatusBarManager.DISABLE_CLOCK
+import android.app.StatusBarManager.DISABLE_EXPAND
+import android.app.StatusBarManager.DISABLE_NAVIGATION
+import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS
+import android.app.StatusBarManager.DISABLE_NOTIFICATION_TICKER
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.CommandQueue
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+class DisableStateTrackerTest : SysuiTestCase() {
+
+ private lateinit var underTest: DisableStateTracker
+
+ @Mock private lateinit var commandQueue: CommandQueue
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ }
+
+ @Test
+ fun startTracking_commandQueueGetsCallback() {
+ underTest = DisableStateTracker(0, 0) { }
+
+ underTest.startTracking(commandQueue, displayId = 0)
+
+ verify(commandQueue).addCallback(underTest)
+ }
+
+ @Test
+ fun stopTracking_commandQueueLosesCallback() {
+ underTest = DisableStateTracker(0, 0) { }
+
+ underTest.stopTracking(commandQueue)
+
+ verify(commandQueue).removeCallback(underTest)
+ }
+
+ @Test
+ fun disable_hadNotStartedTracking_isDisabledFalse() {
+ underTest = DisableStateTracker(DISABLE_CLOCK, 0) { }
+
+ underTest.disable(displayId = 0, state1 = DISABLE_CLOCK, state2 = 0, animate = false)
+
+ assertThat(underTest.isDisabled).isFalse()
+ }
+
+ @Test
+ fun disable_wrongDisplayId_isDisabledFalse() {
+ underTest = DisableStateTracker(DISABLE_CLOCK, 0) { }
+ underTest.startTracking(commandQueue, displayId = 15)
+
+ underTest.disable(displayId = 20, state1 = DISABLE_CLOCK, state2 = 0, animate = false)
+
+ assertThat(underTest.isDisabled).isFalse()
+ }
+
+ @Test
+ fun disable_irrelevantFlagsUpdated_isDisabledFalse() {
+ underTest = DisableStateTracker(DISABLE_CLOCK, DISABLE2_GLOBAL_ACTIONS) { }
+ underTest.startTracking(commandQueue, DISPLAY_ID)
+
+ underTest.disable(
+ DISPLAY_ID, state1 = DISABLE_EXPAND, state2 = DISABLE2_QUICK_SETTINGS, animate = false
+ )
+
+ assertThat(underTest.isDisabled).isFalse()
+ }
+
+ @Test
+ fun disable_partOfMask1True_isDisabledTrue() {
+ underTest = DisableStateTracker(
+ mask1 = DISABLE_CLOCK or DISABLE_EXPAND or DISABLE_NAVIGATION,
+ mask2 = DISABLE2_GLOBAL_ACTIONS
+ ) { }
+ underTest.startTracking(commandQueue, DISPLAY_ID)
+
+ underTest.disable(DISPLAY_ID, state1 = DISABLE_EXPAND, state2 = 0, animate = false)
+
+ assertThat(underTest.isDisabled).isTrue()
+ }
+
+ @Test
+ fun disable_partOfMask2True_isDisabledTrue() {
+ underTest = DisableStateTracker(
+ mask1 = DISABLE_CLOCK,
+ mask2 = DISABLE2_GLOBAL_ACTIONS or DISABLE2_SYSTEM_ICONS
+ ) { }
+ underTest.startTracking(commandQueue, DISPLAY_ID)
+
+ underTest.disable(DISPLAY_ID, state1 = 0, state2 = DISABLE2_SYSTEM_ICONS, animate = false)
+
+ assertThat(underTest.isDisabled).isTrue()
+ }
+
+ @Test
+ fun disable_isDisabledChangesFromFalseToTrue_callbackNotified() {
+ var callbackCalled = false
+
+ underTest = DisableStateTracker(
+ mask1 = DISABLE_CLOCK,
+ mask2 = DISABLE2_GLOBAL_ACTIONS
+ ) { callbackCalled = true }
+ underTest.startTracking(commandQueue, DISPLAY_ID)
+
+ underTest.disable(DISPLAY_ID, state1 = DISABLE_CLOCK, state2 = 0, animate = false)
+
+ assertThat(callbackCalled).isTrue()
+ }
+
+ @Test
+ fun disable_isDisabledChangesFromTrueToFalse_callbackNotified() {
+ var callbackCalled: Boolean
+
+ underTest = DisableStateTracker(
+ mask1 = DISABLE_CLOCK,
+ mask2 = DISABLE2_GLOBAL_ACTIONS
+ ) { callbackCalled = true }
+ underTest.startTracking(commandQueue, DISPLAY_ID)
+
+ // First, update isDisabled to true
+ underTest.disable(DISPLAY_ID, state1 = DISABLE_CLOCK, state2 = 0, animate = false)
+ assertThat(underTest.isDisabled).isTrue()
+
+ // WHEN isDisabled updates back to false
+ callbackCalled = false
+ underTest.disable(DISPLAY_ID, state1 = 0, state2 = 0, animate = false)
+
+ // THEN the callback is called again
+ assertThat(callbackCalled).isTrue()
+ }
+
+ @Test
+ fun disable_manyUpdates_isDisabledUpdatesAppropriately() {
+ underTest = DisableStateTracker(
+ mask1 = DISABLE_CLOCK or DISABLE_EXPAND or DISABLE_NAVIGATION,
+ mask2 = DISABLE2_GLOBAL_ACTIONS or DISABLE2_SYSTEM_ICONS
+ ) { }
+ underTest.startTracking(commandQueue, DISPLAY_ID)
+
+ // All flags from mask1 -> isDisabled = true
+ underTest.disable(
+ DISPLAY_ID,
+ state1 = DISABLE_CLOCK or DISABLE_EXPAND or DISABLE_NAVIGATION,
+ state2 = 0,
+ animate = false
+ )
+ assertThat(underTest.isDisabled).isTrue()
+
+ // Irrelevant flags from mask1 -> isDisabled = false
+ underTest.disable(
+ DISPLAY_ID,
+ state1 = DISABLE_NOTIFICATION_ICONS or DISABLE_NOTIFICATION_TICKER,
+ state2 = 0,
+ animate = false
+ )
+ assertThat(underTest.isDisabled).isFalse()
+
+ // All flags from mask1 & all flags from mask2 -> isDisabled = true
+ underTest.disable(
+ DISPLAY_ID,
+ state1 = DISABLE_CLOCK or DISABLE_EXPAND or DISABLE_NAVIGATION,
+ state2 = DISABLE2_GLOBAL_ACTIONS or DISABLE2_SYSTEM_ICONS,
+ animate = false
+ )
+ assertThat(underTest.isDisabled).isTrue()
+
+ // No flags -> isDisabled = false
+ underTest.disable(DISPLAY_ID, state1 = 0, state2 = 0, animate = false)
+ assertThat(underTest.isDisabled).isFalse()
+
+ // 1 flag from mask1 & 1 flag from mask2 -> isDisabled = true
+ underTest.disable(
+ DISPLAY_ID,
+ state1 = DISABLE_NAVIGATION,
+ state2 = DISABLE2_SYSTEM_ICONS,
+ animate = false
+ )
+ assertThat(underTest.isDisabled).isTrue()
+ }
+
+ companion object {
+ private const val DISPLAY_ID = 3
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java
index 3fc0c81..b719c7f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java
@@ -18,7 +18,6 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
@@ -128,8 +127,6 @@
@Test
public void testNotNotifiedWithoutNotifications() {
when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true);
- when(mLockScreenUserManager.shouldHideNotifications(anyInt())).thenReturn(
- true);
mDynamicPrivacyController.onUnlockedChanged();
verifyNoMoreInteractions(mListener);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
deleted file mode 100644
index 19dd027..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2019 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.statusbar.notification;
-
-import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
-
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.verify;
-
-import android.app.ActivityManager;
-import android.app.Notification;
-import android.os.UserHandle;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-
-import org.junit.Before;
-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
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class NotificationListControllerTest extends SysuiTestCase {
- private NotificationListController mController;
-
- @Mock private NotificationEntryManager mEntryManager;
- @Mock private NotificationListContainer mListContainer;
- @Mock private DeviceProvisionedController mDeviceProvisionedController;
-
- @Captor private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
- @Captor private ArgumentCaptor<DeviceProvisionedListener> mProvisionedCaptor;
-
- private NotificationEntryListener mEntryListener;
- private DeviceProvisionedListener mProvisionedListener;
-
- private int mNextNotifId = 0;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
-
- mController = new NotificationListController(
- mEntryManager,
- mListContainer,
- mDeviceProvisionedController);
- mController.bind();
-
- // Capture callbacks passed to mocks
- verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture());
- mEntryListener = mEntryListenerCaptor.getValue();
- verify(mDeviceProvisionedController).addCallback(mProvisionedCaptor.capture());
- mProvisionedListener = mProvisionedCaptor.getValue();
- }
-
- @Test
- public void testCleanUpViewStateOnEntryRemoved() {
- final NotificationEntry entry = buildEntry();
- mEntryListener.onEntryRemoved(
- entry,
- NotificationVisibility.obtain(entry.getKey(), 0, 0, true),
- false,
- UNDEFINED_DISMISS_REASON);
- verify(mListContainer).cleanUpViewStateForEntry(entry);
- }
-
- @Test
- public void testCallUpdateNotificationsOnDeviceProvisionedChange() {
- mProvisionedListener.onDeviceProvisionedChanged();
- verify(mEntryManager).updateNotifications(anyString());
- }
-
- private NotificationEntry buildEntry() {
- mNextNotifId++;
-
- Notification.Builder n = new Notification.Builder(mContext, "")
- .setSmallIcon(R.drawable.ic_person)
- .setContentTitle("Title")
- .setContentText("Text");
-
- return new NotificationEntryBuilder()
- .setPkg(TEST_PACKAGE_NAME)
- .setOpPkg(TEST_PACKAGE_NAME)
- .setId(mNextNotifId)
- .setUid(TEST_UID)
- .setNotification(n.build())
- .setUser(new UserHandle(ActivityManager.getCurrentUser()))
- .build();
- }
-
- private static final String TEST_PACKAGE_NAME = "test";
- private static final int TEST_UID = 0;
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 4df99be..851517e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -1518,7 +1518,7 @@
verify(mCollectionListener).onRankingApplied();
verifyNoMoreInteractions(mCollectionListener);
verify(mLogger).logMissingRankings(eq(List.of(entry1)), eq(1), any());
- verify(mLogger, never()).logRecoveredRankings(any());
+ verify(mLogger, never()).logRecoveredRankings(any(), anyInt());
clearInvocations(mCollectionListener, mLogger);
// WHEN a ranking update includes key1 again
@@ -1530,7 +1530,7 @@
verify(mCollectionListener).onRankingApplied();
verifyNoMoreInteractions(mCollectionListener);
verify(mLogger, never()).logMissingRankings(any(), anyInt(), any());
- verify(mLogger).logRecoveredRankings(eq(List.of(key1)));
+ verify(mLogger).logRecoveredRankings(eq(List.of(key1)), eq(0));
}
@Test
@@ -1556,7 +1556,7 @@
verify(mCollectionListener).onRankingApplied();
verifyNoMoreInteractions(mCollectionListener);
verify(mLogger).logMissingRankings(eq(List.of(entry1)), eq(1), any());
- verify(mLogger, never()).logRecoveredRankings(any());
+ verify(mLogger, never()).logRecoveredRankings(any(), anyInt());
clearInvocations(mCollectionListener, mLogger);
// WHEN a ranking update includes key1 again
@@ -1568,7 +1568,7 @@
verify(mCollectionListener).onRankingApplied();
verifyNoMoreInteractions(mCollectionListener);
verify(mLogger, never()).logMissingRankings(any(), anyInt(), any());
- verify(mLogger).logRecoveredRankings(eq(List.of(key1)));
+ verify(mLogger).logRecoveredRankings(eq(List.of(key1)), eq(0));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
index d4f0505..8272f5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
@@ -23,11 +23,9 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
-import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
@@ -46,7 +44,6 @@
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
-import org.mockito.Mockito.anyString
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
@@ -61,10 +58,6 @@
@Mock
private lateinit var smartspaceController: LockscreenSmartspaceController
@Mock
- private lateinit var notificationEntryManager: NotificationEntryManager
- @Mock
- private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager
- @Mock
private lateinit var notifPipeline: NotifPipeline
@Mock
private lateinit var pluggableListener: Pluggable.PluggableListener<NotifFilter>
@@ -99,12 +92,10 @@
deduper = SmartspaceDedupingCoordinator(
statusBarStateController,
smartspaceController,
- notificationEntryManager,
- notificationLockscreenUserManager,
notifPipeline,
executor,
clock
- )
+ )
// Attach the deduper and capture the listeners/filters that it registers
deduper.attach(notifPipeline)
@@ -352,7 +343,6 @@
// THEN the new pipeline is invalidated (but the old one isn't because it's not
// necessary) because the notif should no longer be filtered out
verify(pluggableListener).onPluggableInvalidated(eq(filter), any())
- verify(notificationEntryManager, never()).updateNotifications(anyString())
assertFalse(filter.shouldFilterOut(entry2HasNotRecentlyAlerted, now))
}
@@ -390,7 +380,6 @@
private fun verifyPipelinesInvalidated() {
verify(pluggableListener).onPluggableInvalidated(eq(filter), any())
- verify(notificationEntryManager).updateNotifications(anyString())
}
private fun assertExecutorIsClear() {
@@ -399,12 +388,10 @@
private fun verifyPipelinesNotInvalidated() {
verify(pluggableListener, never()).onPluggableInvalidated(eq(filter), any())
- verify(notificationEntryManager, never()).updateNotifications(anyString())
}
private fun clearPipelineInvocations() {
clearInvocations(pluggableListener)
- clearInvocations(notificationEntryManager)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/legacy/GroupEventDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/legacy/GroupEventDispatcherTest.kt
deleted file mode 100644
index c17fe6f..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/legacy/GroupEventDispatcherTest.kt
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.statusbar.notification.collection.legacy
-
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.GroupEventDispatcher
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.NotificationGroup
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.OnGroupChangeListener
-import com.android.systemui.statusbar.phone.NotificationGroupTestHelper
-import com.android.systemui.util.mockito.mock
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@RunWithLooper
-class GroupEventDispatcherTest : SysuiTestCase() {
- val groupMap = mutableMapOf<String, NotificationGroup>()
- val groupTestHelper = NotificationGroupTestHelper(mContext)
-
- private val dispatcher = GroupEventDispatcher(groupMap::get)
- private val listener: OnGroupChangeListener = mock()
-
- @Before
- fun setup() {
- dispatcher.registerGroupChangeListener(listener)
- }
-
- @Test
- fun testOnGroupsChangedUnbuffered() {
- dispatcher.notifyGroupsChanged()
- verify(listener).onGroupsChanged()
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testOnGroupsChangedBuffered() {
- dispatcher.openBufferScope()
- dispatcher.notifyGroupsChanged()
- verifyNoMoreInteractions(listener)
- dispatcher.closeBufferScope()
- verify(listener).onGroupsChanged()
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testOnGroupsChangedDoubleBuffered() {
- dispatcher.openBufferScope()
- dispatcher.notifyGroupsChanged()
- dispatcher.openBufferScope() // open a nested buffer scope
- dispatcher.notifyGroupsChanged()
- dispatcher.closeBufferScope() // should NOT flush events
- dispatcher.notifyGroupsChanged()
- verifyNoMoreInteractions(listener)
- dispatcher.closeBufferScope() // this SHOULD flush events
- verify(listener).onGroupsChanged()
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testOnGroupsChangedBufferCoalesces() {
- dispatcher.openBufferScope()
- dispatcher.notifyGroupsChanged()
- dispatcher.notifyGroupsChanged()
- verifyNoMoreInteractions(listener)
- dispatcher.closeBufferScope()
- verify(listener).onGroupsChanged()
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testOnGroupCreatedIsNeverBuffered() {
- val group = addGroup(1)
-
- dispatcher.openBufferScope()
- dispatcher.notifyGroupCreated(group)
- verify(listener).onGroupCreated(group, group.groupKey)
- verifyNoMoreInteractions(listener)
-
- dispatcher.closeBufferScope()
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testOnGroupRemovedIsNeverBuffered() {
- val group = addGroup(1)
-
- dispatcher.openBufferScope()
- dispatcher.notifyGroupRemoved(group)
- verify(listener).onGroupRemoved(group, group.groupKey)
- verifyNoMoreInteractions(listener)
-
- dispatcher.closeBufferScope()
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testAlertOverrideAddedUnbuffered() {
- val group = addGroup(1)
- val newAlertEntry = groupTestHelper.createChildNotification()
- group.alertOverride = newAlertEntry
- dispatcher.notifyAlertOverrideChanged(group, null)
- verify(listener).onGroupAlertOverrideChanged(group, null, newAlertEntry)
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testAlertOverrideRemovedUnbuffered() {
- val group = addGroup(1)
- val oldAlertEntry = groupTestHelper.createChildNotification()
- dispatcher.notifyAlertOverrideChanged(group, oldAlertEntry)
- verify(listener).onGroupAlertOverrideChanged(group, oldAlertEntry, null)
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testAlertOverrideChangedUnbuffered() {
- val group = addGroup(1)
- val oldAlertEntry = groupTestHelper.createChildNotification()
- val newAlertEntry = groupTestHelper.createChildNotification()
- group.alertOverride = newAlertEntry
- dispatcher.notifyAlertOverrideChanged(group, oldAlertEntry)
- verify(listener).onGroupAlertOverrideChanged(group, oldAlertEntry, newAlertEntry)
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testAlertOverrideChangedBuffered() {
- dispatcher.openBufferScope()
- val group = addGroup(1)
- val oldAlertEntry = groupTestHelper.createChildNotification()
- val newAlertEntry = groupTestHelper.createChildNotification()
- group.alertOverride = newAlertEntry
- dispatcher.notifyAlertOverrideChanged(group, oldAlertEntry)
- verifyNoMoreInteractions(listener)
- dispatcher.closeBufferScope()
- verify(listener).onGroupAlertOverrideChanged(group, oldAlertEntry, newAlertEntry)
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testAlertOverrideIgnoredIfRemoved() {
- dispatcher.openBufferScope()
- val group = addGroup(1)
- val oldAlertEntry = groupTestHelper.createChildNotification()
- val newAlertEntry = groupTestHelper.createChildNotification()
- group.alertOverride = newAlertEntry
- dispatcher.notifyAlertOverrideChanged(group, oldAlertEntry)
- verifyNoMoreInteractions(listener)
- groupMap.clear()
- dispatcher.closeBufferScope()
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testAlertOverrideMultipleChangesBuffered() {
- dispatcher.openBufferScope()
- val group = addGroup(1)
- val oldAlertEntry = groupTestHelper.createChildNotification()
- val newAlertEntry = groupTestHelper.createChildNotification()
- group.alertOverride = null
- dispatcher.notifyAlertOverrideChanged(group, oldAlertEntry)
- group.alertOverride = newAlertEntry
- dispatcher.notifyAlertOverrideChanged(group, null)
- verifyNoMoreInteractions(listener)
- dispatcher.closeBufferScope()
- verify(listener).onGroupAlertOverrideChanged(group, oldAlertEntry, newAlertEntry)
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testAlertOverrideTemporaryValueSwallowed() {
- dispatcher.openBufferScope()
- val group = addGroup(1)
- val stableAlertEntry = groupTestHelper.createChildNotification()
- group.alertOverride = null
- dispatcher.notifyAlertOverrideChanged(group, stableAlertEntry)
- group.alertOverride = stableAlertEntry
- dispatcher.notifyAlertOverrideChanged(group, null)
- verifyNoMoreInteractions(listener)
- dispatcher.closeBufferScope()
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testAlertOverrideTemporaryNullSwallowed() {
- dispatcher.openBufferScope()
- val group = addGroup(1)
- val temporaryAlertEntry = groupTestHelper.createChildNotification()
- group.alertOverride = temporaryAlertEntry
- dispatcher.notifyAlertOverrideChanged(group, null)
- group.alertOverride = null
- dispatcher.notifyAlertOverrideChanged(group, temporaryAlertEntry)
- verifyNoMoreInteractions(listener)
- dispatcher.closeBufferScope()
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testSuppressOnUnbuffered() {
- val group = addGroup(1)
- group.suppressed = true
- dispatcher.notifySuppressedChanged(group)
- verify(listener).onGroupSuppressionChanged(group, true)
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testSuppressOffUnbuffered() {
- val group = addGroup(1)
- group.suppressed = false
- dispatcher.notifySuppressedChanged(group)
- verify(listener).onGroupSuppressionChanged(group, false)
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testSuppressOnBuffered() {
- dispatcher.openBufferScope()
- val group = addGroup(1)
- group.suppressed = false
- dispatcher.notifySuppressedChanged(group)
- verifyNoMoreInteractions(listener)
- dispatcher.closeBufferScope()
- verify(listener).onGroupSuppressionChanged(group, false)
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testSuppressOnIgnoredIfRemoved() {
- dispatcher.openBufferScope()
- val group = addGroup(1)
- group.suppressed = false
- dispatcher.notifySuppressedChanged(group)
- verifyNoMoreInteractions(listener)
- groupMap.clear()
- dispatcher.closeBufferScope()
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testSuppressOnOffBuffered() {
- dispatcher.openBufferScope()
- val group = addGroup(1)
- group.suppressed = true
- dispatcher.notifySuppressedChanged(group)
- group.suppressed = false
- dispatcher.notifySuppressedChanged(group)
- verifyNoMoreInteractions(listener)
- dispatcher.closeBufferScope()
- verifyNoMoreInteractions(listener)
- }
-
- @Test
- fun testSuppressOnOffOnBuffered() {
- dispatcher.openBufferScope()
- val group = addGroup(1)
- group.suppressed = true
- dispatcher.notifySuppressedChanged(group)
- group.suppressed = false
- dispatcher.notifySuppressedChanged(group)
- group.suppressed = true
- dispatcher.notifySuppressedChanged(group)
- verifyNoMoreInteractions(listener)
- dispatcher.closeBufferScope()
- verify(listener).onGroupSuppressionChanged(group, true)
- verifyNoMoreInteractions(listener)
- }
-
- private fun addGroup(id: Int): NotificationGroup {
- val group = NotificationGroup("group:$id")
- groupMap[group.groupKey] = group
- return group
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt
new file mode 100644
index 0000000..6eb391a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.notifcollection
+
+import android.service.notification.NotificationListenerService.RankingMap
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class NotifCollectionInconsistencyTrackerTest : SysuiTestCase() {
+ private val logger: NotifCollectionLogger = mock()
+ private val entry1: NotificationEntry = NotificationEntryBuilder().setId(1).build()
+ private val entry2: NotificationEntry = NotificationEntryBuilder().setId(2).build()
+ private val collectionSet = mutableSetOf<String>()
+ private val coalescedSet = mutableSetOf<String>()
+ private lateinit var inconsistencyTracker: NotifCollectionInconsistencyTracker
+
+ private fun mapOfEntries(vararg entries: NotificationEntry): Map<String, NotificationEntry> =
+ entries.associateBy { it.key }
+
+ private fun rankingMapOf(vararg entries: NotificationEntry): RankingMap =
+ RankingMap(entries.map { it.ranking }.toTypedArray())
+
+ @Before
+ fun setUp() {
+ inconsistencyTracker = NotifCollectionInconsistencyTracker(logger)
+ inconsistencyTracker.attach({ collectionSet }, { coalescedSet })
+ collectionSet.clear()
+ coalescedSet.clear()
+ }
+
+ @Test
+ fun maybeLogInconsistentRankings_logsNewlyInconsistentRanking() {
+ val rankingMap = rankingMapOf(entry1)
+ inconsistencyTracker.maybeLogInconsistentRankings(
+ oldKeysWithoutRankings = emptySet(),
+ newEntriesWithoutRankings = mapOfEntries(entry2),
+ rankingMap = rankingMap
+ )
+ verify(logger).logMissingRankings(
+ newlyInconsistentEntries = eq(listOf(entry2)),
+ totalInconsistent = eq(1),
+ rankingMap = eq(rankingMap),
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogInconsistentRankings_doesNotLogAlreadyInconsistentRanking() {
+ inconsistencyTracker.maybeLogInconsistentRankings(
+ oldKeysWithoutRankings = setOf(entry2.key),
+ newEntriesWithoutRankings = mapOfEntries(entry2),
+ rankingMap = rankingMapOf(entry1)
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogInconsistentRankings_logsWhenRankingIsAdded() {
+ inconsistencyTracker.maybeLogInconsistentRankings(
+ oldKeysWithoutRankings = setOf(entry2.key),
+ newEntriesWithoutRankings = mapOfEntries(),
+ rankingMap = rankingMapOf(entry1, entry2)
+ )
+ verify(logger).logRecoveredRankings(
+ newlyConsistentKeys = eq(listOf(entry2.key)),
+ totalInconsistent = eq(0),
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogInconsistentRankings_doesNotLogsWhenEntryIsRemoved() {
+ inconsistencyTracker.maybeLogInconsistentRankings(
+ oldKeysWithoutRankings = setOf(entry2.key),
+ newEntriesWithoutRankings = mapOfEntries(),
+ rankingMap = rankingMapOf(entry1)
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogMissingNotifications_logsNewlyMissingNotifications() {
+ inconsistencyTracker.maybeLogMissingNotifications(
+ oldMissingKeys = setOf("a"),
+ newMissingKeys = setOf("a", "b"),
+ )
+ verify(logger).logMissingNotifications(
+ newlyMissingKeys = eq(listOf("b")),
+ totalMissing = eq(2),
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogMissingNotifications_logsNoLongerMissingNotifications() {
+ inconsistencyTracker.maybeLogMissingNotifications(
+ oldMissingKeys = setOf("a", "b"),
+ newMissingKeys = setOf("a"),
+ )
+ verify(logger).logFoundNotifications(
+ newlyFoundKeys = eq(listOf("b")),
+ totalMissing = eq(1),
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogMissingNotifications_logsBothAtOnce() {
+ inconsistencyTracker.maybeLogMissingNotifications(
+ oldMissingKeys = setOf("a"),
+ newMissingKeys = setOf("b"),
+ )
+ verify(logger).logFoundNotifications(
+ newlyFoundKeys = eq(listOf("a")),
+ totalMissing = eq(1),
+ )
+ verify(logger).logMissingNotifications(
+ newlyMissingKeys = eq(listOf("b")),
+ totalMissing = eq(1),
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogMissingNotifications_logsNothingWhenNoChange() {
+ inconsistencyTracker.maybeLogMissingNotifications(
+ oldMissingKeys = setOf("a"),
+ newMissingKeys = setOf("a"),
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun logNewMissingNotifications_doesNotLogForConsistentSets() {
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf())
+ verifyNoMoreInteractions(logger)
+
+ collectionSet.add(entry1.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1))
+ verifyNoMoreInteractions(logger)
+
+ coalescedSet.add(entry2.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
+ verifyNoMoreInteractions(logger)
+
+ coalescedSet.add(entry1.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
+ verifyNoMoreInteractions(logger)
+
+ coalescedSet.remove(entry1.key)
+ collectionSet.remove(entry1.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry2))
+ verifyNoMoreInteractions(logger)
+
+ coalescedSet.remove(entry2.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf())
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun logNewMissingNotifications_logsAsExpected() {
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf())
+ verifyNoMoreInteractions(logger)
+
+ collectionSet.add(entry1.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
+ verify(logger).logMissingNotifications(
+ newlyMissingKeys = eq(listOf(entry2.key)),
+ totalMissing = eq(1),
+ )
+ verifyNoMoreInteractions(logger)
+ clearInvocations(logger)
+
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
+ verifyNoMoreInteractions(logger)
+
+ coalescedSet.add(entry2.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
+ verify(logger).logFoundNotifications(
+ newlyFoundKeys = eq(listOf(entry2.key)),
+ totalMissing = eq(0),
+ )
+ verifyNoMoreInteractions(logger)
+ clearInvocations(logger)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLoggerTest.kt
deleted file mode 100644
index 6c07174..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLoggerTest.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.statusbar.notification.collection.notifcollection
-
-import android.service.notification.NotificationListenerService.RankingMap
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.mock
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@RunWithLooper
-class NotifCollectionLoggerTest : SysuiTestCase() {
- private val logger: NotifCollectionLogger = mock()
- private val entry1: NotificationEntry = NotificationEntryBuilder().setId(1).build()
- private val entry2: NotificationEntry = NotificationEntryBuilder().setId(2).build()
-
- private fun mapOfEntries(vararg entries: NotificationEntry): Map<String, NotificationEntry> =
- entries.associateBy { it.key }
-
- private fun rankingMapOf(vararg entries: NotificationEntry): RankingMap =
- RankingMap(entries.map { it.ranking }.toTypedArray())
-
- @Test
- fun testMaybeLogInconsistentRankings_logsNewlyInconsistentRanking() {
- val rankingMap = rankingMapOf(entry1)
- maybeLogInconsistentRankings(
- logger = logger,
- oldKeysWithoutRankings = emptySet(),
- newEntriesWithoutRankings = mapOfEntries(entry2),
- rankingMap = rankingMap
- )
- verify(logger).logMissingRankings(
- newlyInconsistentEntries = eq(listOf(entry2)),
- totalInconsistent = eq(1),
- rankingMap = eq(rankingMap),
- )
- verifyNoMoreInteractions(logger)
- }
-
- @Test
- fun testMaybeLogInconsistentRankings_doesNotLogAlreadyInconsistentRanking() {
- maybeLogInconsistentRankings(
- logger = logger,
- oldKeysWithoutRankings = setOf(entry2.key),
- newEntriesWithoutRankings = mapOfEntries(entry2),
- rankingMap = rankingMapOf(entry1)
- )
- verifyNoMoreInteractions(logger)
- }
-
- @Test
- fun testMaybeLogInconsistentRankings_logsWhenRankingIsAdded() {
- maybeLogInconsistentRankings(
- logger = logger,
- oldKeysWithoutRankings = setOf(entry2.key),
- newEntriesWithoutRankings = mapOfEntries(),
- rankingMap = rankingMapOf(entry1, entry2)
- )
- verify(logger).logRecoveredRankings(
- newlyConsistentKeys = eq(listOf(entry2.key)),
- )
- verifyNoMoreInteractions(logger)
- }
-
- @Test
- fun testMaybeLogInconsistentRankings_doesNotLogsWhenEntryIsRemoved() {
- maybeLogInconsistentRankings(
- logger = logger,
- oldKeysWithoutRankings = setOf(entry2.key),
- newEntriesWithoutRankings = mapOfEntries(),
- rankingMap = rankingMapOf(entry1)
- )
- verifyNoMoreInteractions(logger)
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index 8a7b9d3..b2dc842 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -44,8 +44,6 @@
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
-import com.android.systemui.statusbar.notification.NotifPipelineFlags;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifLiveData;
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -85,11 +83,9 @@
@Mock private NotificationLogger.ExpansionStateLogger mExpansionStateLogger;
// Dependency mocks:
- @Mock private NotifPipelineFlags mNotifPipelineFlags;
@Mock private NotifLiveDataStore mNotifLiveDataStore;
@Mock private NotifLiveData<List<NotificationEntry>> mActiveNotifEntries;
@Mock private NotificationVisibilityProvider mVisibilityProvider;
- @Mock private NotificationEntryManager mEntryManager;
@Mock private NotifPipeline mNotifPipeline;
@Mock private NotificationListener mListener;
@@ -118,17 +114,14 @@
mLogger = new TestableNotificationLogger(
mListener,
mUiBgExecutor,
- mNotifPipelineFlags,
mNotifLiveDataStore,
mVisibilityProvider,
- mEntryManager,
mNotifPipeline,
mock(StatusBarStateControllerImpl.class),
mBarService,
mExpansionStateLogger
);
mLogger.setUpWithContainer(mListContainer);
- verify(mEntryManager, never()).addNotificationEntryListener(any());
verify(mNotifPipeline).addCollectionListener(any());
}
@@ -266,10 +259,8 @@
TestableNotificationLogger(NotificationListener notificationListener,
Executor uiBgExecutor,
- NotifPipelineFlags notifPipelineFlags,
NotifLiveDataStore notifLiveDataStore,
NotificationVisibilityProvider visibilityProvider,
- NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
StatusBarStateControllerImpl statusBarStateController,
IStatusBarService barService,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleFakes.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleFakes.kt
deleted file mode 100644
index 1fb4ca1..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleFakes.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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.statusbar.notification.people
-
-object EmptySubscription : Subscription {
- override fun unsubscribe() {}
-}
-
-class FakeDataSource<T>(
- private val data: T,
- private val subscription: Subscription = EmptySubscription
-) : DataSource<T> {
- override fun registerListener(listener: DataListener<T>): Subscription {
- listener.onDataChanged(data)
- return subscription
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt
deleted file mode 100644
index 5898664..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2019 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.statusbar.notification.people
-
-import android.graphics.drawable.Drawable
-import android.testing.AndroidTestingRunner
-import android.view.View
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.plugins.ActivityStarter
-import com.google.common.truth.Truth.assertThat
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.verify
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-import kotlin.reflect.KClass
-import org.mockito.Mockito.`when` as whenever
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-class PeopleHubViewControllerTest : SysuiTestCase() {
-
- @JvmField @Rule val mockito: MockitoRule = MockitoJUnit.rule()
-
- @Mock private lateinit var mockViewBoundary: PeopleHubViewBoundary
- @Mock private lateinit var mockActivityStarter: ActivityStarter
-
- @Test
- fun testBindViewModelToViewBoundary() {
- val fakePerson1 = fakePersonViewModel("name")
- val fakeViewModel = PeopleHubViewModel(sequenceOf(fakePerson1), true)
-
- val mockFactory = mock(PeopleHubViewModelFactory::class.java)
- whenever(mockFactory.createWithAssociatedClickView(any())).thenReturn(fakeViewModel)
-
- val mockClickView = mock(View::class.java)
- whenever(mockViewBoundary.associatedViewForClickAnimation).thenReturn(mockClickView)
-
- val fakePersonViewAdapter1 = FakeDataListener<PersonViewModel?>()
- val fakePersonViewAdapter2 = FakeDataListener<PersonViewModel?>()
- whenever(mockViewBoundary.personViewAdapters)
- .thenReturn(sequenceOf(fakePersonViewAdapter1, fakePersonViewAdapter2))
-
- val adapter = PeopleHubViewAdapterImpl(FakeDataSource(mockFactory))
-
- adapter.bindView(mockViewBoundary)
-
- assertThat(fakePersonViewAdapter1.lastSeen).isEqualTo(Maybe.Just(fakePerson1))
- assertThat(fakePersonViewAdapter2.lastSeen).isEqualTo(Maybe.Just<PersonViewModel?>(null))
- verify(mockViewBoundary).setVisible(true)
- verify(mockFactory).createWithAssociatedClickView(mockClickView)
- }
-
- @Test
- fun testBindViewModelToViewBoundary_moreDataThanCanBeDisplayed_displaysMostRecent() {
- val fakePerson1 = fakePersonViewModel("person1")
- val fakePerson2 = fakePersonViewModel("person2")
- val fakePerson3 = fakePersonViewModel("person3")
- val fakePeople = sequenceOf(fakePerson3, fakePerson2, fakePerson1)
- val fakeViewModel = PeopleHubViewModel(fakePeople, true)
-
- val mockFactory = mock(PeopleHubViewModelFactory::class.java)
- whenever(mockFactory.createWithAssociatedClickView(any())).thenReturn(fakeViewModel)
-
- whenever(mockViewBoundary.associatedViewForClickAnimation)
- .thenReturn(mock(View::class.java))
-
- val fakePersonViewAdapter1 = FakeDataListener<PersonViewModel?>()
- val fakePersonViewAdapter2 = FakeDataListener<PersonViewModel?>()
- whenever(mockViewBoundary.personViewAdapters)
- .thenReturn(sequenceOf(fakePersonViewAdapter1, fakePersonViewAdapter2))
-
- val adapter = PeopleHubViewAdapterImpl(FakeDataSource(mockFactory))
-
- adapter.bindView(mockViewBoundary)
-
- assertThat(fakePersonViewAdapter1.lastSeen).isEqualTo(Maybe.Just(fakePerson3))
- assertThat(fakePersonViewAdapter2.lastSeen).isEqualTo(Maybe.Just(fakePerson2))
- }
-
- @Test
- fun testViewModelDataSourceTransformsModel() {
- val fakeClickRunnable = mock(Runnable::class.java)
- val fakePerson = fakePersonModel("id", "name", fakeClickRunnable)
- val fakeModel = PeopleHubModel(listOf(fakePerson))
- val fakeModelDataSource = FakeDataSource(fakeModel)
- val factoryDataSource = PeopleHubViewModelFactoryDataSourceImpl(
- mockActivityStarter,
- fakeModelDataSource
- )
- val fakeListener = FakeDataListener<PeopleHubViewModelFactory>()
- val mockClickView = mock(View::class.java)
-
- factoryDataSource.registerListener(fakeListener)
-
- val viewModel = (fakeListener.lastSeen as Maybe.Just).value
- .createWithAssociatedClickView(mockClickView)
- assertThat(viewModel.isVisible).isTrue()
- val people = viewModel.people.toList()
- assertThat(people.size).isEqualTo(1)
- assertThat(people[0].name).isEqualTo("name")
- assertThat(people[0].icon).isSameInstanceAs(fakePerson.avatar)
-
- people[0].onClick()
-
- verify(fakeClickRunnable).run()
- }
-}
-
-/** Works around Mockito matchers returning `null` and breaking non-nullable Kotlin code. */
-private inline fun <reified T : Any> any(): T {
- return Mockito.any() ?: createInstance(T::class)
-}
-
-/** Works around Mockito matchers returning `null` and breaking non-nullable Kotlin code. */
-private inline fun <reified T : Any> same(value: T): T {
- return Mockito.same(value) ?: createInstance(T::class)
-}
-
-/** Creates an instance of the given class. */
-private fun <T : Any> createInstance(clazz: KClass<T>): T = castNull()
-
-/** Tricks the Kotlin compiler into assigning `null` to a non-nullable variable. */
-@Suppress("UNCHECKED_CAST")
-private fun <T> castNull(): T = null as T
-
-private fun fakePersonModel(
- id: String,
- name: CharSequence,
- clickRunnable: Runnable,
- userId: Int = 0
-): PersonModel =
- PersonModel(id, userId, name, mock(Drawable::class.java), clickRunnable)
-
-private fun fakePersonViewModel(name: CharSequence): PersonViewModel =
- PersonViewModel(name, mock(Drawable::class.java), mock({}.javaClass))
-
-sealed class Maybe<T> {
- data class Just<T>(val value: T) : Maybe<T>()
- class Nothing<T> : Maybe<T>() {
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
- return true
- }
-
- override fun hashCode(): Int {
- return javaClass.hashCode()
- }
- }
-}
-
-class FakeDataListener<T> : DataListener<T> {
-
- var lastSeen: Maybe<T> = Maybe.Nothing()
-
- override fun onDataChanged(data: T) {
- lastSeen = Maybe.Just(data)
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt
index 214ba16..64d0256 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt
@@ -98,7 +98,7 @@
@Test
fun testPrepareDialogForApp_onlyDefaultChannel() {
- group.channels = listOf(channelDefault)
+ group.addChannel(channelDefault)
controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
setOf(channelDefault), appIcon, clickListener)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index f8b39e8..137842e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -28,7 +28,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -58,8 +57,8 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
import com.android.systemui.statusbar.notification.FeedbackIcon;
-import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import org.junit.Assert;
@@ -260,17 +259,6 @@
}
@Test
- public void setNeedsRedactionFreesViewWhenFalse() throws Exception {
- ExpandableNotificationRow row = mNotificationTestHelper.createRow(FLAG_CONTENT_VIEW_ALL);
- row.setNeedsRedaction(true);
- row.getPublicLayout().setVisibility(View.GONE);
-
- row.setNeedsRedaction(false);
- TestableLooper.get(this).processAllMessages();
- assertNull(row.getPublicLayout().getContractedChild());
- }
-
- @Test
public void testAboveShelfChangedListenerCalled() throws Exception {
ExpandableNotificationRow row = mNotificationTestHelper.createRow();
AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
index fe2f5f0..6d687a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
@@ -57,7 +57,6 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -84,8 +83,6 @@
private StatusBarNotification mSbn;
@Mock
- private NotificationEntryManager mNotificationEntryManager;
- @Mock
private IStatusBarService mStatusBarService;
@Mock
private NotificationGutsManager mNotificationGutsManager;
@@ -94,7 +91,6 @@
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
mDependency.injectTestDependency(IStatusBarService.class, mStatusBarService);
mDependency.injectTestDependency(NotificationGutsManager.class, mNotificationGutsManager);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
deleted file mode 100644
index b20f95c..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2018 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.statusbar.notification.row;
-
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;
-
-import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.NotificationChannel;
-import android.content.Context;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.View;
-
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Tests for {@link NotificationBlockingHelperManager}.
- */
-@SmallTest
-@FlakyTest
-@org.junit.runner.RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class NotificationBlockingHelperManagerTest extends SysuiTestCase {
- private NotificationBlockingHelperManager mBlockingHelperManager;
-
- private NotificationTestHelper mHelper;
-
- @Mock private NotificationGutsManager mGutsManager;
- @Mock private NotificationEntryManager mEntryManager;
- @Mock private NotificationMenuRow mMenuRow;
- @Mock private NotificationMenuRowPlugin.MenuItem mMenuItem;
- @Mock private GroupMembershipManager mGroupMembershipManager;
-
- @Before
- public void setUp() {
- allowTestableLooperAsMainThread();
- MockitoAnnotations.initMocks(this);
- when(mGutsManager.openGuts(
- any(View.class),
- anyInt(),
- anyInt(),
- any(NotificationMenuRowPlugin.MenuItem.class)))
- .thenReturn(true);
- when(mMenuRow.getLongpressMenuItem(any(Context.class))).thenReturn(mMenuItem);
-
- mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
-
- mBlockingHelperManager = new NotificationBlockingHelperManager(
- mContext, mGutsManager, mEntryManager, mock(MetricsLogger.class),
- mGroupMembershipManager);
- // By default, have the shade visible/expanded.
- mBlockingHelperManager.setNotificationShadeExpanded(1f);
- }
-
- @Test
- public void testDismissCurrentBlockingHelper_nullBlockingHelperRow() {
- // By default, this shouldn't dismiss (no pointers/vars set up!)
- assertFalse(mBlockingHelperManager.dismissCurrentBlockingHelper());
- assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
- }
-
- @Test
- public void testDismissCurrentBlockingHelper_withDetachedBlockingHelperRow() throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- row.setBlockingHelperShowing(true);
- when(row.isAttachedToWindow()).thenReturn(false);
- mBlockingHelperManager.setBlockingHelperRowForTest(row);
-
- assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
- assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-
- verify(mEntryManager, times(0)).updateNotifications(anyString());
- }
-
- @Test
- public void testDismissCurrentBlockingHelper_withAttachedBlockingHelperRow() throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- row.setBlockingHelperShowing(true);
- when(row.isAttachedToWindow()).thenReturn(true);
- mBlockingHelperManager.setBlockingHelperRowForTest(row);
-
- assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
- assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-
- verify(mEntryManager).updateNotifications(anyString());
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_shown() throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- modifyRanking(row.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
-
- assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-
- verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_notShownForMultiChannelGroup() throws Exception {
- ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10);
- int i = 0;
- for (ExpandableNotificationRow childRow : groupRow.getAttachedChildren()) {
- modifyRanking(childRow.getEntry())
- .setChannel(
- new NotificationChannel(
- Integer.toString(i++), "", IMPORTANCE_DEFAULT))
- .build();
- }
-
- modifyRanking(groupRow.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
-
- assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(groupRow, mMenuRow));
-
- verify(mGutsManager, never()).openGuts(groupRow, 0, 0, mMenuItem);
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_shownForLargeGroup() throws Exception {
- ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10);
- modifyRanking(groupRow.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
-
- assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(groupRow, mMenuRow));
-
- verify(mGutsManager).openGuts(groupRow, 0, 0, mMenuItem);
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_shownForOnlyChildNotification()
- throws Exception {
- ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(1);
- // Explicitly get the children container & call getViewAtPosition on it instead of the row
- // as other factors such as view expansion may cause us to get the parent row back instead
- // of the child row.
- ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0);
- modifyRanking(childRow.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
- assertFalse(childRow.getIsNonblockable());
-
- when(mGroupMembershipManager.isOnlyChildInGroup(childRow.getEntry())).thenReturn(true);
- assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow));
-
- verify(mGutsManager).openGuts(childRow, 0, 0, mMenuItem);
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_notShownDueToNeutralUserSentiment() throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- modifyRanking(row.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEUTRAL)
- .build();
-
- assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_notShownDueToPositiveUserSentiment()
- throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- modifyRanking(row.getEntry())
- .setUserSentiment(USER_SENTIMENT_POSITIVE)
- .build();
-
- assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_notShownDueToShadeVisibility() throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- modifyRanking(row.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
- // Hide the shade
- mBlockingHelperManager.setNotificationShadeExpanded(0f);
-
- assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_notShownDueToNonblockability() throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- when(row.getIsNonblockable()).thenReturn(true);
- modifyRanking(row.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
-
- assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_notShownAsNotificationIsInMultipleChildGroup()
- throws Exception {
- ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(2);
- // Explicitly get the children container & call getViewAtPosition on it instead of the row
- // as other factors such as view expansion may cause us to get the parent row back instead
- // of the child row.
- ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0);
- modifyRanking(childRow.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
-
- assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow));
- }
-
- @Test
- public void testBlockingHelperShowAndDismiss() throws Exception{
- ExpandableNotificationRow row = createBlockableRowSpy();
- modifyRanking(row.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
- when(row.isAttachedToWindow()).thenReturn(true);
-
- // Show check
- assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-
- verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
-
- // Dismiss check
- assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
- assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-
- verify(mEntryManager).updateNotifications(anyString());
- }
-
- @Test
- public void testNonBlockable_package() {
- mBlockingHelperManager.setNonBlockablePkgs(new String[] {"banana", "strawberry:pie"});
-
- assertFalse(mBlockingHelperManager.isNonblockable("orange", "pie"));
-
- assertTrue(mBlockingHelperManager.isNonblockable("banana", "pie"));
- }
-
- @Test
- public void testNonBlockable_channel() {
- mBlockingHelperManager.setNonBlockablePkgs(new String[] {"banana", "strawberry:pie"});
-
- assertFalse(mBlockingHelperManager.isNonblockable("strawberry", "shortcake"));
-
- assertTrue(mBlockingHelperManager.isNonblockable("strawberry", "pie"));
- }
-
- private ExpandableNotificationRow createBlockableRowSpy() throws Exception {
- ExpandableNotificationRow row = spy(mHelper.createRow());
- when(row.getIsNonblockable()).thenReturn(false);
- return row;
- }
-
- private ExpandableNotificationRow createBlockableGroupRowSpy(int numChildren) throws Exception {
- ExpandableNotificationRow row = spy(mHelper.createGroup(numChildren));
- when(row.getIsNonblockable()).thenReturn(false);
- return row;
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 66821dd..9abdeb9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -48,6 +48,7 @@
import android.widget.RemoteViews;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
import com.android.systemui.TestableDependency;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake;
@@ -75,6 +76,7 @@
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.HeadsUpManagerLogger;
import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
@@ -144,7 +146,10 @@
mock(KeyguardBypassController.class),
mock(GroupMembershipManager.class),
mock(VisualStabilityProvider.class),
- mock(ConfigurationControllerImpl.class)
+ mock(ConfigurationControllerImpl.class),
+ new Handler(mTestLooper.getLooper()),
+ mock(AccessibilityManagerWrapper.class),
+ mock(UiEventLogger.class)
);
mHeadsUpManager.mHandler.removeCallbacksAndMessages(null);
mHeadsUpManager.mHandler = new Handler(mTestLooper.getLooper());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 1460e04..8be9eb5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -34,7 +34,6 @@
import android.content.res.Resources;
import android.metrics.LogMaker;
import android.testing.AndroidTestingRunner;
-import android.view.LayoutInflater;
import androidx.test.filters.SmallTest;
@@ -42,11 +41,9 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
@@ -61,12 +58,8 @@
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotifPipelineFlags;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
-import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
@@ -112,7 +105,6 @@
@Mock private KeyguardMediaController mKeyguardMediaController;
@Mock private SysuiStatusBarStateController mSysuiStatusBarStateController;
@Mock private KeyguardBypassController mKeyguardBypassController;
- @Mock private SysuiColorExtractor mColorExtractor;
@Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
@Mock private MetricsLogger mMetricsLogger;
@Mock private DumpManager mDumpManager;
@@ -122,19 +114,13 @@
@Mock private NotificationSwipeHelper mNotificationSwipeHelper;
@Mock private CentralSurfaces mCentralSurfaces;
@Mock private ScrimController mScrimController;
- @Mock private NotificationGroupManagerLegacy mGroupManagerLegacy;
@Mock private GroupExpansionManager mGroupExpansionManager;
@Mock private SectionHeaderController mSilentHeaderController;
- @Mock private NotifPipelineFlags mNotifPipelineFlags;
@Mock private NotifPipeline mNotifPipeline;
@Mock private NotifCollection mNotifCollection;
- @Mock private NotificationEntryManager mEntryManager;
- @Mock private IStatusBarService mIStatusBarService;
@Mock private UiEventLogger mUiEventLogger;
@Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
- @Mock private LayoutInflater mLayoutInflater;
@Mock private NotificationRemoteInputManager mRemoteInputManager;
- @Mock private VisualStabilityManager mVisualStabilityManager;
@Mock private ShadeController mShadeController;
@Mock private InteractionJankMonitor mJankMonitor;
@Mock private StackStateLogger mStackLogger;
@@ -176,12 +162,10 @@
mNotificationSwipeHelperBuilder,
mCentralSurfaces,
mScrimController,
- mGroupManagerLegacy,
mGroupExpansionManager,
mSilentHeaderController,
mNotifPipeline,
mNotifCollection,
- mEntryManager,
mLockscreenShadeTransitionController,
mShadeTransitionController,
mUiEventLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 8fd6842..35d2363b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -3,19 +3,21 @@
import android.annotation.DimenRes
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
+import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.ShadeInterpolation.getContentAlpha
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.EmptyShadeView
+import com.android.systemui.statusbar.NotificationShelf
+import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
-import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.BypassController
-import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.google.common.truth.Truth.assertThat
+import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
-import junit.framework.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.mock
@@ -26,17 +28,20 @@
private val hostView = FrameLayout(context)
private val stackScrollAlgorithm = StackScrollAlgorithm(context, hostView)
- private val expandableViewState = ExpandableViewState()
private val notificationRow = mock(ExpandableNotificationRow::class.java)
private val dumpManager = mock(DumpManager::class.java)
private val mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager::class.java)
+ private val notificationShelf = mock(NotificationShelf::class.java)
+ private val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply {
+ layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100)
+ }
private val ambientState = AmbientState(
- context,
- dumpManager,
- SectionProvider { _, _ -> false },
- BypassController { false },
- mStatusBarKeyguardViewManager
+ context,
+ dumpManager,
+ /* sectionProvider */ { _, _ -> false },
+ /* bypassController */ { false },
+ mStatusBarKeyguardViewManager
)
private val testableResources = mContext.orCreateTestableResources
@@ -49,7 +54,9 @@
@Before
fun setUp() {
- whenever(notificationRow.viewState).thenReturn(expandableViewState)
+ whenever(notificationShelf.viewState).thenReturn(ExpandableViewState())
+ whenever(notificationRow.viewState).thenReturn(ExpandableViewState())
+
hostView.addView(notificationRow)
}
@@ -60,7 +67,8 @@
stackScrollAlgorithm.resetViewStates(ambientState, 0)
- assertThat(expandableViewState.yTranslation).isEqualTo(stackScrollAlgorithm.mHeadsUpInset)
+ assertThat(notificationRow.viewState.yTranslation)
+ .isEqualTo(stackScrollAlgorithm.mHeadsUpInset)
}
@Test
@@ -75,15 +83,12 @@
stackScrollAlgorithm.resetViewStates(ambientState, 0)
// top margin presence should decrease heads up translation up to minHeadsUpTranslation
- assertThat(expandableViewState.yTranslation).isEqualTo(minHeadsUpTranslation)
+ assertThat(notificationRow.viewState.yTranslation).isEqualTo(minHeadsUpTranslation)
}
@Test
fun resetViewStates_emptyShadeView_isCenteredVertically() {
stackScrollAlgorithm.initView(context)
- val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply {
- layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100)
- }
hostView.removeAllViews()
hostView.addView(emptyShadeView)
ambientState.layoutMaxHeight = 1280
@@ -98,6 +103,121 @@
}
@Test
+ fun resetViewStates_hunGoingToShade_viewBecomesOpaque() {
+ whenever(notificationRow.isAboveShelf).thenReturn(true)
+ ambientState.isShadeExpanded = true
+ ambientState.trackedHeadsUpRow = notificationRow
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(notificationRow.viewState.alpha).isEqualTo(1f)
+ }
+
+ @Test
+ fun resetViewStates_isExpansionChanging_viewBecomesTransparent() {
+ whenever(mStatusBarKeyguardViewManager.isBouncerInTransit).thenReturn(false)
+ ambientState.isExpansionChanging = true
+ ambientState.expansionFraction = 0.25f
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ val expected = getContentAlpha(0.25f)
+ assertThat(notificationRow.viewState.alpha).isEqualTo(expected)
+ }
+
+ @Test
+ fun resetViewStates_isExpansionChangingWhileBouncerInTransit_viewBecomesTransparent() {
+ whenever(mStatusBarKeyguardViewManager.isBouncerInTransit).thenReturn(true)
+ ambientState.isExpansionChanging = true
+ ambientState.expansionFraction = 0.25f
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ val expected = aboutToShowBouncerProgress(0.25f)
+ assertThat(notificationRow.viewState.alpha).isEqualTo(expected)
+ }
+
+ @Test
+ fun resetViewStates_isOnKeyguard_viewBecomesTransparent() {
+ ambientState.setStatusBarState(StatusBarState.KEYGUARD)
+ ambientState.hideAmount = 0.25f
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(notificationRow.viewState.alpha).isEqualTo(1f - ambientState.hideAmount)
+ }
+
+ @Test
+ fun resetViewStates_isOnKeyguard_emptyShadeViewBecomesTransparent() {
+ ambientState.setStatusBarState(StatusBarState.KEYGUARD)
+ ambientState.fractionToShade = 0.25f
+ stackScrollAlgorithm.initView(context)
+ hostView.removeAllViews()
+ hostView.addView(emptyShadeView)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ val expected = getContentAlpha(ambientState.fractionToShade)
+ assertThat(emptyShadeView.viewState.alpha).isEqualTo(expected)
+ }
+
+ @Test
+ fun resetViewStates_isOnKeyguard_emptyShadeViewBecomesOpaque() {
+ ambientState.setStatusBarState(StatusBarState.SHADE)
+ ambientState.fractionToShade = 0.25f
+ stackScrollAlgorithm.initView(context)
+ hostView.removeAllViews()
+ hostView.addView(emptyShadeView)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(emptyShadeView.viewState.alpha).isEqualTo(1f)
+ }
+
+ @Test
+ fun resetViewStates_hiddenShelf_viewAlphaDoesNotChange() {
+ val expected = notificationShelf.viewState.alpha
+ notificationShelf.viewState.hidden = true
+ ambientState.shelf = notificationShelf
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(notificationShelf.viewState.alpha).isEqualTo(expected)
+ }
+
+ @Test
+ fun resetViewStates_shelfTopLessThanViewTop_hidesView() {
+ notificationRow.viewState.yTranslation = 10f
+ notificationShelf.viewState.yTranslation = 0.9f
+ notificationShelf.viewState.hidden = false
+ ambientState.shelf = notificationShelf
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(notificationRow.viewState.alpha).isEqualTo(0f)
+ }
+
+ @Test
+ fun resetViewStates_shelfTopGreaterOrEqualThanViewTop_viewAlphaDoesNotChange() {
+ val expected = notificationRow.viewState.alpha
+ notificationRow.viewState.yTranslation = 10f
+ notificationShelf.viewState.yTranslation = 10f
+ notificationShelf.viewState.hidden = false
+ ambientState.shelf = notificationShelf
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(notificationRow.viewState.alpha).isEqualTo(expected)
+ }
+
+ @Test
fun getGapForLocation_onLockscreen_returnsSmallGap() {
val gap = stackScrollAlgorithm.getGapForLocation(
/* fractionToShade= */ 0f, /* onKeyguard= */ true)
@@ -267,7 +387,6 @@
assertEquals(10f, expandableViewState.yTranslation)
}
-
@Test
fun clampHunToTop_viewYFarAboveVisibleStack_heightCollapsed() {
val expandableViewState = ExpandableViewState()
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 d2680eb5..a6808e0 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
@@ -22,6 +22,8 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -395,15 +397,19 @@
}
@Test
- public void onUdfpsConsecutivelyFailedTwoTimes_showBouncer() {
+ public void onUdfpsConsecutivelyFailedThreeTimes_showBouncer() {
// GIVEN UDFPS is supported
when(mUpdateMonitor.isUdfpsSupported()).thenReturn(true);
- // WHEN udfps fails once - then don't show the bouncer
+ // WHEN udfps fails once - then don't show the bouncer yet
mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
- // WHEN udfps fails the second time
+ // WHEN udfps fails the second time - then don't show the bouncer yet
+ mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
+ verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
+
+ // WHEN udpfs fails the third time
mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
// THEN show the bouncer
@@ -427,8 +433,8 @@
}
@Test
- public void onFPFailureNoHaptics_notDeviceInteractive_showBouncer() {
- // GIVEN no vibrator and the screen is off
+ public void onFPFailureNoHaptics_notInteractive_showLockScreen() {
+ // GIVEN no vibrator and device is dreaming
when(mVibratorHelper.hasVibrator()).thenReturn(false);
when(mUpdateMonitor.isDeviceInteractive()).thenReturn(false);
when(mUpdateMonitor.isDreaming()).thenReturn(false);
@@ -436,15 +442,12 @@
// WHEN FP fails
mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
- // after device is finished waking up
- mBiometricUnlockController.mWakefulnessObserver.onFinishedWakingUp();
-
- // THEN show the bouncer
- verify(mStatusBarKeyguardViewManager).showBouncer(true);
+ // THEN wakeup the device
+ verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
}
@Test
- public void onFPFailureNoHaptics_dreaming_showBouncer() {
+ public void onFPFailureNoHaptics_dreaming_showLockScreen() {
// GIVEN no vibrator and device is dreaming
when(mVibratorHelper.hasVibrator()).thenReturn(false);
when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
@@ -453,7 +456,7 @@
// WHEN FP fails
mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
- // THEN show the bouncer
- verify(mStatusBarKeyguardViewManager).showBouncer(true);
+ // THEN wakeup the device
+ verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index a0f7087..14b7471 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -127,13 +127,11 @@
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider;
@@ -209,7 +207,6 @@
@Mock private DozeScrimController mDozeScrimController;
@Mock private Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
@Mock private BiometricUnlockController mBiometricUnlockController;
- @Mock private VisualStabilityManager mVisualStabilityManager;
@Mock private NotificationListener mNotificationListener;
@Mock private KeyguardViewMediator mKeyguardViewMediator;
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@@ -225,7 +222,6 @@
@Mock private NotificationShadeWindowView mNotificationShadeWindowView;
@Mock private BroadcastDispatcher mBroadcastDispatcher;
@Mock private AssistManager mAssistManager;
- @Mock private NotificationEntryManager mNotificationEntryManager;
@Mock private NotificationGutsManager mNotificationGutsManager;
@Mock private NotificationMediaManager mNotificationMediaManager;
@Mock private NavigationBarController mNavigationBarController;
@@ -399,7 +395,6 @@
new FalsingManagerFake(),
new FalsingCollectorFake(),
mBroadcastDispatcher,
- mNotificationEntryManager,
mNotificationGutsManager,
notificationLogger,
mNotificationInterruptStateProvider,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
index 2ab2172..e252401 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -23,11 +23,13 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
+import com.android.internal.logging.UiEventLogger;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.AlertingNotificationManagerTest;
@@ -64,6 +66,8 @@
@Mock private StatusBarStateController mStatusBarStateController;
@Mock private KeyguardBypassController mBypassController;
@Mock private ConfigurationControllerImpl mConfigurationController;
+ @Mock private AccessibilityManagerWrapper mAccessibilityManagerWrapper;
+ @Mock private UiEventLogger mUiEventLogger;
private boolean mLivesPastNormalTime;
private static final class TestableHeadsUpManagerPhone extends HeadsUpManagerPhone {
@@ -74,7 +78,10 @@
VisualStabilityProvider visualStabilityProvider,
StatusBarStateController statusBarStateController,
KeyguardBypassController keyguardBypassController,
- ConfigurationController configurationController
+ ConfigurationController configurationController,
+ Handler handler,
+ AccessibilityManagerWrapper accessibilityManagerWrapper,
+ UiEventLogger uiEventLogger
) {
super(
context,
@@ -83,7 +90,10 @@
keyguardBypassController,
groupManager,
visualStabilityProvider,
- configurationController
+ configurationController,
+ handler,
+ accessibilityManagerWrapper,
+ uiEventLogger
);
mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
@@ -103,6 +113,8 @@
when(mVSProvider.isReorderingAllowed()).thenReturn(true);
mDependency.injectMockDependency(NotificationShadeWindowController.class);
mDependency.injectMockDependency(ConfigurationController.class);
+ super.setUp();
+
mHeadsUpManager = new TestableHeadsUpManagerPhone(
mContext,
mHeadsUpManagerLogger,
@@ -110,11 +122,11 @@
mVSProvider,
mStatusBarStateController,
mBypassController,
- mConfigurationController
+ mConfigurationController,
+ mTestHandler,
+ mAccessibilityManagerWrapper,
+ mUiEventLogger
);
- super.setUp();
- mHeadsUpManager.mHandler.removeCallbacksAndMessages(null);
- mHeadsUpManager.mHandler = mTestHandler;
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
index 6cf1a12..ba5f503 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
@@ -17,6 +17,9 @@
package com.android.systemui.statusbar.phone;
+import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
+import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
+
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
@@ -49,6 +52,7 @@
import com.android.systemui.battery.BatteryMeterViewController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.NotificationPanelViewController;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserInfoTracker;
@@ -118,6 +122,7 @@
@Mock
private StatusBarUserInfoTracker mStatusBarUserInfoTracker;
@Mock private SecureSettings mSecureSettings;
+ @Mock private CommandQueue mCommandQueue;
private TestNotificationPanelViewStateProvider mNotificationPanelViewStateProvider;
private KeyguardStatusBarView mKeyguardStatusBarView;
@@ -137,6 +142,7 @@
mKeyguardStatusBarView =
spy((KeyguardStatusBarView) LayoutInflater.from(mContext)
.inflate(R.layout.keyguard_status_bar, null));
+ when(mKeyguardStatusBarView.getDisplay()).thenReturn(mContext.getDisplay());
});
mController = createController();
@@ -165,6 +171,7 @@
mStatusBarUserSwitcherController,
mStatusBarUserInfoTracker,
mSecureSettings,
+ mCommandQueue,
mFakeExecutor
);
}
@@ -176,6 +183,7 @@
verify(mConfigurationController).addCallback(any());
verify(mAnimationScheduler).addCallback(any());
verify(mUserInfoController).addCallback(any());
+ verify(mCommandQueue).addCallback(any());
verify(mStatusBarIconController).addIconGroup(any());
verify(mUserManager).isUserSwitcherEnabled(anyBoolean());
}
@@ -214,6 +222,7 @@
verify(mConfigurationController).removeCallback(any());
verify(mAnimationScheduler).removeCallback(any());
verify(mUserInfoController).removeCallback(any());
+ verify(mCommandQueue).removeCallback(any());
verify(mStatusBarIconController).removeIconGroup(any());
}
@@ -280,6 +289,17 @@
}
@Test
+ public void updateViewState_paramVisibleButIsDisabled_viewIsInvisible() {
+ mController.onViewAttached();
+ setDisableSystemIcons(true);
+
+ mController.updateViewState(1f, View.VISIBLE);
+
+ // Since we're disabled, we stay invisible
+ assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE);
+ }
+
+ @Test
public void updateViewState_notKeyguardState_nothingUpdated() {
mController.onViewAttached();
updateStateToNotKeyguard();
@@ -359,6 +379,50 @@
}
@Test
+ public void updateViewState_disableSystemInfoFalse_viewShown() {
+ mController.onViewAttached();
+ updateStateToKeyguard();
+ setDisableSystemInfo(false);
+
+ mController.updateViewState();
+
+ assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void updateViewState_disableSystemInfoTrue_viewHidden() {
+ mController.onViewAttached();
+ updateStateToKeyguard();
+ setDisableSystemInfo(true);
+
+ mController.updateViewState();
+
+ assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE);
+ }
+
+ @Test
+ public void updateViewState_disableSystemIconsFalse_viewShown() {
+ mController.onViewAttached();
+ updateStateToKeyguard();
+ setDisableSystemIcons(false);
+
+ mController.updateViewState();
+
+ assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void updateViewState_disableSystemIconsTrue_viewHidden() {
+ mController.onViewAttached();
+ updateStateToKeyguard();
+ setDisableSystemIcons(true);
+
+ mController.updateViewState();
+
+ assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE);
+ }
+
+ @Test
public void setAlpha_explicitAlpha_setsExplicitAlpha() {
mController.onViewAttached();
updateStateToKeyguard();
@@ -485,6 +549,19 @@
callback.onStateChanged(state);
}
+ @Test
+ public void animateKeyguardStatusBarIn_isDisabled_viewStillHidden() {
+ mController.onViewAttached();
+ updateStateToKeyguard();
+ setDisableSystemInfo(true);
+ assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE);
+
+ mController.animateKeyguardStatusBarIn();
+
+ // Since we're disabled, we don't actually animate in and stay invisible
+ assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE);
+ }
+
/**
* Calls {@link com.android.keyguard.KeyguardUpdateMonitorCallback#onFinishedGoingToSleep(int)}
* to ensure values are updated properly.
@@ -498,6 +575,25 @@
callback.onFinishedGoingToSleep(0);
}
+ private void setDisableSystemInfo(boolean disabled) {
+ CommandQueue.Callbacks callback = getCommandQueueCallback();
+ int disabled1 = disabled ? DISABLE_SYSTEM_INFO : 0;
+ callback.disable(mContext.getDisplayId(), disabled1, 0, false);
+ }
+
+ private void setDisableSystemIcons(boolean disabled) {
+ CommandQueue.Callbacks callback = getCommandQueueCallback();
+ int disabled2 = disabled ? DISABLE2_SYSTEM_ICONS : 0;
+ callback.disable(mContext.getDisplayId(), 0, disabled2, false);
+ }
+
+ private CommandQueue.Callbacks getCommandQueueCallback() {
+ ArgumentCaptor<CommandQueue.Callbacks> captor =
+ ArgumentCaptor.forClass(CommandQueue.Callbacks.class);
+ verify(mCommandQueue).addCallback(captor.capture());
+ return captor.getValue();
+ }
+
private static class TestNotificationPanelViewStateProvider
implements NotificationPanelViewController.NotificationPanelViewStateProvider {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
new file mode 100644
index 0000000..64dee95
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.app.AlarmManager
+import android.app.IActivityManager
+import android.app.admin.DevicePolicyManager
+import android.content.SharedPreferences
+import android.os.UserManager
+import android.telecom.TelecomManager
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.privacy.PrivacyItemController
+import com.android.systemui.privacy.logging.PrivacyLogger
+import com.android.systemui.screenrecord.RecordingController
+import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.statusbar.policy.BluetoothController
+import com.android.systemui.statusbar.policy.CastController
+import com.android.systemui.statusbar.policy.DataSaverController
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.HotspotController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.statusbar.policy.LocationController
+import com.android.systemui.statusbar.policy.NextAlarmController
+import com.android.systemui.statusbar.policy.RotationLockController
+import com.android.systemui.statusbar.policy.SensorPrivacyController
+import com.android.systemui.statusbar.policy.UserInfoController
+import com.android.systemui.statusbar.policy.ZenModeController
+import com.android.systemui.util.RingerModeTracker
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.time.DateFormatUtil
+import com.android.systemui.util.time.FakeSystemClock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Answers
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+@SmallTest
+class PhoneStatusBarPolicyTest : SysuiTestCase() {
+
+ companion object {
+ private const val ALARM_SLOT = "alarm"
+ }
+
+ @Mock
+ private lateinit var iconController: StatusBarIconController
+ @Mock
+ private lateinit var commandQueue: CommandQueue
+ @Mock
+ private lateinit var broadcastDispatcher: BroadcastDispatcher
+ @Mock
+ private lateinit var castController: CastController
+ @Mock
+ private lateinit var hotspotController: HotspotController
+ @Mock
+ private lateinit var bluetoothController: BluetoothController
+ @Mock
+ private lateinit var nextAlarmController: NextAlarmController
+ @Mock
+ private lateinit var userInfoController: UserInfoController
+ @Mock
+ private lateinit var rotationLockController: RotationLockController
+ @Mock
+ private lateinit var dataSaverController: DataSaverController
+ @Mock
+ private lateinit var zenModeController: ZenModeController
+ @Mock
+ private lateinit var deviceProvisionedController: DeviceProvisionedController
+ @Mock
+ private lateinit var keyguardStateController: KeyguardStateController
+ @Mock
+ private lateinit var locationController: LocationController
+ @Mock
+ private lateinit var sensorPrivacyController: SensorPrivacyController
+ @Mock
+ private lateinit var iActivityManager: IActivityManager
+ @Mock
+ private lateinit var alarmManager: AlarmManager
+ @Mock
+ private lateinit var userManager: UserManager
+ @Mock
+ private lateinit var devicePolicyManager: DevicePolicyManager
+ @Mock
+ private lateinit var recordingController: RecordingController
+ @Mock
+ private lateinit var telecomManager: TelecomManager
+ @Mock
+ private lateinit var sharedPreferences: SharedPreferences
+ @Mock
+ private lateinit var dateFormatUtil: DateFormatUtil
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private lateinit var ringerModeTracker: RingerModeTracker
+ @Mock
+ private lateinit var privacyItemController: PrivacyItemController
+ @Mock
+ private lateinit var privacyLogger: PrivacyLogger
+ @Captor
+ private lateinit var alarmCallbackCaptor:
+ ArgumentCaptor<NextAlarmController.NextAlarmChangeCallback>
+
+ private lateinit var executor: FakeExecutor
+ private lateinit var statusBarPolicy: PhoneStatusBarPolicy
+ private lateinit var testableLooper: TestableLooper
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ executor = FakeExecutor(FakeSystemClock())
+ testableLooper = TestableLooper.get(this)
+ context.orCreateTestableResources.addOverride(
+ com.android.internal.R.string.status_bar_alarm_clock,
+ ALARM_SLOT
+ )
+ statusBarPolicy = createStatusBarPolicy()
+ }
+
+ @Test
+ fun testDeviceNotProvisioned_alarmIconNotShown() {
+ val alarmInfo = createAlarmInfo()
+
+ whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(false)
+ statusBarPolicy.init()
+ verify(nextAlarmController).addCallback(capture(alarmCallbackCaptor))
+
+ whenever(alarmManager.getNextAlarmClock(anyInt())).thenReturn(alarmInfo)
+
+ alarmCallbackCaptor.value.onNextAlarmChanged(alarmInfo)
+ verify(iconController, never()).setIconVisibility(ALARM_SLOT, true)
+ }
+
+ @Test
+ fun testDeviceProvisioned_alarmIconShown() {
+ val alarmInfo = createAlarmInfo()
+
+ whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(true)
+ statusBarPolicy.init()
+
+ verify(nextAlarmController).addCallback(capture(alarmCallbackCaptor))
+ whenever(alarmManager.getNextAlarmClock(anyInt())).thenReturn(alarmInfo)
+
+ alarmCallbackCaptor.value.onNextAlarmChanged(alarmInfo)
+ verify(iconController).setIconVisibility(ALARM_SLOT, true)
+ }
+
+ @Test
+ fun testDeviceProvisionedChanged_alarmIconShownAfterCurrentUserSetup() {
+ val alarmInfo = createAlarmInfo()
+
+ whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(false)
+ statusBarPolicy.init()
+
+ verify(nextAlarmController).addCallback(capture(alarmCallbackCaptor))
+ whenever(alarmManager.getNextAlarmClock(anyInt())).thenReturn(alarmInfo)
+
+ alarmCallbackCaptor.value.onNextAlarmChanged(alarmInfo)
+ verify(iconController, never()).setIconVisibility(ALARM_SLOT, true)
+
+ whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(true)
+ statusBarPolicy.onUserSetupChanged()
+ verify(iconController).setIconVisibility(ALARM_SLOT, true)
+ }
+
+ private fun createAlarmInfo(): AlarmManager.AlarmClockInfo {
+ return AlarmManager.AlarmClockInfo(10L, null)
+ }
+
+ private fun createStatusBarPolicy(): PhoneStatusBarPolicy {
+ return PhoneStatusBarPolicy(
+ iconController,
+ commandQueue,
+ broadcastDispatcher,
+ executor,
+ testableLooper.looper,
+ context.resources,
+ castController,
+ hotspotController,
+ bluetoothController,
+ nextAlarmController,
+ userInfoController,
+ rotationLockController,
+ dataSaverController,
+ zenModeController,
+ deviceProvisionedController,
+ keyguardStateController,
+ locationController,
+ sensorPrivacyController,
+ iActivityManager,
+ alarmManager,
+ userManager,
+ devicePolicyManager,
+ recordingController,
+ telecomManager,
+ /* displayId = */ 0,
+ sharedPreferences,
+ dateFormatUtil,
+ ringerModeTracker,
+ privacyItemController,
+ privacyLogger
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 9892448..a61fba5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -26,22 +26,22 @@
import androidx.test.platform.app.InstrumentationRegistry
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
-import com.android.systemui.shade.PanelViewController
+import com.android.systemui.shade.NotificationPanelViewController
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.unfold.SysUIUnfoldComponent
import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
-import com.android.systemui.util.view.ViewUtil
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.view.ViewUtil
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentCaptor
import org.mockito.Mock
-import org.mockito.Mockito.spy
-import org.mockito.Mockito.mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.util.Optional
@@ -52,7 +52,7 @@
private val touchEventHandler = TestTouchEventHandler()
@Mock
- private lateinit var panelViewController: PanelViewController
+ private lateinit var notificationPanelViewController: NotificationPanelViewController
@Mock
private lateinit var panelView: ViewGroup
@Mock
@@ -76,7 +76,7 @@
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- `when`(panelViewController.view).thenReturn(panelView)
+ `when`(notificationPanelViewController.view).thenReturn(panelView)
`when`(sysuiUnfoldComponent.getStatusBarMoveFromCenterAnimationController())
.thenReturn(moveFromCenterAnimation)
// create the view on main thread as it requires main looper
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
index d6c995b..5aa7f92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
@@ -20,7 +20,7 @@
import android.view.ViewGroup
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.shade.PanelViewController
+import com.android.systemui.shade.NotificationPanelViewController
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -32,7 +32,7 @@
class PhoneStatusBarViewTest : SysuiTestCase() {
@Mock
- private lateinit var panelViewController: PanelViewController
+ private lateinit var notificationPanelViewController: NotificationPanelViewController
@Mock
private lateinit var panelView: ViewGroup
@@ -43,7 +43,7 @@
MockitoAnnotations.initMocks(this)
// TODO(b/197137564): Setting up a panel view and its controller feels unnecessary when
// testing just [PhoneStatusBarView].
- `when`(panelViewController.view).thenReturn(panelView)
+ `when`(notificationPanelViewController.view).thenReturn(panelView)
view = PhoneStatusBarView(mContext, null)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
index a6b7e51..ca98143 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
@@ -58,7 +58,6 @@
@Before
public void setup() {
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
- mDependency.injectMockDependency(DarkIconDispatcher.class);
}
@Test
@@ -75,7 +74,8 @@
layout,
mock(FeatureFlags.class),
mock(StatusBarPipelineFlags.class),
- () -> mock(WifiViewModel.class));
+ () -> mock(WifiViewModel.class),
+ mock(DarkIconDispatcher.class));
testCallOnAdd_forManager(manager);
}
@@ -116,8 +116,10 @@
LinearLayout group,
FeatureFlags featureFlags,
StatusBarPipelineFlags statusBarPipelineFlags,
- Provider<WifiViewModel> wifiViewModelProvider) {
- super(group, featureFlags, statusBarPipelineFlags, wifiViewModelProvider);
+ Provider<WifiViewModel> wifiViewModelProvider,
+ DarkIconDispatcher darkIconDispatcher) {
+ super(group, featureFlags, statusBarPipelineFlags, wifiViewModelProvider,
+ darkIconDispatcher);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index de43a1f..c409857 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -37,7 +37,6 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
-import android.content.Intent;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -67,7 +66,6 @@
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -103,8 +101,6 @@
@Mock
private AssistManager mAssistManager;
@Mock
- private NotificationEntryManager mEntryManager;
- @Mock
private ActivityStarter mActivityStarter;
@Mock
private NotificationClickNotifier mClickNotifier;
@@ -135,8 +131,6 @@
@Mock
private PendingIntent mContentIntent;
@Mock
- private Intent mContentIntentInner;
- @Mock
private OnUserInteractionCallback mOnUserInteractionCallback;
@Mock
private Runnable mFutureDismissalRunnable;
@@ -159,7 +153,6 @@
MockitoAnnotations.initMocks(this);
when(mContentIntent.isActivity()).thenReturn(true);
when(mContentIntent.getCreatorUserHandle()).thenReturn(UserHandle.of(1));
- when(mContentIntent.getIntent()).thenReturn(mContentIntentInner);
NotificationTestHelper notificationTestHelper = new NotificationTestHelper(
mContext,
@@ -374,7 +367,6 @@
eq(entry.getKey()), any(NotificationVisibility.class));
// The content intent should NOT be sent on click.
- verify(mContentIntent).getIntent();
verify(mContentIntent).isActivity();
verifyNoMoreInteractions(mContentIntent);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
index 1ec4de9..c3a7e65 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
@@ -37,7 +37,6 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -55,7 +54,6 @@
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class StatusBarRemoteInputCallbackTest extends SysuiTestCase {
- @Mock private NotificationEntryManager mEntryManager;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private com.android.systemui.shade.ShadeController mShadeController;
@Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
@@ -71,7 +69,6 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
mDependency.injectTestDependency(DeviceProvisionedController.class,
mDeviceProvisionedController);
mDependency.injectTestDependency(ShadeController.class, mShadeController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index 20bf50e..37c8f62 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -333,10 +333,9 @@
}
@Test
- public void disable_isDozingButNoCustomClock_clockAndSystemInfoVisible() {
+ public void disable_isDozing_clockAndSystemInfoVisible() {
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
when(mStatusBarStateController.isDozing()).thenReturn(true);
- when(mNotificationPanelViewController.hasCustomClock()).thenReturn(false);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
@@ -345,10 +344,9 @@
}
@Test
- public void disable_customClockButNotDozing_clockAndSystemInfoVisible() {
+ public void disable_NotDozing_clockAndSystemInfoVisible() {
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
when(mStatusBarStateController.isDozing()).thenReturn(false);
- when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
@@ -357,40 +355,6 @@
}
@Test
- public void disable_dozingAndCustomClock_clockAndSystemInfoHidden() {
- CollapsedStatusBarFragment fragment = resumeAndGetFragment();
- when(mStatusBarStateController.isDozing()).thenReturn(true);
- when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
-
- // Make sure they start out as visible
- assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
- assertEquals(View.VISIBLE, getClockView().getVisibility());
-
- fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
-
- assertEquals(View.INVISIBLE, getEndSideContentView().getVisibility());
- assertEquals(View.GONE, getClockView().getVisibility());
- }
-
- @Test
- public void onDozingChanged_clockAndSystemInfoVisibilitiesUpdated() {
- CollapsedStatusBarFragment fragment = resumeAndGetFragment();
- when(mStatusBarStateController.isDozing()).thenReturn(true);
- when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
-
- // Make sure they start out as visible
- assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
- assertEquals(View.VISIBLE, getClockView().getVisibility());
-
- fragment.onDozingChanged(true);
-
- // When this callback is triggered, we want to make sure the clock and system info
- // visibilities are recalculated. Since dozing=true, they shouldn't be visible.
- assertEquals(View.INVISIBLE, getEndSideContentView().getVisibility());
- assertEquals(View.GONE, getClockView().getVisibility());
- }
-
- @Test
public void disable_headsUpShouldBeVisibleTrue_clockDisabled() {
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
when(mHeadsUpAppearanceController.shouldBeVisible()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt
new file mode 100644
index 0000000..3d29d2b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.wifi.data.model
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel.Active.Companion.MAX_VALID_LEVEL
+import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel.Active.Companion.MIN_VALID_LEVEL
+import org.junit.Test
+
+@SmallTest
+class WifiNetworkModelTest : SysuiTestCase() {
+ @Test
+ fun active_levelsInValidRange_noException() {
+ (MIN_VALID_LEVEL..MAX_VALID_LEVEL).forEach { level ->
+ WifiNetworkModel.Active(NETWORK_ID, level = level)
+ // No assert, just need no crash
+ }
+ }
+
+ @Test
+ fun active_levelNull_noException() {
+ WifiNetworkModel.Active(NETWORK_ID, level = null)
+ // No assert, just need no crash
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun active_levelNegative_exceptionThrown() {
+ WifiNetworkModel.Active(NETWORK_ID, level = MIN_VALID_LEVEL - 1)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun active_levelTooHigh_exceptionThrown() {
+ WifiNetworkModel.Active(NETWORK_ID, level = MAX_VALID_LEVEL + 1)
+ }
+
+ companion object {
+ private const val NETWORK_ID = 2
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
index d0a3808..d070ba0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
@@ -19,6 +19,7 @@
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
+import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.vcn.VcnTransportInfo
@@ -39,11 +40,14 @@
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.Executor
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
@@ -61,20 +65,28 @@
@Mock private lateinit var connectivityManager: ConnectivityManager
@Mock private lateinit var wifiManager: WifiManager
private lateinit var executor: Executor
+ private lateinit var scope: CoroutineScope
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
executor = FakeExecutor(FakeSystemClock())
+ scope = CoroutineScope(IMMEDIATE)
underTest = WifiRepositoryImpl(
connectivityManager,
- wifiManager,
- executor,
logger,
+ executor,
+ scope,
+ wifiManager,
)
}
+ @After
+ fun tearDown() {
+ scope.cancel()
+ }
+
@Test
fun wifiNetwork_initiallyGetsDefault() = runBlocking(IMMEDIATE) {
var latest: WifiNetworkModel? = null
@@ -115,6 +127,61 @@
}
@Test
+ fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() = runBlocking(IMMEDIATE) {
+ var latest: WifiNetworkModel? = null
+ val job = underTest
+ .wifiNetwork
+ .onEach { latest = it }
+ .launchIn(this)
+
+ val wifiInfo = mock<WifiInfo>().apply {
+ whenever(this.ssid).thenReturn(SSID)
+ whenever(this.isPrimary).thenReturn(true)
+ whenever(this.isCarrierMerged).thenReturn(true)
+ }
+
+ getNetworkCallback().onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
+
+ assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
+
+ job.cancel()
+ }
+
+ @Test
+ fun wifiNetwork_notValidated_networkNotValidated() = runBlocking(IMMEDIATE) {
+ var latest: WifiNetworkModel? = null
+ val job = underTest
+ .wifiNetwork
+ .onEach { latest = it }
+ .launchIn(this)
+
+ getNetworkCallback().onCapabilitiesChanged(
+ NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO, isValidated = false)
+ )
+
+ assertThat((latest as WifiNetworkModel.Active).isValidated).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun wifiNetwork_validated_networkValidated() = runBlocking(IMMEDIATE) {
+ var latest: WifiNetworkModel? = null
+ val job = underTest
+ .wifiNetwork
+ .onEach { latest = it }
+ .launchIn(this)
+
+ getNetworkCallback().onCapabilitiesChanged(
+ NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO, isValidated = true)
+ )
+
+ assertThat((latest as WifiNetworkModel.Active).isValidated).isTrue()
+
+ job.cancel()
+ }
+
+ @Test
fun wifiNetwork_nonPrimaryWifiNetworkAdded_flowHasNoNetwork() = runBlocking(IMMEDIATE) {
var latest: WifiNetworkModel? = null
val job = underTest
@@ -282,13 +349,14 @@
.launchIn(this)
val wifiInfo = mock<WifiInfo>().apply {
- whenever(this.ssid).thenReturn(SSID)
- whenever(this.isPrimary).thenReturn(true)
- }
+ whenever(this.ssid).thenReturn(SSID)
+ whenever(this.isPrimary).thenReturn(true)
+ }
// Start with the original network
- getNetworkCallback()
- .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
+ getNetworkCallback().onCapabilitiesChanged(
+ NETWORK, createWifiNetworkCapabilities(wifiInfo, isValidated = true)
+ )
// WHEN we keep the same network ID but change the SSID
val newSsid = "CD"
@@ -297,14 +365,16 @@
whenever(this.isPrimary).thenReturn(true)
}
- getNetworkCallback()
- .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(newWifiInfo))
+ getNetworkCallback().onCapabilitiesChanged(
+ NETWORK, createWifiNetworkCapabilities(newWifiInfo, isValidated = false)
+ )
// THEN we've updated to the new SSID
assertThat(latest is WifiNetworkModel.Active).isTrue()
val latestActive = latest as WifiNetworkModel.Active
assertThat(latestActive.networkId).isEqualTo(NETWORK_ID)
assertThat(latestActive.ssid).isEqualTo(newSsid)
+ assertThat(latestActive.isValidated).isFalse()
job.cancel()
}
@@ -403,13 +473,48 @@
job.cancel()
}
+ /** Regression test for b/244173280. */
+ @Test
+ fun wifiNetwork_multipleSubscribers_newSubscribersGetCurrentValue() = runBlocking(IMMEDIATE) {
+ var latest1: WifiNetworkModel? = null
+ val job1 = underTest
+ .wifiNetwork
+ .onEach { latest1 = it }
+ .launchIn(this)
+
+ getNetworkCallback()
+ .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
+
+ assertThat(latest1 is WifiNetworkModel.Active).isTrue()
+ val latest1Active = latest1 as WifiNetworkModel.Active
+ assertThat(latest1Active.networkId).isEqualTo(NETWORK_ID)
+ assertThat(latest1Active.ssid).isEqualTo(SSID)
+
+ // WHEN we add a second subscriber after having already emitted a value
+ var latest2: WifiNetworkModel? = null
+ val job2 = underTest
+ .wifiNetwork
+ .onEach { latest2 = it }
+ .launchIn(this)
+
+ // THEN the second subscribe receives the already-emitted value
+ assertThat(latest2 is WifiNetworkModel.Active).isTrue()
+ val latest2Active = latest2 as WifiNetworkModel.Active
+ assertThat(latest2Active.networkId).isEqualTo(NETWORK_ID)
+ assertThat(latest2Active.ssid).isEqualTo(SSID)
+
+ job1.cancel()
+ job2.cancel()
+ }
+
@Test
fun wifiActivity_nullWifiManager_receivesDefault() = runBlocking(IMMEDIATE) {
underTest = WifiRepositoryImpl(
- connectivityManager,
- wifiManager = null,
- executor,
- logger,
+ connectivityManager,
+ logger,
+ executor,
+ scope,
+ wifiManager = null,
)
var latest: WifiActivityModel? = null
@@ -501,11 +606,16 @@
return callbackCaptor.value!!
}
- private fun createWifiNetworkCapabilities(wifiInfo: WifiInfo) =
- mock<NetworkCapabilities>().apply {
- whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
- whenever(this.transportInfo).thenReturn(wifiInfo)
+ private fun createWifiNetworkCapabilities(
+ wifiInfo: WifiInfo,
+ isValidated: Boolean = true,
+ ): NetworkCapabilities {
+ return mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ whenever(it.transportInfo).thenReturn(wifiInfo)
+ whenever(it.hasCapability(NET_CAPABILITY_VALIDATED)).thenReturn(isValidated)
}
+ }
private companion object {
const val NETWORK_ID = 45
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
index 5f1b1db..9d8b4bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
@@ -126,6 +126,38 @@
}
@Test
+ fun hasActivityIn_inactiveNetwork_outputsFalse() = runBlocking(IMMEDIATE) {
+ repository.setWifiNetwork(WifiNetworkModel.Inactive)
+ repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = true))
+
+ var latest: Boolean? = null
+ val job = underTest
+ .hasActivityIn
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun hasActivityIn_carrierMergedNetwork_outputsFalse() = runBlocking(IMMEDIATE) {
+ repository.setWifiNetwork(WifiNetworkModel.CarrierMerged)
+ repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = true))
+
+ var latest: Boolean? = null
+ val job = underTest
+ .hasActivityIn
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
fun hasActivityIn_multipleChanges_multipleOutputChanges() = runBlocking(IMMEDIATE) {
repository.setWifiNetwork(VALID_WIFI_NETWORK_MODEL)
@@ -159,6 +191,28 @@
job.cancel()
}
+ @Test
+ fun wifiNetwork_matchesRepoWifiNetwork() = runBlocking(IMMEDIATE) {
+ val wifiNetwork = WifiNetworkModel.Active(
+ networkId = 45,
+ isValidated = true,
+ level = 3,
+ ssid = "AB",
+ passpointProviderFriendlyName = "friendly"
+ )
+ repository.setWifiNetwork(wifiNetwork)
+
+ var latest: WifiNetworkModel? = null
+ val job = underTest
+ .wifiNetwork
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isEqualTo(wifiNetwork)
+
+ job.cancel()
+ }
+
companion object {
val VALID_WIFI_NETWORK_MODEL = WifiNetworkModel.Active(networkId = 1, ssid = "AB")
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
index c790734..f0a775b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
@@ -18,6 +18,9 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS
+import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS
+import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiActivityModel
@@ -62,14 +65,103 @@
logger,
interactor
)
-
- // Set up with a valid SSID
- repository.setWifiNetwork(WifiNetworkModel.Active(networkId = 1, ssid = "AB"))
}
@Test
- fun activityInVisible_showActivityConfigFalse_receivesFalse() = runBlocking(IMMEDIATE) {
+ fun wifiIconResId_inactiveNetwork_outputsNoNetworkIcon() = runBlocking(IMMEDIATE) {
+ repository.setWifiNetwork(WifiNetworkModel.Inactive)
+
+ var latest: Int? = null
+ val job = underTest
+ .wifiIconResId
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isEqualTo(WIFI_NO_NETWORK)
+
+ job.cancel()
+ }
+
+ @Test
+ fun wifiIconResId_carrierMergedNetwork_outputsNull() = runBlocking(IMMEDIATE) {
+ repository.setWifiNetwork(WifiNetworkModel.CarrierMerged)
+
+ var latest: Int? = null
+ val job = underTest
+ .wifiIconResId
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isNull()
+
+ job.cancel()
+ }
+
+ @Test
+ fun wifiIconResId_isActiveNullLevel_outputsNull() = runBlocking(IMMEDIATE) {
+ repository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, level = null))
+
+ var latest: Int? = null
+ val job = underTest
+ .wifiIconResId
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isNull()
+
+ job.cancel()
+ }
+
+ @Test
+ fun wifiIconResId_isActiveAndValidated_level1_outputsFull1Icon() = runBlocking(IMMEDIATE) {
+ val level = 1
+
+ repository.setWifiNetwork(
+ WifiNetworkModel.Active(
+ NETWORK_ID,
+ isValidated = true,
+ level = level
+ )
+ )
+
+ var latest: Int? = null
+ val job = underTest
+ .wifiIconResId
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isEqualTo(WIFI_FULL_ICONS[level])
+
+ job.cancel()
+ }
+
+ @Test
+ fun wifiIconResId_isActiveAndNotValidated_level4_outputsEmpty4Icon() = runBlocking(IMMEDIATE) {
+ val level = 4
+
+ repository.setWifiNetwork(
+ WifiNetworkModel.Active(
+ NETWORK_ID,
+ isValidated = false,
+ level = level
+ )
+ )
+
+ var latest: Int? = null
+ val job = underTest
+ .wifiIconResId
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isEqualTo(WIFI_NO_INTERNET_ICONS[level])
+
+ job.cancel()
+ }
+
+ @Test
+ fun activityInVisible_showActivityConfigFalse_outputsFalse() = runBlocking(IMMEDIATE) {
whenever(constants.shouldShowActivityConfig).thenReturn(false)
+ repository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
var latest: Boolean? = null
val job = underTest
@@ -86,6 +178,7 @@
@Test
fun activityInVisible_showActivityConfigFalse_noUpdatesReceived() = runBlocking(IMMEDIATE) {
whenever(constants.shouldShowActivityConfig).thenReturn(false)
+ repository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
var latest: Boolean? = null
val job = underTest
@@ -104,8 +197,9 @@
}
@Test
- fun activityInVisible_showActivityConfigTrue_receivesUpdate() = runBlocking(IMMEDIATE) {
+ fun activityInVisible_showActivityConfigTrue_outputsUpdate() = runBlocking(IMMEDIATE) {
whenever(constants.shouldShowActivityConfig).thenReturn(true)
+ repository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
var latest: Boolean? = null
val job = underTest
@@ -122,6 +216,11 @@
job.cancel()
}
+
+ companion object {
+ private const val NETWORK_ID = 2
+ private val ACTIVE_VALID_WIFI_NETWORK = WifiNetworkModel.Active(NETWORK_ID, ssid = "AB")
+ }
}
private val IMMEDIATE = Dispatchers.Main.immediate
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
index b8e25ab..9764b8c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
@@ -36,6 +36,7 @@
import android.app.Person;
import android.content.Context;
import android.content.Intent;
+import android.os.Handler;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -62,7 +63,6 @@
private static final int TEST_A11Y_AUTO_DISMISS_TIME = 600;
private static final int TEST_A11Y_TIMEOUT_TIME = 5_000;
- private AccessibilityManagerWrapper mAccessibilityMgr;
private HeadsUpManager mHeadsUpManager;
private boolean mLivesPastNormalTime;
private UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake();
@@ -71,10 +71,15 @@
@Mock private StatusBarNotification mSbn;
@Mock private Notification mNotification;
@Mock private HeadsUpManagerLogger mLogger;
+ @Mock private AccessibilityManagerWrapper mAccessibilityMgr;
private final class TestableHeadsUpManager extends HeadsUpManager {
- TestableHeadsUpManager(Context context, HeadsUpManagerLogger logger) {
- super(context, logger);
+ TestableHeadsUpManager(Context context,
+ HeadsUpManagerLogger logger,
+ Handler handler,
+ AccessibilityManagerWrapper accessibilityManagerWrapper,
+ UiEventLogger uiEventLogger) {
+ super(context, logger, handler, accessibilityManagerWrapper, uiEventLogger);
mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
}
@@ -87,14 +92,11 @@
@Before
public void setUp() {
initMocks(this);
- mAccessibilityMgr = mDependency.injectMockDependency(AccessibilityManagerWrapper.class);
- mDependency.injectTestDependency(UiEventLogger.class, mUiEventLoggerFake);
when(mEntry.getSbn()).thenReturn(mSbn);
when(mSbn.getNotification()).thenReturn(mNotification);
- mHeadsUpManager = new TestableHeadsUpManager(mContext, mLogger);
super.setUp();
- mHeadsUpManager.mHandler.removeCallbacksAndMessages(null);
- mHeadsUpManager.mHandler = mTestHandler;
+ mHeadsUpManager = new TestableHeadsUpManager(mContext, mLogger, mTestHandler,
+ mAccessibilityMgr, mUiEventLoggerFake);
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
index 0dd6cbb7..c3805ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
@@ -28,6 +28,7 @@
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.qs.tiles.UserDetailItemView
+import com.android.systemui.user.data.source.UserRecord
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
@@ -38,8 +39,8 @@
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@@ -186,13 +187,14 @@
}
private fun createUserRecord(isCurrentUser: Boolean, isGuestUser: Boolean) =
- UserSwitcherController.UserRecord(
- userInfo,
- picture,
- isGuestUser,
- isCurrentUser,
- false /* isAddUser */,
- false /* isRestricted */,
- true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ UserRecord(
+ userInfo,
+ picture,
+ isGuestUser,
+ isCurrentUser,
+ false /* isAddUser */,
+ false /* isRestricted */,
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */
+ )
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
index 359a780..8dcd4bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
@@ -56,6 +56,7 @@
import com.android.systemui.settings.UserTracker
import com.android.systemui.shade.NotificationShadeWindowView
import com.android.systemui.telephony.TelephonyListenerManager
+import com.android.systemui.user.data.source.UserRecord
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
@@ -235,15 +236,16 @@
@Test
fun testSwitchUser_parentDialogDismissed() {
- val otherUserRecord = UserSwitcherController.UserRecord(
- secondaryUser,
- picture,
- false /* guest */,
- false /* current */,
- false /* isAddUser */,
- false /* isRestricted */,
- true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ val otherUserRecord = UserRecord(
+ secondaryUser,
+ picture,
+ false /* guest */,
+ false /* current */,
+ false /* isAddUser */,
+ false /* isRestricted */,
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(ownerId)
`when`(userTracker.userInfo).thenReturn(ownerInfo)
@@ -255,7 +257,8 @@
@Test
fun testAddGuest_okButtonPressed() {
- val emptyGuestUserRecord = UserSwitcherController.UserRecord(
+ val emptyGuestUserRecord =
+ UserRecord(
null,
null,
true /* guest */,
@@ -263,7 +266,8 @@
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(ownerId)
`when`(userTracker.userInfo).thenReturn(ownerInfo)
@@ -282,7 +286,8 @@
@Test
fun testAddGuest_parentDialogDismissed() {
- val emptyGuestUserRecord = UserSwitcherController.UserRecord(
+ val emptyGuestUserRecord =
+ UserRecord(
null,
null,
true /* guest */,
@@ -290,7 +295,8 @@
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(ownerId)
`when`(userTracker.userInfo).thenReturn(ownerInfo)
@@ -305,7 +311,8 @@
@Test
fun testRemoveGuest_removeButtonPressed_isLogged() {
- val currentGuestUserRecord = UserSwitcherController.UserRecord(
+ val currentGuestUserRecord =
+ UserRecord(
guestInfo,
picture,
true /* guest */,
@@ -313,7 +320,8 @@
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(guestInfo.id)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -331,7 +339,8 @@
@Test
fun testRemoveGuest_removeButtonPressed_dialogDismissed() {
- val currentGuestUserRecord = UserSwitcherController.UserRecord(
+ val currentGuestUserRecord =
+ UserRecord(
guestInfo,
picture,
true /* guest */,
@@ -339,7 +348,8 @@
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(guestInfo.id)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -353,7 +363,8 @@
@Test
fun testRemoveGuest_dialogShowerUsed() {
- val currentGuestUserRecord = UserSwitcherController.UserRecord(
+ val currentGuestUserRecord =
+ UserRecord(
guestInfo,
picture,
true /* guest */,
@@ -361,7 +372,8 @@
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(guestInfo.id)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -376,7 +388,8 @@
@Test
fun testRemoveGuest_cancelButtonPressed_isNotLogged() {
- val currentGuestUserRecord = UserSwitcherController.UserRecord(
+ val currentGuestUserRecord =
+ UserRecord(
guestInfo,
picture,
true /* guest */,
@@ -384,7 +397,8 @@
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(guestId)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -398,7 +412,8 @@
@Test
fun testWipeGuest_startOverButtonPressed_isLogged() {
- val currentGuestUserRecord = UserSwitcherController.UserRecord(
+ val currentGuestUserRecord =
+ UserRecord(
guestInfo,
picture,
true /* guest */,
@@ -406,7 +421,8 @@
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(guestId)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -433,7 +449,8 @@
@Test
fun testWipeGuest_continueButtonPressed_isLogged() {
- val currentGuestUserRecord = UserSwitcherController.UserRecord(
+ val currentGuestUserRecord =
+ UserRecord(
guestInfo,
picture,
true /* guest */,
@@ -441,7 +458,8 @@
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(guestId)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -470,11 +488,13 @@
@Test
fun test_getCurrentUserName_shouldReturnNameOfTheCurrentUser() {
fun addUser(id: Int, name: String, isCurrent: Boolean) {
- userSwitcherController.users.add(UserSwitcherController.UserRecord(
+ userSwitcherController.users.add(
+ UserRecord(
UserInfo(id, name, 0),
null, false, isCurrent, false,
false, false, false
- ))
+ )
+ )
}
val bgUserName = "background_user"
val fgUserName = "foreground_user"
@@ -593,7 +613,7 @@
@Test
fun onUserItemClicked_guest_runsOnBgThread() {
val dialogShower = mock(UserSwitchDialogController.DialogShower::class.java)
- val guestUserRecord = UserSwitcherController.UserRecord(
+ val guestUserRecord = UserRecord(
null,
picture,
true /* guest */,
@@ -601,7 +621,8 @@
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
userSwitcherController.onUserListItemClicked(guestUserRecord, dialogShower)
assertTrue(bgExecutor.numPending() > 0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/SysuiLifecycleTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/SysuiLifecycleTest.java
deleted file mode 100644
index 4f509ea..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/util/SysuiLifecycleTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2018 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.util;
-
-import static androidx.lifecycle.Lifecycle.Event.ON_CREATE;
-import static androidx.lifecycle.Lifecycle.Event.ON_DESTROY;
-import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
-import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
-import static androidx.lifecycle.Lifecycle.Event.ON_START;
-import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
-
-import static com.android.systemui.util.SysuiLifecycle.viewAttachLifecycle;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.testing.TestableLooper.RunWithLooper;
-import android.testing.ViewUtils;
-import android.view.View;
-
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleEventObserver;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWithLooper(setAsMainLooper = true)
-@RunWith(AndroidTestingRunner.class)
-@SmallTest
-public class SysuiLifecycleTest extends SysuiTestCase {
-
- private View mView;
-
- @Before
- public void setUp() {
- mView = new View(mContext);
- }
-
- @After
- public void tearDown() {
- if (mView.isAttachedToWindow()) {
- ViewUtils.detachView(mView);
- TestableLooper.get(this).processAllMessages();
- }
- }
-
- @Test
- public void testAttach() {
- LifecycleEventObserver observer = mock(LifecycleEventObserver.class);
- LifecycleOwner lifecycle = viewAttachLifecycle(mView);
- lifecycle.getLifecycle().addObserver(observer);
-
- ViewUtils.attachView(mView);
- TestableLooper.get(this).processAllMessages();
-
- verify(observer).onStateChanged(eq(lifecycle), eq(ON_CREATE));
- verify(observer).onStateChanged(eq(lifecycle), eq(ON_START));
- verify(observer).onStateChanged(eq(lifecycle), eq(ON_RESUME));
- }
-
- @Test
- public void testDetach() {
- LifecycleEventObserver observer = mock(LifecycleEventObserver.class);
- LifecycleOwner lifecycle = viewAttachLifecycle(mView);
- lifecycle.getLifecycle().addObserver(observer);
-
- ViewUtils.attachView(mView);
- TestableLooper.get(this).processAllMessages();
-
- ViewUtils.detachView(mView);
- TestableLooper.get(this).processAllMessages();
-
- verify(observer).onStateChanged(eq(lifecycle), eq(ON_PAUSE));
- verify(observer).onStateChanged(eq(lifecycle), eq(ON_STOP));
- verify(observer).onStateChanged(eq(lifecycle), eq(ON_DESTROY));
- }
-
- @Test
- public void testStateBeforeAttach() {
- // WHEN a lifecycle is obtained from a view
- LifecycleOwner lifecycle = viewAttachLifecycle(mView);
- // THEN the lifecycle state should be INITIAZED
- assertThat(lifecycle.getLifecycle().getCurrentState()).isEqualTo(
- Lifecycle.State.INITIALIZED);
- }
-
- @Test
- public void testStateAfterAttach() {
- // WHEN a lifecycle is obtained from a view
- LifecycleOwner lifecycle = viewAttachLifecycle(mView);
- // AND the view is attached
- ViewUtils.attachView(mView);
- TestableLooper.get(this).processAllMessages();
- // THEN the lifecycle state should be RESUMED
- assertThat(lifecycle.getLifecycle().getCurrentState()).isEqualTo(Lifecycle.State.RESUMED);
- }
-
- @Test
- public void testStateAfterDetach() {
- // WHEN a lifecycle is obtained from a view
- LifecycleOwner lifecycle = viewAttachLifecycle(mView);
- // AND the view is detached
- ViewUtils.attachView(mView);
- TestableLooper.get(this).processAllMessages();
- ViewUtils.detachView(mView);
- TestableLooper.get(this).processAllMessages();
- // THEN the lifecycle state should be DESTROYED
- assertThat(lifecycle.getLifecycle().getCurrentState()).isEqualTo(Lifecycle.State.DESTROYED);
- }
-
- @Test
- public void testStateAfterReattach() {
- // WHEN a lifecycle is obtained from a view
- LifecycleOwner lifecycle = viewAttachLifecycle(mView);
- // AND the view is re-attached
- ViewUtils.attachView(mView);
- TestableLooper.get(this).processAllMessages();
- ViewUtils.detachView(mView);
- TestableLooper.get(this).processAllMessages();
- ViewUtils.attachView(mView);
- TestableLooper.get(this).processAllMessages();
- // THEN the lifecycle state should still be DESTROYED, err RESUMED?
- assertThat(lifecycle.getLifecycle().getCurrentState()).isEqualTo(Lifecycle.State.RESUMED);
- }
-
- @Test
- public void testStateWhenViewAlreadyAttached() {
- // GIVEN that a view is already attached
- ViewUtils.attachView(mView);
- TestableLooper.get(this).processAllMessages();
- // WHEN a lifecycle is obtained from a view
- LifecycleOwner lifecycle = viewAttachLifecycle(mView);
- // THEN the lifecycle state should be RESUMED
- assertThat(lifecycle.getLifecycle().getCurrentState()).isEqualTo(Lifecycle.State.RESUMED);
- }
-
- @Test
- public void testStateWhenViewAlreadyDetached() {
- // GIVEN that a view is already detached
- ViewUtils.attachView(mView);
- TestableLooper.get(this).processAllMessages();
- ViewUtils.detachView(mView);
- TestableLooper.get(this).processAllMessages();
- // WHEN a lifecycle is obtained from a view
- LifecycleOwner lifecycle = viewAttachLifecycle(mView);
- // THEN the lifecycle state should be INITIALIZED
- assertThat(lifecycle.getLifecycle().getCurrentState()).isEqualTo(
- Lifecycle.State.INITIALIZED);
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
new file mode 100644
index 0000000..092e82c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.kotlin
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.filterIsInstance
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.takeWhile
+import kotlinx.coroutines.flow.toList
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class PairwiseFlowTest : SysuiTestCase() {
+ @Test
+ fun simple() = runBlocking {
+ assertThatFlow((1..3).asFlow().pairwise())
+ .emitsExactly(
+ WithPrev(1, 2),
+ WithPrev(2, 3),
+ )
+ }
+
+ @Test
+ fun notEnough() = runBlocking {
+ assertThatFlow(flowOf(1).pairwise()).emitsNothing()
+ }
+
+ @Test
+ fun withInit() = runBlocking {
+ assertThatFlow(flowOf(2).pairwise(initialValue = 1))
+ .emitsExactly(WithPrev(1, 2))
+ }
+
+ @Test
+ fun notEnoughWithInit() = runBlocking {
+ assertThatFlow(emptyFlow<Int>().pairwise(initialValue = 1)).emitsNothing()
+ }
+
+ @Test
+ fun withStateFlow() = runBlocking(Dispatchers.Main.immediate) {
+ val state = MutableStateFlow(1)
+ val stop = MutableSharedFlow<Unit>()
+
+ val stoppable = merge(state, stop)
+ .takeWhile { it is Int }
+ .filterIsInstance<Int>()
+
+ val job1 = launch {
+ assertThatFlow(stoppable.pairwise()).emitsExactly(WithPrev(1, 2))
+ }
+ state.value = 2
+ val job2 = launch { assertThatFlow(stoppable.pairwise()).emitsNothing() }
+
+ stop.emit(Unit)
+
+ assertThatJob(job1).isCompleted()
+ assertThatJob(job2).isCompleted()
+ }
+}
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class SetChangesFlowTest : SysuiTestCase() {
+ @Test
+ fun simple() = runBlocking {
+ assertThatFlow(
+ flowOf(setOf(1, 2, 3), setOf(2, 3, 4)).setChanges()
+ ).emitsExactly(
+ SetChanges(
+ added = setOf(1, 2, 3),
+ removed = emptySet(),
+ ),
+ SetChanges(
+ added = setOf(4),
+ removed = setOf(1),
+ ),
+ )
+ }
+
+ @Test
+ fun onlyOneEmission() = runBlocking {
+ assertThatFlow(flowOf(setOf(1)).setChanges())
+ .emitsExactly(
+ SetChanges(
+ added = setOf(1),
+ removed = emptySet(),
+ )
+ )
+ }
+
+ @Test
+ fun fromEmptySet() = runBlocking {
+ assertThatFlow(flowOf(emptySet(), setOf(1, 2)).setChanges())
+ .emitsExactly(
+ SetChanges(
+ removed = emptySet(),
+ added = setOf(1, 2),
+ )
+ )
+ }
+}
+
+private fun <T> assertThatFlow(flow: Flow<T>) = object {
+ suspend fun emitsExactly(vararg emissions: T) =
+ assertThat(flow.toList()).containsExactly(*emissions).inOrder()
+ suspend fun emitsNothing() =
+ assertThat(flow.toList()).isEmpty()
+}
+
+private fun assertThatJob(job: Job) = object {
+ fun isCompleted() = assertThat(job.isCompleted).isTrue()
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index 312db2d..2e74bf5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -85,6 +85,8 @@
@Mock
MediaOutputDialogFactory mMediaOutputDialogFactory;
@Mock
+ VolumePanelFactory mVolumePanelFactory;
+ @Mock
ActivityStarter mActivityStarter;
@Mock
InteractionJankMonitor mInteractionJankMonitor;
@@ -102,6 +104,7 @@
mDeviceProvisionedController,
mConfigurationController,
mMediaOutputDialogFactory,
+ mVolumePanelFactory,
mActivityStarter,
mInteractionJankMonitor);
mDialog.init(0, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 5d63632..09da52e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -99,7 +99,6 @@
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
@@ -162,8 +161,6 @@
@Mock
private CommonNotifCollection mCommonNotifCollection;
@Mock
- private NotificationGroupManagerLegacy mNotificationGroupManager;
- @Mock
private BubblesManager.NotifCallback mNotifCallback;
@Mock
private WindowManager mWindowManager;
@@ -389,7 +386,6 @@
interruptionStateProvider,
mZenModeController,
mLockscreenUserManager,
- mNotificationGroupManager,
mCommonNotifCollection,
mNotifPipeline,
mSysUiState,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java
index 48b5c62..34c83bd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java
@@ -40,6 +40,7 @@
private boolean mIsReportingEnabled;
private boolean mIsFalseRobustTap;
private boolean mDestroyed;
+ private boolean mIsProximityNear;
private final List<FalsingBeliefListener> mFalsingBeliefListeners = new ArrayList<>();
private final List<FalsingTapListener> mTapListeners = new ArrayList<>();
@@ -82,6 +83,10 @@
mIsFalseDoubleTap = falseDoubleTap;
}
+ public void setIsProximityNear(boolean proxNear) {
+ mIsProximityNear = proxNear;
+ }
+
@Override
public boolean isSimpleTap() {
checkDestroyed();
@@ -100,6 +105,11 @@
return mIsFalseDoubleTap;
}
+ @Override
+ public boolean isProximityNear() {
+ return mIsProximityNear;
+ }
+
@VisibleForTesting
public void setIsClassifierEnabled(boolean isClassifierEnabled) {
mIsClassifierEnabled = isClassifierEnabled;
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt
new file mode 100644
index 0000000..c56fdb1
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+class FakeFeatureFlags : FeatureFlags {
+ private val booleanFlags = mutableMapOf<Int, Boolean>()
+ private val stringFlags = mutableMapOf<Int, String>()
+ private val knownFlagNames = mutableMapOf<Int, String>()
+ private val flagListeners = mutableMapOf<Int, MutableSet<FlagListenable.Listener>>()
+ private val listenerFlagIds = mutableMapOf<FlagListenable.Listener, MutableSet<Int>>()
+
+ init {
+ Flags.getFlagFields().forEach { field ->
+ val flag: Flag<*> = field.get(null) as Flag<*>
+ knownFlagNames[flag.id] = field.name
+ }
+ }
+
+ fun set(flag: BooleanFlag, value: Boolean) {
+ if (booleanFlags.put(flag.id, value)?.let { value != it } != false) {
+ notifyFlagChanged(flag)
+ }
+ }
+
+ fun set(flag: DeviceConfigBooleanFlag, value: Boolean) {
+ if (booleanFlags.put(flag.id, value)?.let { value != it } != false) {
+ notifyFlagChanged(flag)
+ }
+ }
+
+ fun set(flag: ResourceBooleanFlag, value: Boolean) {
+ if (booleanFlags.put(flag.id, value)?.let { value != it } != false) {
+ notifyFlagChanged(flag)
+ }
+ }
+
+ fun set(flag: SysPropBooleanFlag, value: Boolean) {
+ if (booleanFlags.put(flag.id, value)?.let { value != it } != false) {
+ notifyFlagChanged(flag)
+ }
+ }
+
+ fun set(flag: StringFlag, value: String) {
+ if (stringFlags.put(flag.id, value)?.let { value != it } == null) {
+ notifyFlagChanged(flag)
+ }
+ }
+
+ fun set(flag: ResourceStringFlag, value: String) {
+ if (stringFlags.put(flag.id, value)?.let { value != it } == null) {
+ notifyFlagChanged(flag)
+ }
+ }
+
+ private fun notifyFlagChanged(flag: Flag<*>) {
+ flagListeners[flag.id]?.let { listeners ->
+ listeners.forEach { listener ->
+ listener.onFlagChanged(
+ object : FlagListenable.FlagEvent {
+ override val flagId = flag.id
+ override fun requestNoRestart() {}
+ }
+ )
+ }
+ }
+ }
+
+ override fun isEnabled(flag: UnreleasedFlag): Boolean = requireBooleanValue(flag.id)
+
+ override fun isEnabled(flag: ReleasedFlag): Boolean = requireBooleanValue(flag.id)
+
+ override fun isEnabled(flag: ResourceBooleanFlag): Boolean = requireBooleanValue(flag.id)
+
+ override fun isEnabled(flag: DeviceConfigBooleanFlag): Boolean = requireBooleanValue(flag.id)
+
+ override fun isEnabled(flag: SysPropBooleanFlag): Boolean = requireBooleanValue(flag.id)
+
+ override fun getString(flag: StringFlag): String = requireStringValue(flag.id)
+
+ override fun getString(flag: ResourceStringFlag): String = requireStringValue(flag.id)
+
+ override fun addListener(flag: Flag<*>, listener: FlagListenable.Listener) {
+ flagListeners.getOrPut(flag.id) { mutableSetOf() }.add(listener)
+ listenerFlagIds.getOrPut(listener) { mutableSetOf() }.add(flag.id)
+ }
+
+ override fun removeListener(listener: FlagListenable.Listener) {
+ listenerFlagIds.remove(listener)?.let {
+ flagIds -> flagIds.forEach {
+ id -> flagListeners[id]?.remove(listener)
+ }
+ }
+ }
+
+ private fun flagName(flagId: Int): String {
+ return knownFlagNames[flagId] ?: "UNKNOWN(id=$flagId)"
+ }
+
+ private fun requireBooleanValue(flagId: Int): Boolean {
+ return booleanFlags[flagId]
+ ?: error("Flag ${flagName(flagId)} was accessed but not specified.")
+ }
+
+ private fun requireStringValue(flagId: Int): String {
+ return stringFlags[flagId]
+ ?: error("Flag ${flagName(flagId)} was accessed but not specified.")
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt
new file mode 100644
index 0000000..5272585
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs
+
+import android.view.View
+import com.android.systemui.qs.FgsManagerController.OnDialogDismissedListener
+import com.android.systemui.qs.FgsManagerController.OnNumberOfPackagesChangedListener
+import kotlinx.coroutines.flow.MutableStateFlow
+
+/** A fake [FgsManagerController] to be used in tests. */
+class FakeFgsManagerController(
+ isAvailable: Boolean = true,
+ showFooterDot: Boolean = false,
+ numRunningPackages: Int = 0,
+) : FgsManagerController {
+ override val isAvailable: MutableStateFlow<Boolean> = MutableStateFlow(isAvailable)
+
+ override var numRunningPackages = numRunningPackages
+ set(value) {
+ if (value != field) {
+ field = value
+ newChangesSinceDialogWasDismissed = true
+ numRunningPackagesListeners.forEach { it.onNumberOfPackagesChanged(value) }
+ }
+ }
+
+ override var newChangesSinceDialogWasDismissed = false
+ private set
+
+ override val showFooterDot: MutableStateFlow<Boolean> = MutableStateFlow(showFooterDot)
+
+ private val numRunningPackagesListeners = LinkedHashSet<OnNumberOfPackagesChangedListener>()
+ private val dialogDismissedListeners = LinkedHashSet<OnDialogDismissedListener>()
+
+ /** Simulate that a fgs dialog was just dismissed. */
+ fun simulateDialogDismiss() {
+ newChangesSinceDialogWasDismissed = false
+ dialogDismissedListeners.forEach { it.onDialogDismissed() }
+ }
+
+ override fun init() {}
+
+ override fun showDialog(viewLaunchedFrom: View?) {}
+
+ override fun addOnNumberOfPackagesChangedListener(listener: OnNumberOfPackagesChangedListener) {
+ numRunningPackagesListeners.add(listener)
+ }
+
+ override fun removeOnNumberOfPackagesChangedListener(
+ listener: OnNumberOfPackagesChangedListener
+ ) {
+ numRunningPackagesListeners.remove(listener)
+ }
+
+ override fun addOnDialogDismissedListener(listener: OnDialogDismissedListener) {
+ dialogDismissedListeners.add(listener)
+ }
+
+ override fun removeOnDialogDismissedListener(listener: OnDialogDismissedListener) {
+ dialogDismissedListeners.remove(listener)
+ }
+
+ override fun shouldUpdateFooterVisibility(): Boolean = false
+
+ override fun visibleButtonsCount(): Int = 0
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
new file mode 100644
index 0000000..2a9aedd
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.footer
+
+import android.content.Context
+import android.os.Handler
+import android.os.UserManager
+import android.provider.Settings
+import android.testing.TestableLooper
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.UiEventLogger
+import com.android.internal.logging.testing.FakeMetricsLogger
+import com.android.internal.logging.testing.UiEventLoggerFake
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.classifier.FalsingManagerFake
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.qs.FakeFgsManagerController
+import com.android.systemui.qs.FgsManagerController
+import com.android.systemui.qs.QSSecurityFooterUtils
+import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepository
+import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepositoryImpl
+import com.android.systemui.qs.footer.data.repository.UserSwitcherRepository
+import com.android.systemui.qs.footer.data.repository.UserSwitcherRepositoryImpl
+import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
+import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractorImpl
+import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
+import com.android.systemui.qs.user.UserSwitchDialogController
+import com.android.systemui.security.data.repository.SecurityRepository
+import com.android.systemui.security.data.repository.SecurityRepositoryImpl
+import com.android.systemui.settings.FakeUserTracker
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.FakeSecurityController
+import com.android.systemui.statusbar.policy.FakeUserInfoController
+import com.android.systemui.statusbar.policy.SecurityController
+import com.android.systemui.statusbar.policy.UserInfoController
+import com.android.systemui.statusbar.policy.UserSwitcherController
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.settings.FakeSettings
+import com.android.systemui.util.settings.GlobalSettings
+import com.android.systemui.util.time.FakeSystemClock
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.test.TestCoroutineDispatcher
+
+/**
+ * Util class to create real implementations of the FooterActions repositories, viewModel and
+ * interactor to be used in tests.
+ */
+class FooterActionsTestUtils(
+ private val context: Context,
+ private val testableLooper: TestableLooper,
+ private val fakeClock: FakeSystemClock = FakeSystemClock(),
+) {
+ /** Enable or disable the user switcher in the settings. */
+ fun setUserSwitcherEnabled(settings: GlobalSettings, enabled: Boolean, userId: Int) {
+ settings.putBoolForUser(Settings.Global.USER_SWITCHER_ENABLED, enabled, userId)
+
+ // The settings listener is processing messages on the bgHandler (usually backed by a
+ // testableLooper in tests), so let's make sure we process the callback before continuing.
+ testableLooper.processAllMessages()
+ }
+
+ /** Create a [FooterActionsViewModel] to be used in tests. */
+ fun footerActionsViewModel(
+ @Application context: Context = this.context.applicationContext,
+ footerActionsInteractor: FooterActionsInteractor = footerActionsInteractor(),
+ falsingManager: FalsingManager = FalsingManagerFake(),
+ globalActionsDialogLite: GlobalActionsDialogLite = mock(),
+ showPowerButton: Boolean = true,
+ ): FooterActionsViewModel {
+ return FooterActionsViewModel(
+ context,
+ footerActionsInteractor,
+ falsingManager,
+ globalActionsDialogLite,
+ showPowerButton,
+ )
+ }
+
+ /** Create a [FooterActionsInteractor] to be used in tests. */
+ fun footerActionsInteractor(
+ activityStarter: ActivityStarter = mock(),
+ featureFlags: FeatureFlags = FakeFeatureFlags(),
+ metricsLogger: MetricsLogger = FakeMetricsLogger(),
+ uiEventLogger: UiEventLogger = UiEventLoggerFake(),
+ deviceProvisionedController: DeviceProvisionedController = mock(),
+ qsSecurityFooterUtils: QSSecurityFooterUtils = mock(),
+ fgsManagerController: FgsManagerController = mock(),
+ userSwitchDialogController: UserSwitchDialogController = mock(),
+ securityRepository: SecurityRepository = securityRepository(),
+ foregroundServicesRepository: ForegroundServicesRepository = foregroundServicesRepository(),
+ userSwitcherRepository: UserSwitcherRepository = userSwitcherRepository(),
+ broadcastDispatcher: BroadcastDispatcher = mock(),
+ bgDispatcher: CoroutineDispatcher = TestCoroutineDispatcher(),
+ ): FooterActionsInteractor {
+ return FooterActionsInteractorImpl(
+ activityStarter,
+ featureFlags,
+ metricsLogger,
+ uiEventLogger,
+ deviceProvisionedController,
+ qsSecurityFooterUtils,
+ fgsManagerController,
+ userSwitchDialogController,
+ securityRepository,
+ foregroundServicesRepository,
+ userSwitcherRepository,
+ broadcastDispatcher,
+ bgDispatcher,
+ )
+ }
+
+ /** Create a [SecurityRepository] to be used in tests. */
+ fun securityRepository(
+ securityController: SecurityController = FakeSecurityController(),
+ bgDispatcher: CoroutineDispatcher = TestCoroutineDispatcher(),
+ ): SecurityRepository {
+ return SecurityRepositoryImpl(
+ securityController,
+ bgDispatcher,
+ )
+ }
+
+ /** Create a [SecurityRepository] to be used in tests. */
+ fun foregroundServicesRepository(
+ fgsManagerController: FakeFgsManagerController = FakeFgsManagerController(),
+ ): ForegroundServicesRepository {
+ return ForegroundServicesRepositoryImpl(fgsManagerController)
+ }
+
+ /** Create a [UserSwitcherRepository] to be used in tests. */
+ fun userSwitcherRepository(
+ @Application context: Context = this.context.applicationContext,
+ bgHandler: Handler = Handler(testableLooper.looper),
+ bgDispatcher: CoroutineDispatcher = TestCoroutineDispatcher(),
+ userManager: UserManager = mock(),
+ userTracker: UserTracker = FakeUserTracker(),
+ userSwitcherController: UserSwitcherController = mock(),
+ userInfoController: UserInfoController = FakeUserInfoController(),
+ settings: GlobalSettings = FakeSettings(),
+ ): UserSwitcherRepository {
+ return UserSwitcherRepositoryImpl(
+ context,
+ bgHandler,
+ bgDispatcher,
+ userManager,
+ userTracker,
+ userSwitcherController,
+ userInfoController,
+ settings,
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
new file mode 100644
index 0000000..b2b1764
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings
+
+import android.content.ContentResolver
+import android.content.Context
+import android.content.pm.UserInfo
+import android.os.UserHandle
+import android.test.mock.MockContentResolver
+import com.android.systemui.util.mockito.mock
+import java.util.concurrent.Executor
+
+/** A fake [UserTracker] to be used in tests. */
+class FakeUserTracker(
+ userId: Int = 0,
+ userHandle: UserHandle = UserHandle.of(userId),
+ userInfo: UserInfo = mock(),
+ userProfiles: List<UserInfo> = emptyList(),
+ userContentResolver: ContentResolver = MockContentResolver(),
+ userContext: Context = mock(),
+ private val onCreateCurrentUserContext: (Context) -> Context = { mock() },
+) : UserTracker {
+ val callbacks = mutableListOf<UserTracker.Callback>()
+
+ override val userId: Int = userId
+ override val userHandle: UserHandle = userHandle
+ override val userInfo: UserInfo = userInfo
+ override val userProfiles: List<UserInfo> = userProfiles
+
+ override val userContentResolver: ContentResolver = userContentResolver
+ override val userContext: Context = userContext
+
+ override fun addCallback(callback: UserTracker.Callback, executor: Executor) {
+ callbacks.add(callback)
+ }
+
+ override fun removeCallback(callback: UserTracker.Callback) {
+ callbacks.remove(callback)
+ }
+
+ override fun createCurrentUserContext(context: Context): Context {
+ return onCreateCurrentUserContext(context)
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt
new file mode 100644
index 0000000..c6aa395
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy
+
+import android.app.admin.DeviceAdminInfo
+import android.content.ComponentName
+import android.graphics.drawable.Drawable
+import java.io.PrintWriter
+
+/** A fake [SecurityController] to be used in tests. */
+class FakeSecurityController(
+ private val fakeState: FakeState = FakeState(),
+) : SecurityController {
+ private val callbacks = LinkedHashSet<SecurityController.SecurityControllerCallback>()
+
+ override fun addCallback(callback: SecurityController.SecurityControllerCallback) {
+ callbacks.add(callback)
+ }
+
+ override fun removeCallback(callback: SecurityController.SecurityControllerCallback) {
+ callbacks.remove(callback)
+ }
+
+ /** Update [fakeState], then notify the callbacks. */
+ fun updateState(f: FakeState.() -> Unit) {
+ fakeState.f()
+ callbacks.forEach { it.onStateChanged() }
+ }
+
+ override fun dump(pw: PrintWriter, args: Array<out String>) {}
+
+ override fun isDeviceManaged(): Boolean = fakeState.isDeviceManaged
+
+ override fun hasProfileOwner(): Boolean = fakeState.hasProfileOwner
+
+ override fun hasWorkProfile(): Boolean = fakeState.hasWorkProfile
+
+ override fun isWorkProfileOn(): Boolean = fakeState.isWorkProfileOn
+
+ override fun isProfileOwnerOfOrganizationOwnedDevice(): Boolean =
+ fakeState.isProfileOwnerOfOrganizationOwnedDevice
+
+ override fun getDeviceOwnerName(): String? = fakeState.deviceOwnerName
+
+ override fun getProfileOwnerName(): String? = fakeState.profileOwnerName
+
+ override fun getDeviceOwnerOrganizationName(): String? = fakeState.deviceOwnerOrganizationName
+
+ override fun getWorkProfileOrganizationName(): String? = fakeState.workProfileOrganizationName
+
+ override fun getDeviceOwnerComponentOnAnyUser(): ComponentName? =
+ fakeState.deviceOwnerComponentOnAnyUser
+
+ override fun getDeviceOwnerType(admin: ComponentName?): Int = 0
+
+ override fun isNetworkLoggingEnabled(): Boolean = fakeState.isNetworkLoggingEnabled
+
+ override fun isVpnEnabled(): Boolean = fakeState.isVpnEnabled
+
+ override fun isVpnRestricted(): Boolean = fakeState.isVpnRestricted
+
+ override fun isVpnBranded(): Boolean = fakeState.isVpnBranded
+
+ override fun getPrimaryVpnName(): String? = fakeState.primaryVpnName
+
+ override fun getWorkProfileVpnName(): String? = fakeState.workProfileVpnName
+
+ override fun hasCACertInCurrentUser(): Boolean = fakeState.hasCACertInCurrentUser
+
+ override fun hasCACertInWorkProfile(): Boolean = fakeState.hasCACertInWorkProfile
+
+ override fun onUserSwitched(newUserId: Int) {}
+
+ override fun isParentalControlsEnabled(): Boolean = fakeState.isParentalControlsEnabled
+
+ override fun getDeviceAdminInfo(): DeviceAdminInfo? = fakeState.deviceAdminInfo
+
+ override fun getIcon(info: DeviceAdminInfo?): Drawable? = null
+
+ override fun getLabel(info: DeviceAdminInfo?): CharSequence? = null
+
+ class FakeState(
+ var isDeviceManaged: Boolean = false,
+ var hasProfileOwner: Boolean = false,
+ var hasWorkProfile: Boolean = false,
+ var isWorkProfileOn: Boolean = false,
+ var isProfileOwnerOfOrganizationOwnedDevice: Boolean = false,
+ var deviceOwnerName: String? = null,
+ var profileOwnerName: String? = null,
+ var deviceOwnerOrganizationName: String? = null,
+ var workProfileOrganizationName: String? = null,
+ var deviceOwnerComponentOnAnyUser: ComponentName? = null,
+ var isNetworkLoggingEnabled: Boolean = false,
+ var isVpnEnabled: Boolean = false,
+ var isVpnRestricted: Boolean = false,
+ var isVpnBranded: Boolean = false,
+ var primaryVpnName: String? = null,
+ var workProfileVpnName: String? = null,
+ var hasCACertInCurrentUser: Boolean = false,
+ var hasCACertInWorkProfile: Boolean = false,
+ var isParentalControlsEnabled: Boolean = false,
+ var deviceAdminInfo: DeviceAdminInfo? = null,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeUserInfoController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeUserInfoController.kt
new file mode 100644
index 0000000..32b9a37
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeUserInfoController.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy
+
+import android.graphics.drawable.Drawable
+import com.android.systemui.util.mockito.mock
+
+/** A fake [UserInfoController] to be used in tests. */
+class FakeUserInfoController(
+ private val fakeInfo: FakeInfo = FakeInfo(),
+) : UserInfoController {
+ private val listeners = LinkedHashSet<UserInfoController.OnUserInfoChangedListener>()
+
+ /** Update [fakeInfo], then notify the listeners. */
+ fun updateInfo(f: FakeInfo.() -> Unit) {
+ fakeInfo.f()
+ notifyListeners()
+ }
+
+ private fun notifyListeners() {
+ listeners.forEach { listener ->
+ listener.onUserInfoChanged(fakeInfo.name, fakeInfo.picture, fakeInfo.userAccount)
+ }
+ }
+
+ override fun addCallback(listener: UserInfoController.OnUserInfoChangedListener) {
+ listeners.add(listener)
+
+ // The actual implementation notifies the listener when adding it.
+ listener.onUserInfoChanged(fakeInfo.name, fakeInfo.picture, fakeInfo.userAccount)
+ }
+
+ override fun removeCallback(listener: UserInfoController.OnUserInfoChangedListener) {
+ listeners.remove(listener)
+ }
+
+ override fun reloadUserInfo() {}
+
+ class FakeInfo(
+ var name: String = "",
+ var picture: Drawable = mock(),
+ var userAccount: String = "",
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/MockUserSwitcherControllerWrapper.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/MockUserSwitcherControllerWrapper.kt
new file mode 100644
index 0000000..1304a12
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/MockUserSwitcherControllerWrapper.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy
+
+import com.android.systemui.statusbar.policy.UserSwitcherController.UserSwitchCallback
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import org.mockito.Mockito.`when` as whenever
+
+/**
+ * A wrapper around a mocked [UserSwitcherController] to be used in tests.
+ *
+ * Note that this was implemented as a mock wrapper instead of fake implementation of a common
+ * interface given how big the UserSwitcherController grew.
+ */
+class MockUserSwitcherControllerWrapper(
+ currentUserName: String = "",
+) {
+ val controller: UserSwitcherController = mock()
+ private val callbacks = LinkedHashSet<UserSwitchCallback>()
+
+ var currentUserName = currentUserName
+ set(value) {
+ if (value != field) {
+ field = value
+ notifyCallbacks()
+ }
+ }
+
+ private fun notifyCallbacks() {
+ callbacks.forEach { it.onUserSwitched() }
+ }
+
+ init {
+ whenever(controller.addUserSwitchCallback(any())).then { invocation ->
+ callbacks.add(invocation.arguments.first() as UserSwitchCallback)
+ }
+
+ whenever(controller.removeUserSwitchCallback(any())).then { invocation ->
+ callbacks.remove(invocation.arguments.first() as UserSwitchCallback)
+ }
+
+ whenever(controller.currentUserName).thenAnswer { this.currentUserName }
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/truth/correspondence/FakeUiEvent.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/truth/correspondence/FakeUiEvent.kt
new file mode 100644
index 0000000..48cd345
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/truth/correspondence/FakeUiEvent.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.truth.correspondence
+
+import com.android.internal.logging.testing.UiEventLoggerFake
+import com.android.internal.logging.testing.UiEventLoggerFake.FakeUiEvent
+import com.google.common.truth.Correspondence
+
+/** Instances of [Correspondence] to match a [UiEventLoggerFake.FakeUiEvent] with Truth. */
+object FakeUiEvent {
+ val EVENT_ID =
+ Correspondence.transforming<FakeUiEvent, Int>(
+ { it?.eventId },
+ "has a eventId of",
+ )
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java b/packages/SystemUI/tests/utils/src/com/android/systemui/truth/correspondence/LogMaker.kt
similarity index 61%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
copy to packages/SystemUI/tests/utils/src/com/android/systemui/truth/correspondence/LogMaker.kt
index e62a63a..3f0a9524 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/truth/correspondence/LogMaker.kt
@@ -14,18 +14,16 @@
* limitations under the License.
*/
-package com.android.wm.shell.desktopmode;
+package com.android.systemui.truth.correspondence
-import android.os.SystemProperties;
+import android.metrics.LogMaker
+import com.google.common.truth.Correspondence
-/**
- * Constants for desktop mode feature
- */
-public class DesktopModeConstants {
-
- /**
- * Flag to indicate whether desktop mode is available on the device
- */
- public static final boolean IS_FEATURE_ENABLED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode", false);
+/** Instances of [Correspondence] to match a [LogMaker] with Truth. */
+object LogMaker {
+ val CATEGORY =
+ Correspondence.transforming<LogMaker, Int>(
+ { it?.category },
+ "has a category of",
+ )
}
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index 41b6fad..2b644fe 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -41,6 +41,7 @@
import android.os.Parcel;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.util.ArraySet;
import android.util.ExceptionUtils;
import android.util.Slog;
import android.util.SparseArray;
@@ -56,6 +57,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@@ -86,6 +88,12 @@
private final SparseArray<VirtualDeviceImpl> mVirtualDevices = new SparseArray<>();
/**
+ * Mapping from CDM association IDs to app UIDs running on the corresponding virtual device.
+ */
+ @GuardedBy("mVirtualDeviceManagerLock")
+ private final SparseArray<ArraySet<Integer>> mAppsOnVirtualDevices = new SparseArray<>();
+
+ /**
* Mapping from user ID to CDM associations. The associations come from
* {@link CompanionDeviceManager#getAllAssociations()}, which contains associations across all
* packages.
@@ -208,6 +216,18 @@
}
@VisibleForTesting
+ VirtualDeviceManagerInternal getLocalServiceInstance() {
+ return mLocalService;
+ }
+
+ @VisibleForTesting
+ void notifyRunningAppsChanged(int associationId, ArraySet<Integer> uids) {
+ synchronized (mVirtualDeviceManagerLock) {
+ mAppsOnVirtualDevices.put(associationId, uids);
+ }
+ mLocalService.onAppsOnVirtualDeviceChanged();
+ }
+
class VirtualDeviceManagerImpl extends IVirtualDeviceManager.Stub implements
VirtualDeviceImpl.PendingTrampolineCallback {
@@ -247,6 +267,7 @@
public void onClose(int associationId) {
synchronized (mVirtualDeviceManagerLock) {
mVirtualDevices.remove(associationId);
+ mAppsOnVirtualDevices.remove(associationId);
if (cameraAccessController != null) {
cameraAccessController.stopObservingIfNeeded();
} else {
@@ -257,8 +278,10 @@
}
},
this, activityListener,
- runningUids -> cameraAccessController.blockCameraAccessIfNeeded(
- runningUids),
+ runningUids -> {
+ cameraAccessController.blockCameraAccessIfNeeded(runningUids);
+ notifyRunningAppsChanged(associationInfo.getId(), runningUids);
+ },
params);
if (cameraAccessController != null) {
cameraAccessController.startObservingIfNeeded();
@@ -308,10 +331,11 @@
final long tokenTwo = Binder.clearCallingIdentity();
try {
virtualDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, displayId);
- return displayId;
} finally {
Binder.restoreCallingIdentity(tokenTwo);
}
+ mLocalService.onVirtualDisplayCreated(displayId);
+ return displayId;
}
@Nullable
@@ -378,6 +402,15 @@
}
private final class LocalService extends VirtualDeviceManagerInternal {
+ @GuardedBy("mVirtualDeviceManagerLock")
+ private final ArrayList<VirtualDisplayListener>
+ mVirtualDisplayListeners = new ArrayList<>();
+ @GuardedBy("mVirtualDeviceManagerLock")
+ private final ArrayList<AppsOnVirtualDeviceListener>
+ mAppsOnVirtualDeviceListeners = new ArrayList<>();
+ @GuardedBy("mVirtualDeviceManagerLock")
+ private final ArraySet<Integer> mAllUidsOnVirtualDevice = new ArraySet<>();
+
@Override
public boolean isValidVirtualDevice(IVirtualDevice virtualDevice) {
synchronized (mVirtualDeviceManagerLock) {
@@ -386,9 +419,57 @@
}
@Override
+ public void onVirtualDisplayCreated(int displayId) {
+ final VirtualDisplayListener[] listeners;
+ synchronized (mVirtualDeviceManagerLock) {
+ listeners = mVirtualDisplayListeners.toArray(new VirtualDisplayListener[0]);
+ }
+ mHandler.post(() -> {
+ for (VirtualDisplayListener listener : listeners) {
+ listener.onVirtualDisplayCreated(displayId);
+ }
+ });
+ }
+
+ @Override
public void onVirtualDisplayRemoved(IVirtualDevice virtualDevice, int displayId) {
+ final VirtualDisplayListener[] listeners;
synchronized (mVirtualDeviceManagerLock) {
((VirtualDeviceImpl) virtualDevice).onVirtualDisplayRemovedLocked(displayId);
+ listeners = mVirtualDisplayListeners.toArray(new VirtualDisplayListener[0]);
+ }
+ mHandler.post(() -> {
+ for (VirtualDisplayListener listener : listeners) {
+ listener.onVirtualDisplayRemoved(displayId);
+ }
+ });
+ }
+
+ @Override
+ public void onAppsOnVirtualDeviceChanged() {
+ ArraySet<Integer> latestRunningUids = new ArraySet<>();
+ final AppsOnVirtualDeviceListener[] listeners;
+ synchronized (mVirtualDeviceManagerLock) {
+ int size = mAppsOnVirtualDevices.size();
+ for (int i = 0; i < size; i++) {
+ latestRunningUids.addAll(mAppsOnVirtualDevices.valueAt(i));
+ }
+ if (!mAllUidsOnVirtualDevice.equals(latestRunningUids)) {
+ mAllUidsOnVirtualDevice.clear();
+ mAllUidsOnVirtualDevice.addAll(latestRunningUids);
+ listeners =
+ mAppsOnVirtualDeviceListeners.toArray(
+ new AppsOnVirtualDeviceListener[0]);
+ } else {
+ listeners = null;
+ }
+ }
+ if (listeners != null) {
+ mHandler.post(() -> {
+ for (AppsOnVirtualDeviceListener listener : listeners) {
+ listener.onAppsOnAnyVirtualDeviceChanged(latestRunningUids);
+ }
+ });
}
}
@@ -435,6 +516,38 @@
}
return false;
}
+
+ @Override
+ public void registerVirtualDisplayListener(
+ @NonNull VirtualDisplayListener listener) {
+ synchronized (mVirtualDeviceManagerLock) {
+ mVirtualDisplayListeners.add(listener);
+ }
+ }
+
+ @Override
+ public void unregisterVirtualDisplayListener(
+ @NonNull VirtualDisplayListener listener) {
+ synchronized (mVirtualDeviceManagerLock) {
+ mVirtualDisplayListeners.remove(listener);
+ }
+ }
+
+ @Override
+ public void registerAppsOnVirtualDeviceListener(
+ @NonNull AppsOnVirtualDeviceListener listener) {
+ synchronized (mVirtualDeviceManagerLock) {
+ mAppsOnVirtualDeviceListeners.add(listener);
+ }
+ }
+
+ @Override
+ public void unregisterAppsOnVirtualDeviceListener(
+ @NonNull AppsOnVirtualDeviceListener listener) {
+ synchronized (mVirtualDeviceManagerLock) {
+ mAppsOnVirtualDeviceListeners.remove(listener);
+ }
+ }
}
private static final class PendingTrampolineMap {
diff --git a/services/core/java/com/android/server/DockObserver.java b/services/core/java/com/android/server/DockObserver.java
index 8a6b54f..104d10d 100644
--- a/services/core/java/com/android/server/DockObserver.java
+++ b/services/core/java/com/android/server/DockObserver.java
@@ -69,6 +69,7 @@
private boolean mUpdatesStopped;
+ private final boolean mKeepDreamingWhenUndocking;
private final boolean mAllowTheaterModeWakeFromDock;
private final List<ExtconStateConfig> mExtconStateConfigs;
@@ -164,6 +165,8 @@
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mAllowTheaterModeWakeFromDock = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromDock);
+ mKeepDreamingWhenUndocking = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_keepDreamingWhenUndocking);
mExtconStateConfigs = loadExtconStateConfigs(context);
@@ -216,10 +219,8 @@
if (newState != mReportedDockState) {
mReportedDockState = newState;
if (mSystemReady) {
- // Wake up immediately when docked or undocked except in theater mode.
- if (mAllowTheaterModeWakeFromDock
- || Settings.Global.getInt(getContext().getContentResolver(),
- Settings.Global.THEATER_MODE_ON, 0) == 0) {
+ // Wake up immediately when docked or undocked unless prohibited from doing so.
+ if (allowWakeFromDock()) {
mPowerManager.wakeUp(SystemClock.uptimeMillis(),
"android.server:DOCK");
}
@@ -228,6 +229,15 @@
}
}
+ private boolean allowWakeFromDock() {
+ if (mKeepDreamingWhenUndocking) {
+ return false;
+ }
+ return (mAllowTheaterModeWakeFromDock
+ || Settings.Global.getInt(getContext().getContentResolver(),
+ Settings.Global.THEATER_MODE_ON, 0) == 0);
+ }
+
private void updateLocked() {
mWakeLock.acquire();
mHandler.sendEmptyMessage(MSG_DOCK_STATE_CHANGED);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 9a98f54..dcb7a30 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -19,12 +19,10 @@
import static android.Manifest.permission.ACCESS_MTP;
import static android.Manifest.permission.INSTALL_PACKAGES;
import static android.Manifest.permission.MANAGE_EXTERNAL_STORAGE;
-import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
import static android.app.AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE;
import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES;
-import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE;
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.app.PendingIntent.FLAG_ONE_SHOT;
@@ -4526,11 +4524,7 @@
}
}
- // Determine if caller is holding runtime permission
- final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
- uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE);
-
- // We're only willing to give out installer access if they also hold
+ // We're only willing to give out installer access if they hold
// runtime permission; this is a firm CDD requirement
final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES,
uid) == PERMISSION_GRANTED;
@@ -4546,7 +4540,7 @@
break;
}
}
- if ((hasInstall || hasInstallOp) && hasWrite) {
+ if (hasInstall || hasInstallOp) {
return StorageManager.MOUNT_MODE_EXTERNAL_INSTALLER;
}
return StorageManager.MOUNT_MODE_EXTERNAL_DEFAULT;
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index c853ba9..e9dd836 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -359,6 +359,11 @@
SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME, Integer.toString(mode));
}
+ @VisibleForTesting
+ void setStartDreamImmediatelyOnDock(boolean startDreamImmediatelyOnDock) {
+ mStartDreamImmediatelyOnDock = startDreamImmediatelyOnDock;
+ }
+
@Override
public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
mCurrentUser = to.getUserIdentifier();
@@ -1824,7 +1829,8 @@
// If we did not start a dock app, then start dreaming if appropriate.
if (category != null && !dockAppStarted && (mStartDreamImmediatelyOnDock
- || mKeyguardManager.isKeyguardLocked())) {
+ || mWindowManager.isKeyguardShowingAndNotOccluded()
+ || !mPowerManager.isInteractive())) {
Sandman.startDreamWhenDockedIfAppropriate(getContext());
}
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 8368b4d..9840e0f 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -190,6 +190,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
public final class ActiveServices {
@@ -220,6 +221,11 @@
| ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
| ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION;
+ // Keep track of number of foreground services and number of apps that have foreground
+ // services in the device. This field is made to be directly accessed without holding AMS lock.
+ static final AtomicReference<Pair<Integer, Integer>> sNumForegroundServices =
+ new AtomicReference(new Pair<>(0, 0));
+
// Foreground service is stopped for unknown reason.
static final int FGS_STOP_REASON_UNKNOWN = 0;
// Foreground service is stopped by app calling Service.stopForeground().
@@ -454,6 +460,7 @@
final ArrayList<ServiceRecord> mStartingBackground = new ArrayList<>();
final ArrayMap<String, ActiveForegroundApp> mActiveForegroundApps = new ArrayMap<>();
+
boolean mActiveForegroundAppsChanged;
static final int MSG_BG_START_TIMEOUT = 1;
@@ -2025,6 +2032,7 @@
logFGSStateChangeLocked(r,
FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER,
0, FGS_STOP_REASON_UNKNOWN);
+ updateNumForegroundServicesLocked();
}
// Even if the service is already a FGS, we need to update the notification,
// so we need to call it again.
@@ -2116,6 +2124,7 @@
mAm.updateLruProcessLocked(r.app, false, null);
updateServiceForegroundLocked(r.app.mServices, true);
}
+ updateNumForegroundServicesLocked();
}
}
}
@@ -4784,6 +4793,7 @@
}
smap.ensureNotStartingBackgroundLocked(r);
+ updateNumForegroundServicesLocked();
}
private void dropFgsNotificationStateLocked(ServiceRecord r) {
@@ -6975,6 +6985,10 @@
fgsStopReasonToString(fgsStopReason));
}
+ private void updateNumForegroundServicesLocked() {
+ sNumForegroundServices.set(mAm.mProcessList.getNumForegroundServices());
+ }
+
boolean canAllowWhileInUsePermissionInFgsLocked(int callingPid, int callingUid,
String callingPackage) {
return shouldAllowFgsWhileInUsePermissionLocked(callingPackage, callingPid, callingUid,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 147b550..ef9b2ed 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8745,12 +8745,40 @@
if (process.info.isInstantApp()) {
sb.append("Instant-App: true\n");
}
+
if (isSdkSandboxUid(process.uid)) {
+ final int appUid = Process.getAppUidForSdkSandboxUid(process.uid);
+ try {
+ String[] clientPackages = pm.getPackagesForUid(appUid);
+ // In shared UID case, don't add the package information
+ if (clientPackages.length == 1) {
+ appendSdkSandboxClientPackageHeader(sb, clientPackages[0], callingUserId);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error getting packages for client app uid: " + appUid, e);
+ }
sb.append("SdkSandbox: true\n");
}
}
}
+ private void appendSdkSandboxClientPackageHeader(StringBuilder sb, String pkg, int userId) {
+ final IPackageManager pm = AppGlobals.getPackageManager();
+ sb.append("SdkSandbox-Client-Package: ").append(pkg);
+ try {
+ final PackageInfo pi = pm.getPackageInfo(pkg, 0, userId);
+ if (pi != null) {
+ sb.append(" v").append(pi.getLongVersionCode());
+ if (pi.versionName != null) {
+ sb.append(" (").append(pi.versionName).append(")");
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error getting package info for SDK sandbox client: " + pkg, e);
+ }
+ sb.append("\n");
+ }
+
private static String processClass(ProcessRecord process) {
if (process == null || process.getPid() == MY_PID) {
return "system_server";
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 0d3685d..9921956 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -1167,7 +1167,18 @@
return;
}
Slog.d(TAG_AM, "quick sync unfreeze " + pid);
- unfreezeAppLSP(app, reason);
+ try {
+ freezeBinder(pid, false);
+ } catch (RuntimeException e) {
+ Slog.e(TAG_AM, "Unable to quick unfreeze binder for " + pid);
+ return;
+ }
+
+ try {
+ Process.setProcessFrozen(pid, app.uid, false);
+ } catch (Exception e) {
+ Slog.e(TAG_AM, "Unable to quick unfreeze " + pid);
+ }
}
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index a8d7e13..3eac406 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -814,12 +814,14 @@
< LmkdStatsReporter.KILL_OCCURRED_MSG_SIZE) {
return false;
}
- Pair<Integer, Integer> temp = getNumForegroundServices();
- final int totalForegroundServices = temp.first;
- final int procsWithForegroundServices = temp.second;
+ // Note: directly access
+ // ActiveServices.sNumForegroundServices, do not try to
+ // hold AMS lock here, otherwise it is a potential deadlock.
+ Pair<Integer, Integer> foregroundServices =
+ ActiveServices.sNumForegroundServices.get();
LmkdStatsReporter.logKillOccurred(inputData,
- totalForegroundServices,
- procsWithForegroundServices);
+ foregroundServices.first,
+ foregroundServices.second);
return true;
case LMK_STATE_CHANGED:
if (receivedLen
diff --git a/services/core/java/com/android/server/am/UidObserverController.java b/services/core/java/com/android/server/am/UidObserverController.java
index e8c1b54..51cb987 100644
--- a/services/core/java/com/android/server/am/UidObserverController.java
+++ b/services/core/java/com/android/server/am/UidObserverController.java
@@ -15,6 +15,7 @@
*/
package com.android.server.am;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
@@ -25,6 +26,7 @@
import android.app.ActivityManager;
import android.app.ActivityManagerProto;
import android.app.IUidObserver;
+import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -81,7 +83,9 @@
@NonNull String callingPackage, int callingUid) {
synchronized (mLock) {
mUidObservers.register(observer, new UidObserverRegistration(callingUid,
- callingPackage, which, cutpoint));
+ callingPackage, which, cutpoint,
+ ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL, callingUid)
+ == PackageManager.PERMISSION_GRANTED));
}
}
@@ -252,6 +256,11 @@
final ChangeRecord item = mActiveUidChanges[j];
final long start = SystemClock.uptimeMillis();
final int change = item.change;
+ // Does the user have permission? Don't send a non user UID change otherwise
+ if (UserHandle.getUserId(item.uid) != UserHandle.getUserId(reg.mUid)
+ && !reg.mCanInteractAcrossUsers) {
+ continue;
+ }
if (change == UidRecord.CHANGE_PROCSTATE
&& (reg.mWhich & ActivityManager.UID_OBSERVER_PROCSTATE) == 0) {
// No-op common case: no significant change, the observer is not
@@ -437,6 +446,7 @@
private final String mPkg;
private final int mWhich;
private final int mCutpoint;
+ private final boolean mCanInteractAcrossUsers;
/**
* Total # of callback calls that took more than {@link #SLOW_UID_OBSERVER_THRESHOLD_MS}.
@@ -467,11 +477,13 @@
ActivityManagerProto.UID_OBSERVER_FLAG_PROC_OOM_ADJ,
};
- UidObserverRegistration(int uid, @NonNull String pkg, int which, int cutpoint) {
+ UidObserverRegistration(int uid, @NonNull String pkg, int which, int cutpoint,
+ boolean canInteractAcrossUsers) {
this.mUid = uid;
this.mPkg = pkg;
this.mWhich = which;
this.mCutpoint = cutpoint;
+ this.mCanInteractAcrossUsers = canInteractAcrossUsers;
mLastProcStates = cutpoint >= ActivityManager.MIN_PROCESS_STATE
? new SparseIntArray() : null;
}
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java
index 028288f..dcadd5f 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java
@@ -29,6 +29,7 @@
import android.app.ambientcontext.AmbientContextEvent;
import android.app.ambientcontext.AmbientContextEventRequest;
import android.app.ambientcontext.AmbientContextManager;
+import android.app.ambientcontext.IAmbientContextObserver;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
@@ -53,6 +54,8 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
+import java.util.function.Consumer;
/**
* Per-user manager service for {@link AmbientContextEvent}s.
@@ -165,20 +168,17 @@
* package. A new registration from the same package will overwrite the previous registration.
*/
public void onRegisterObserver(AmbientContextEventRequest request,
- PendingIntent pendingIntent, RemoteCallback clientStatusCallback) {
+ String packageName, IAmbientContextObserver observer) {
synchronized (mLock) {
if (!setUpServiceIfNeeded()) {
Slog.w(TAG, "Detection service is not available at this moment.");
- sendStatusCallback(
- clientStatusCallback,
- AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
+ completeRegistration(observer, AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
return;
}
// Register package and add to existing ClientRequests cache
- startDetection(request, pendingIntent.getCreatorPackage(),
- createDetectionResultRemoteCallback(), clientStatusCallback);
- mMaster.newClientAdded(mUserId, request, pendingIntent, clientStatusCallback);
+ startDetection(request, packageName, observer);
+ mMaster.newClientAdded(mUserId, request, packageName, observer);
}
}
@@ -186,49 +186,46 @@
* Returns a RemoteCallback that handles the status from the detection service, and
* sends results to the client callback.
*/
- private RemoteCallback getServerStatusCallback(RemoteCallback clientStatusCallback) {
+ private RemoteCallback getServerStatusCallback(Consumer<Integer> statusConsumer) {
return new RemoteCallback(result -> {
AmbientContextDetectionServiceStatus serviceStatus =
(AmbientContextDetectionServiceStatus) result.get(
AmbientContextDetectionServiceStatus.STATUS_RESPONSE_BUNDLE_KEY);
final long token = Binder.clearCallingIdentity();
try {
- String packageName = serviceStatus.getPackageName();
- Bundle bundle = new Bundle();
- bundle.putInt(
- AmbientContextManager.STATUS_RESPONSE_BUNDLE_KEY,
- serviceStatus.getStatusCode());
- clientStatusCallback.sendResult(bundle);
int statusCode = serviceStatus.getStatusCode();
+ statusConsumer.accept(statusCode);
Slog.i(TAG, "Got detection status of " + statusCode
- + " for " + packageName);
+ + " for " + serviceStatus.getPackageName());
} finally {
Binder.restoreCallingIdentity(token);
}
});
}
- @VisibleForTesting
void startDetection(AmbientContextEventRequest request, String callingPackage,
- RemoteCallback detectionResultCallback, RemoteCallback clientStatusCallback) {
+ IAmbientContextObserver observer) {
Slog.d(TAG, "Requested detection of " + request.getEventTypes());
synchronized (mLock) {
if (setUpServiceIfNeeded()) {
ensureRemoteServiceInitiated();
- mRemoteService.startDetection(request, callingPackage, detectionResultCallback,
- getServerStatusCallback(clientStatusCallback));
+ mRemoteService.startDetection(request, callingPackage,
+ createDetectionResultRemoteCallback(),
+ getServerStatusCallback(
+ statusCode -> completeRegistration(observer, statusCode)));
} else {
Slog.w(TAG, "No valid component found for AmbientContextDetectionService");
- sendStatusToCallback(clientStatusCallback,
+ completeRegistration(observer,
AmbientContextManager.STATUS_NOT_SUPPORTED);
}
}
}
/**
- * Sends an intent with a status code and empty events.
+ * Sends the result response with the specified status to the callback.
*/
- void sendStatusCallback(RemoteCallback statusCallback, int statusCode) {
+ static void sendStatusCallback(RemoteCallback statusCallback,
+ @AmbientContextManager.StatusCode int statusCode) {
Bundle bundle = new Bundle();
bundle.putInt(
AmbientContextManager.STATUS_RESPONSE_BUNDLE_KEY,
@@ -236,6 +233,15 @@
statusCallback.sendResult(bundle);
}
+ static void completeRegistration(IAmbientContextObserver observer, int statusCode) {
+ try {
+ observer.onRegistrationComplete(statusCode);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call IAmbientContextObserver.onRegistrationComplete: "
+ + e.getMessage());
+ }
+ }
+
/**
* Unregisters the client from all previously registered events by removing from the
* mExistingRequests map, and unregister events from the service if those events are not
@@ -255,7 +261,7 @@
synchronized (mLock) {
if (!setUpServiceIfNeeded()) {
Slog.w(TAG, "Detection service is not available at this moment.");
- sendStatusToCallback(statusCallback,
+ sendStatusCallback(statusCallback,
AmbientContextManager.STATUS_NOT_SUPPORTED);
return;
}
@@ -263,7 +269,8 @@
mRemoteService.queryServiceStatus(
eventTypes,
callingPackage,
- getServerStatusCallback(statusCallback));
+ getServerStatusCallback(
+ statusCode -> sendStatusCallback(statusCallback, statusCode)));
}
}
@@ -350,18 +357,6 @@
return ComponentName.unflattenFromString(consentComponent);
}
- /**
- * Sends the result response with the specified status to the callback.
- */
- void sendStatusToCallback(RemoteCallback callback,
- @AmbientContextManager.StatusCode int status) {
- Bundle bundle = new Bundle();
- bundle.putInt(
- AmbientContextManager.STATUS_RESPONSE_BUNDLE_KEY,
- status);
- callback.sendResult(bundle);
- }
-
@VisibleForTesting
void stopDetection(String packageName) {
Slog.d(TAG, "Stop detection for " + packageName);
@@ -377,13 +372,13 @@
* Sends out the Intent to the client after the event is detected.
*
* @param pendingIntent Client's PendingIntent for callback
- * @param result result from the detection service
+ * @param events detected events from the detection service
*/
- private void sendDetectionResultIntent(PendingIntent pendingIntent,
- AmbientContextDetectionResult result) {
+ void sendDetectionResultIntent(PendingIntent pendingIntent,
+ List<AmbientContextEvent> events) {
Intent intent = new Intent();
intent.putExtra(AmbientContextManager.EXTRA_AMBIENT_CONTEXT_EVENTS,
- new ArrayList(result.getEvents()));
+ new ArrayList(events));
// Explicitly disallow the receiver from starting activities, to prevent apps from utilizing
// the PendingIntent as a backdoor to do this.
BroadcastOptions options = BroadcastOptions.makeBasic();
@@ -392,7 +387,7 @@
pendingIntent.send(getContext(), 0, intent, null, null, null,
options.toBundle());
Slog.i(TAG, "Sending PendingIntent to " + pendingIntent.getCreatorPackage() + ": "
- + result);
+ + events);
} catch (PendingIntent.CanceledException e) {
Slog.w(TAG, "Couldn't deliver pendingIntent:" + pendingIntent);
}
@@ -405,16 +400,19 @@
(AmbientContextDetectionResult) result.get(
AmbientContextDetectionResult.RESULT_RESPONSE_BUNDLE_KEY);
String packageName = detectionResult.getPackageName();
- PendingIntent pendingIntent = mMaster.getPendingIntent(mUserId, packageName);
- if (pendingIntent == null) {
+ IAmbientContextObserver observer = mMaster.getClientRequestObserver(
+ mUserId, packageName);
+ if (observer == null) {
return;
}
final long token = Binder.clearCallingIdentity();
try {
- sendDetectionResultIntent(pendingIntent, detectionResult);
+ observer.onEvents(detectionResult.getEvents());
Slog.i(TAG, "Got detection result of " + detectionResult.getEvents()
+ " for " + packageName);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call IAmbientContextObserver.onEvents: " + e.getMessage());
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
index 4206262..e205e84 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
@@ -27,10 +27,12 @@
import android.app.ambientcontext.AmbientContextEventRequest;
import android.app.ambientcontext.AmbientContextManager;
import android.app.ambientcontext.IAmbientContextManager;
+import android.app.ambientcontext.IAmbientContextObserver;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManagerInternal;
import android.os.RemoteCallback;
+import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
@@ -48,6 +50,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -67,31 +70,27 @@
static class ClientRequest {
private final int mUserId;
private final AmbientContextEventRequest mRequest;
- private final PendingIntent mPendingIntent;
- private final RemoteCallback mClientStatusCallback;
+ private final String mPackageName;
+ private final IAmbientContextObserver mObserver;
ClientRequest(int userId, AmbientContextEventRequest request,
- PendingIntent pendingIntent, RemoteCallback clientStatusCallback) {
+ String packageName, IAmbientContextObserver observer) {
this.mUserId = userId;
this.mRequest = request;
- this.mPendingIntent = pendingIntent;
- this.mClientStatusCallback = clientStatusCallback;
+ this.mPackageName = packageName;
+ this.mObserver = observer;
}
String getPackageName() {
- return mPendingIntent.getCreatorPackage();
+ return mPackageName;
}
AmbientContextEventRequest getRequest() {
return mRequest;
}
- PendingIntent getPendingIntent() {
- return mPendingIntent;
- }
-
- RemoteCallback getClientStatusCallback() {
- return mClientStatusCallback;
+ IAmbientContextObserver getObserver() {
+ return mObserver;
}
boolean hasUserId(int userId) {
@@ -139,16 +138,16 @@
}
void newClientAdded(int userId, AmbientContextEventRequest request,
- PendingIntent pendingIntent, RemoteCallback clientStatusCallback) {
- Slog.d(TAG, "New client added: " + pendingIntent.getCreatorPackage());
+ String callingPackage, IAmbientContextObserver observer) {
+ Slog.d(TAG, "New client added: " + callingPackage);
// Remove any existing ClientRequest for this user and package.
mExistingClientRequests.removeAll(
- findExistingRequests(userId, pendingIntent.getCreatorPackage()));
+ findExistingRequests(userId, callingPackage));
// Add to existing ClientRequests
mExistingClientRequests.add(
- new ClientRequest(userId, request, pendingIntent, clientStatusCallback));
+ new ClientRequest(userId, request, callingPackage, observer));
}
void clientRemoved(int userId, String packageName) {
@@ -167,10 +166,10 @@
}
@Nullable
- PendingIntent getPendingIntent(int userId, String packageName) {
+ IAmbientContextObserver getClientRequestObserver(int userId, String packageName) {
for (ClientRequest clientRequest : mExistingClientRequests) {
if (clientRequest.hasUserIdAndPackageName(userId, packageName)) {
- return clientRequest.getPendingIntent();
+ return clientRequest.getObserver();
}
}
return null;
@@ -236,15 +235,13 @@
* Requires ACCESS_AMBIENT_CONTEXT_EVENT permission.
*/
void startDetection(@UserIdInt int userId, AmbientContextEventRequest request,
- String packageName, RemoteCallback detectionResultCallback,
- RemoteCallback statusCallback) {
+ String packageName, IAmbientContextObserver observer) {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
synchronized (mLock) {
final AmbientContextManagerPerUserService service = getServiceForUserLocked(userId);
if (service != null) {
- service.startDetection(request, packageName, detectionResultCallback,
- statusCallback);
+ service.startDetection(request, packageName, observer);
} else {
Slog.i(TAG, "service not available for user_id: " + userId);
}
@@ -297,8 +294,7 @@
Slog.d(TAG, "Restoring detection for " + clientRequest.getPackageName());
service.startDetection(clientRequest.getRequest(),
clientRequest.getPackageName(),
- service.createDetectionResultRemoteCallback(),
- clientRequest.getClientStatusCallback());
+ clientRequest.getObserver());
}
}
}
@@ -328,16 +324,45 @@
Objects.requireNonNull(request);
Objects.requireNonNull(resultPendingIntent);
Objects.requireNonNull(statusCallback);
+ // Wrap the PendingIntent and statusCallback in a IAmbientContextObserver to make the
+ // code unified
+ IAmbientContextObserver observer = new IAmbientContextObserver.Stub() {
+ @Override
+ public void onEvents(List<AmbientContextEvent> events) throws RemoteException {
+ mService.sendDetectionResultIntent(resultPendingIntent, events);
+ }
+
+ @Override
+ public void onRegistrationComplete(int statusCode) throws RemoteException {
+ AmbientContextManagerPerUserService.sendStatusCallback(statusCallback,
+ statusCode);
+ }
+ };
+ registerObserverWithCallback(request, resultPendingIntent.getCreatorPackage(),
+ observer);
+ }
+
+ /**
+ * Register an observer for Ambient Context events.
+ */
+ @Override
+ public void registerObserverWithCallback(AmbientContextEventRequest request,
+ String packageName,
+ IAmbientContextObserver observer) {
+ Slog.i(TAG, "AmbientContextManagerService registerObserverWithCallback.");
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(observer);
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
- assertCalledByPackageOwner(resultPendingIntent.getCreatorPackage());
+ assertCalledByPackageOwner(packageName);
if (!mIsServiceEnabled) {
Slog.w(TAG, "Service not available.");
- mService.sendStatusCallback(statusCallback,
+ AmbientContextManagerPerUserService.completeRegistration(observer,
AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
return;
}
- mService.onRegisterObserver(request, resultPendingIntent, statusCallback);
+ mService.onRegisterObserver(request, packageName, observer);
}
@Override
@@ -359,7 +384,7 @@
assertCalledByPackageOwner(callingPackage);
if (!mIsServiceEnabled) {
Slog.w(TAG, "Detection service not available.");
- mService.sendStatusToCallback(statusCallback,
+ AmbientContextManagerPerUserService.sendStatusCallback(statusCallback,
AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
return;
}
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java b/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java
index e2b22dc..a3ffcde8 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java
@@ -21,14 +21,16 @@
import android.annotation.NonNull;
import android.app.ambientcontext.AmbientContextEvent;
import android.app.ambientcontext.AmbientContextEventRequest;
+import android.app.ambientcontext.AmbientContextManager;
+import android.app.ambientcontext.IAmbientContextObserver;
import android.content.ComponentName;
import android.os.Binder;
import android.os.RemoteCallback;
+import android.os.RemoteException;
import android.os.ShellCommand;
-import android.service.ambientcontext.AmbientContextDetectionResult;
-import android.service.ambientcontext.AmbientContextDetectionServiceStatus;
import java.io.PrintWriter;
+import java.util.List;
/**
* Shell command for {@link AmbientContextManagerService}.
@@ -39,6 +41,7 @@
new AmbientContextEventRequest.Builder()
.addEventType(AmbientContextEvent.EVENT_COUGH)
.addEventType(AmbientContextEvent.EVENT_SNORE)
+ .addEventType(AmbientContextEvent.EVENT_BACK_DOUBLE_TAP)
.build();
@NonNull
@@ -50,43 +53,40 @@
/** Callbacks for AmbientContextEventService results used internally for testing. */
static class TestableCallbackInternal {
- private AmbientContextDetectionResult mLastResult;
- private AmbientContextDetectionServiceStatus mLastStatus;
+ private List<AmbientContextEvent> mLastEvents;
+ private int mLastStatus;
- public AmbientContextDetectionResult getLastResult() {
- return mLastResult;
+ public List<AmbientContextEvent> getLastEvents() {
+ return mLastEvents;
}
- public AmbientContextDetectionServiceStatus getLastStatus() {
+ public int getLastStatus() {
return mLastStatus;
}
@NonNull
- private RemoteCallback createRemoteDetectionResultCallback() {
- return new RemoteCallback(result -> {
- AmbientContextDetectionResult detectionResult =
- (AmbientContextDetectionResult) result.get(
- AmbientContextDetectionResult.RESULT_RESPONSE_BUNDLE_KEY);
- final long token = Binder.clearCallingIdentity();
- try {
- mLastResult = detectionResult;
- out.println("Detection result available: " + detectionResult);
- } finally {
- Binder.restoreCallingIdentity(token);
+ private IAmbientContextObserver createAmbientContextObserver() {
+ return new IAmbientContextObserver.Stub() {
+ @Override
+ public void onEvents(List<AmbientContextEvent> events) throws RemoteException {
+ mLastEvents = events;
+ out.println("Detection events available: " + events);
}
- });
+
+ @Override
+ public void onRegistrationComplete(int statusCode) throws RemoteException {
+ mLastStatus = statusCode;
+ }
+ };
}
@NonNull
private RemoteCallback createRemoteStatusCallback() {
return new RemoteCallback(result -> {
- AmbientContextDetectionServiceStatus status =
- (AmbientContextDetectionServiceStatus) result.get(
- AmbientContextDetectionServiceStatus.STATUS_RESPONSE_BUNDLE_KEY);
+ int status = result.getInt(AmbientContextManager.STATUS_RESPONSE_BUNDLE_KEY);
final long token = Binder.clearCallingIdentity();
try {
mLastStatus = status;
- out.println("Status available: " + status);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -110,8 +110,6 @@
return runStopDetection();
case "get-last-status-code":
return getLastStatusCode();
- case "get-last-package-name":
- return getLastPackageName();
case "query-service-status":
return runQueryServiceStatus();
case "get-bound-package":
@@ -126,9 +124,9 @@
private int runStartDetection() {
final int userId = Integer.parseInt(getNextArgRequired());
final String packageName = getNextArgRequired();
- mService.startDetection(userId, REQUEST, packageName,
- sTestableCallbackInternal.createRemoteDetectionResultCallback(),
- sTestableCallbackInternal.createRemoteStatusCallback());
+ mService.startDetection(
+ userId, REQUEST, packageName,
+ sTestableCallbackInternal.createAmbientContextObserver());
return 0;
}
@@ -151,18 +149,9 @@
}
private int getLastStatusCode() {
- AmbientContextDetectionServiceStatus lastResponse =
- sTestableCallbackInternal.getLastStatus();
- if (lastResponse == null) {
- return -1;
- }
- return lastResponse.getStatusCode();
- }
-
- private int getLastPackageName() {
- AmbientContextDetectionServiceStatus lastResponse =
- sTestableCallbackInternal.getLastStatus();
- out.println(lastResponse == null ? "" : lastResponse.getPackageName());
+ final PrintWriter resultPrinter = getOutPrintWriter();
+ int lastStatus = sTestableCallbackInternal.getLastStatus();
+ resultPrinter.println(lastStatus);
return 0;
}
@@ -174,22 +163,21 @@
pw.println(" Print this help text.");
pw.println();
pw.println(" start-detection USER_ID PACKAGE_NAME: Starts AmbientContextEvent detection.");
- pw.println(" stop-detection USER_ID: Stops AmbientContextEvent detection.");
+ pw.println(" stop-detection USER_ID PACKAGE_NAME: Stops AmbientContextEvent detection.");
pw.println(" get-last-status-code: Prints the latest request status code.");
- pw.println(" get-last-package-name: Prints the latest request package name.");
- pw.println(" query-event-status USER_ID PACKAGE_NAME: Prints the event status code.");
+ pw.println(" query-service-status USER_ID PACKAGE_NAME: Prints the service status code.");
pw.println(" get-bound-package USER_ID:"
+ " Print the bound package that implements the service.");
- pw.println(" set-temporary-service USER_ID [COMPONENT_NAME DURATION]");
+ pw.println(" set-temporary-service USER_ID [PACKAGE_NAME] [COMPONENT_NAME DURATION]");
pw.println(" Temporarily (for DURATION ms) changes the service implementation.");
pw.println(" To reset, call with just the USER_ID argument.");
}
private int getBoundPackageName() {
- final PrintWriter out = getOutPrintWriter();
+ final PrintWriter resultPrinter = getOutPrintWriter();
final int userId = Integer.parseInt(getNextArgRequired());
final ComponentName componentName = mService.getComponentName(userId);
- out.println(componentName == null ? "" : componentName.getPackageName());
+ resultPrinter.println(componentName == null ? "" : componentName.getPackageName());
return 0;
}
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index dd73cbe..15c569e 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -554,31 +554,24 @@
private static final String GAME_MODE_CONFIG_NODE_NAME = "game-mode-config";
private final String mPackageName;
private final ArrayMap<Integer, GameModeConfiguration> mModeConfigs;
- private boolean mPerfModeOptedIn;
- private boolean mBatteryModeOptedIn;
- private boolean mAllowDownscale;
- private boolean mAllowAngle;
- private boolean mAllowFpsOverride;
+ private boolean mPerfModeOptedIn = false;
+ private boolean mBatteryModeOptedIn = false;
+ private boolean mAllowDownscale = true;
+ private boolean mAllowAngle = true;
+ private boolean mAllowFpsOverride = true;
GamePackageConfiguration(String packageName, int userId) {
mPackageName = packageName;
mModeConfigs = new ArrayMap<>();
+
try {
final ApplicationInfo ai = mPackageManager.getApplicationInfoAsUser(packageName,
PackageManager.GET_META_DATA, userId);
- if (!parseInterventionFromXml(ai, packageName)) {
- if (ai.metaData != null) {
- mPerfModeOptedIn = ai.metaData.getBoolean(METADATA_PERFORMANCE_MODE_ENABLE);
- mBatteryModeOptedIn = ai.metaData.getBoolean(METADATA_BATTERY_MODE_ENABLE);
- mAllowDownscale = ai.metaData.getBoolean(METADATA_WM_ALLOW_DOWNSCALE, true);
- mAllowAngle = ai.metaData.getBoolean(METADATA_ANGLE_ALLOW_ANGLE, true);
- } else {
- mPerfModeOptedIn = false;
- mBatteryModeOptedIn = false;
- mAllowDownscale = true;
- mAllowAngle = true;
- mAllowFpsOverride = true;
- }
+ if (!parseInterventionFromXml(ai, packageName) && ai.metaData != null) {
+ mPerfModeOptedIn = ai.metaData.getBoolean(METADATA_PERFORMANCE_MODE_ENABLE);
+ mBatteryModeOptedIn = ai.metaData.getBoolean(METADATA_BATTERY_MODE_ENABLE);
+ mAllowDownscale = ai.metaData.getBoolean(METADATA_WM_ALLOW_DOWNSCALE, true);
+ mAllowAngle = ai.metaData.getBoolean(METADATA_ANGLE_ALLOW_ANGLE, true);
}
} catch (NameNotFoundException e) {
// Not all packages are installed, hence ignore those that are not installed yet.
@@ -641,6 +634,12 @@
}
}
} catch (NameNotFoundException | XmlPullParserException | IOException ex) {
+ // set flag back to default values when parsing fails
+ mPerfModeOptedIn = false;
+ mBatteryModeOptedIn = false;
+ mAllowDownscale = true;
+ mAllowAngle = true;
+ mAllowFpsOverride = true;
Slog.e(TAG, "Error while parsing XML meta-data for "
+ METADATA_GAME_MODE_CONFIG);
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 82fe6c6..2b8d6a33 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1770,8 +1770,8 @@
return;
}
Log.w(TAG, "Communication client died");
- removeCommunicationRouteClient(client.getBinder(), true);
- onUpdateCommunicationRouteClient("onCommunicationRouteClientDied");
+ setCommunicationRouteForClient(client.getBinder(), client.getPid(), null,
+ BtHelper.SCO_MODE_UNDEFINED, "onCommunicationRouteClientDied");
}
/**
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 0a081bf..0c4ea97 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1005,7 +1005,9 @@
mSfxHelper = new SoundEffectsHelper(mContext);
- mSpatializerHelper = new SpatializerHelper(this, mAudioSystem);
+ final boolean headTrackingDefault = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_spatial_audio_head_tracking_enabled_default);
+ mSpatializerHelper = new SpatializerHelper(this, mAudioSystem, headTrackingDefault);
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 5eaa948..8e8fd05 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -169,9 +169,20 @@
//------------------------------------------------------
// initialization
- SpatializerHelper(@NonNull AudioService mother, @NonNull AudioSystemAdapter asa) {
+ @SuppressWarnings("StaticAssignmentInConstructor")
+ SpatializerHelper(@NonNull AudioService mother, @NonNull AudioSystemAdapter asa,
+ boolean headTrackingEnabledByDefault) {
mAudioService = mother;
mASA = asa;
+ // "StaticAssignmentInConstructor" warning is suppressed as the SpatializerHelper being
+ // constructed here is the factory for SADeviceState, thus SADeviceState and its
+ // private static field sHeadTrackingEnabledDefault should never be accessed directly.
+ SADeviceState.sHeadTrackingEnabledDefault = headTrackingEnabledByDefault;
+ }
+
+ synchronized void initForTest(boolean hasBinaural, boolean hasTransaural) {
+ mBinauralSupported = hasBinaural;
+ mTransauralSupported = hasTransaural;
}
synchronized void init(boolean effectExpected, @Nullable String settings) {
@@ -571,7 +582,9 @@
// There may be different devices with the same device type (aliasing).
// We always send the full device state info on each change.
private void logDeviceState(SADeviceState deviceState, String event) {
- final String deviceName = AudioSystem.getDeviceName(deviceState.mDeviceType);
+ final int deviceType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(
+ deviceState.mDeviceType);
+ final String deviceName = AudioSystem.getDeviceName(deviceType);
new MediaMetrics.Item(METRICS_DEVICE_PREFIX + deviceName)
.set(MediaMetrics.Property.ADDRESS, deviceState.mDeviceAddress)
.set(MediaMetrics.Property.ENABLED, deviceState.mEnabled ? "true" : "false")
@@ -1113,6 +1126,9 @@
&& ROUTING_DEVICES[0].getAddress().equals(ada.getAddress())) {
setDesiredHeadTrackingMode(enabled ? mDesiredHeadTrackingModeWhenEnabled
: Spatializer.HEAD_TRACKING_MODE_DISABLED);
+ if (enabled && !mHeadTrackerAvailable) {
+ postInitSensors();
+ }
}
}
@@ -1497,18 +1513,26 @@
}
/*package*/ static final class SADeviceState {
+ private static boolean sHeadTrackingEnabledDefault = false;
final @AudioDeviceInfo.AudioDeviceType int mDeviceType;
final @NonNull String mDeviceAddress;
boolean mEnabled = true; // by default, SA is enabled on any device
boolean mHasHeadTracker = false;
- boolean mHeadTrackerEnabled = true; // by default, if head tracker is present, use it
+ boolean mHeadTrackerEnabled;
static final String SETTING_FIELD_SEPARATOR = ",";
static final String SETTING_DEVICE_SEPARATOR_CHAR = "|";
static final String SETTING_DEVICE_SEPARATOR = "\\|";
- SADeviceState(@AudioDeviceInfo.AudioDeviceType int deviceType, @NonNull String address) {
+ /**
+ * Constructor
+ * @param deviceType
+ * @param address must be non-null for wireless devices
+ * @throws NullPointerException if a null address is passed for a wireless device
+ */
+ SADeviceState(@AudioDeviceInfo.AudioDeviceType int deviceType, @Nullable String address) {
mDeviceType = deviceType;
mDeviceAddress = isWireless(deviceType) ? Objects.requireNonNull(address) : "";
+ mHeadTrackerEnabled = sHeadTrackingEnabledDefault;
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/log/ALSProbe.java b/services/core/java/com/android/server/biometrics/log/ALSProbe.java
new file mode 100644
index 0000000..62f94ed
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/log/ALSProbe.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.log;
+
+import android.annotation.DurationMillisLong;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
+
+import java.util.concurrent.TimeUnit;
+
+/** Probe for ambient light. */
+final class ALSProbe implements Probe {
+ private static final String TAG = "ALSProbe";
+
+ @Nullable
+ private final SensorManager mSensorManager;
+ @Nullable
+ private final Sensor mLightSensor;
+ @NonNull
+ private final Handler mTimer;
+ @DurationMillisLong
+ private long mMaxSubscriptionTime = -1;
+
+ private boolean mEnabled = false;
+ private boolean mDestroyed = false;
+ private volatile float mLastAmbientLux = -1;
+
+ private final SensorEventListener mLightSensorListener = new SensorEventListener() {
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ mLastAmbientLux = event.values[0];
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ // Not used.
+ }
+ };
+
+ /**
+ * Create a probe with a 1-minute max sampling time.
+ *
+ * @param sensorManager Sensor manager
+ */
+ ALSProbe(@NonNull SensorManager sensorManager) {
+ this(sensorManager, new Handler(Looper.getMainLooper()),
+ TimeUnit.MINUTES.toMillis(1));
+ }
+
+ /**
+ * Create a probe with a given max sampling time.
+ *
+ * Note: The max time is a workaround for potential scheduler bugs where
+ * {@link BaseClientMonitor#destroy()} is not called due to an abnormal lifecycle. Clients
+ * should ensure that {@link #disable()} and {@link #destroy()} are called appropriately and
+ * avoid relying on this timeout to unsubscribe from the sensor when it is not needed.
+ *
+ * @param sensorManager Sensor manager
+ * @param handler Timeout handler
+ * @param maxTime The max amount of time to subscribe to events. If this time is exceeded
+ * {@link #disable()} will be called and no sampling will occur until {@link
+ * #enable()} is called again.
+ */
+ @VisibleForTesting
+ ALSProbe(@Nullable SensorManager sensorManager, @NonNull Handler handler,
+ @DurationMillisLong long maxTime) {
+ mSensorManager = sensorManager;
+ mLightSensor = sensorManager != null
+ ? sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) : null;
+ mTimer = handler;
+ mMaxSubscriptionTime = maxTime;
+
+ if (mSensorManager == null || mLightSensor == null) {
+ Slog.w(TAG, "No sensor - probe disabled");
+ mDestroyed = true;
+ }
+ }
+
+ @Override
+ public synchronized void enable() {
+ if (!mDestroyed) {
+ enableLightSensorLoggingLocked();
+ }
+ }
+
+ @Override
+ public synchronized void disable() {
+ if (!mDestroyed) {
+ disableLightSensorLoggingLocked();
+ }
+ }
+
+ @Override
+ public synchronized void destroy() {
+ disable();
+ mDestroyed = true;
+ }
+
+ /** The most recent lux reading. */
+ public float getCurrentLux() {
+ return mLastAmbientLux;
+ }
+
+ private void enableLightSensorLoggingLocked() {
+ if (!mEnabled) {
+ mEnabled = true;
+ mLastAmbientLux = -1;
+ mSensorManager.registerListener(mLightSensorListener, mLightSensor,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ Slog.v(TAG, "Enable ALS: " + mLightSensorListener.hashCode());
+ }
+
+ resetTimerLocked(true /* start */);
+ }
+
+ private void disableLightSensorLoggingLocked() {
+ resetTimerLocked(false /* start */);
+
+ if (mEnabled) {
+ mEnabled = false;
+ mLastAmbientLux = -1;
+ mSensorManager.unregisterListener(mLightSensorListener);
+ Slog.v(TAG, "Disable ALS: " + mLightSensorListener.hashCode());
+ }
+ }
+
+ private void resetTimerLocked(boolean start) {
+ mTimer.removeCallbacksAndMessages(this /* token */);
+ if (start && mMaxSubscriptionTime > 0) {
+ mTimer.postDelayed(this::onTimeout, this /* token */, mMaxSubscriptionTime);
+ }
+ }
+
+ private void onTimeout() {
+ Slog.e(TAG, "Max time exceeded for ALS logger - disabling: "
+ + mLightSensorListener.hashCode());
+ disable();
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContext.java b/services/core/java/com/android/server/biometrics/log/BiometricContext.java
index c86a8cb..8265203 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricContext.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricContext.java
@@ -46,6 +46,9 @@
/** If the display is in AOD. */
boolean isAod();
+ /** If the device is awake or is becoming awake. */
+ boolean isAwake();
+
/**
* Subscribe to context changes.
*
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
index 9d2fde7..3d1a634 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
@@ -43,7 +43,7 @@
/**
* A default provider for {@link BiometricContext}.
*/
-class BiometricContextProvider implements BiometricContext {
+final class BiometricContextProvider implements BiometricContext {
private static final String TAG = "BiometricContextProvider";
@@ -76,7 +76,8 @@
private final Map<Integer, InstanceId> mSession = new ConcurrentHashMap<>();
private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
- private boolean mIsDozing = false;
+ private boolean mIsAod = false;
+ private boolean mIsAwake = false;
@VisibleForTesting
BiometricContextProvider(@NonNull AmbientDisplayConfiguration ambientDisplayConfiguration,
@@ -85,9 +86,14 @@
try {
service.setBiometicContextListener(new IBiometricContextListener.Stub() {
@Override
- public void onDozeChanged(boolean isDozing) {
- mIsDozing = isDozing;
- notifyChanged();
+ public void onDozeChanged(boolean isDozing, boolean isAwake) {
+ isDozing = isDozing && isAodEnabled();
+ final boolean changed = (mIsAod != isDozing) || (mIsAwake != isAwake);
+ if (changed) {
+ mIsAod = isDozing;
+ mIsAwake = isAwake;
+ notifyChanged();
+ }
}
private void notifyChanged() {
@@ -97,6 +103,10 @@
notifySubscribers();
}
}
+
+ private boolean isAodEnabled() {
+ return mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
+ }
});
service.registerSessionListener(SESSION_TYPES, new ISessionListener.Stub() {
@Override
@@ -161,7 +171,12 @@
@Override
public boolean isAod() {
- return mIsDozing && mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
+ return mIsAod;
+ }
+
+ @Override
+ public boolean isAwake() {
+ return mIsAwake;
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
index 262be08..02b350e 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
@@ -17,21 +17,15 @@
package com.android.server.biometrics.log;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.common.OperationContext;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
-import android.util.Log;
import android.util.Slog;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.biometrics.Utils;
@@ -43,61 +37,16 @@
public static final String TAG = "BiometricLogger";
public static final boolean DEBUG = false;
- private static final Object sLock = new Object();
-
- @GuardedBy("sLock")
- private static int sAlsCounter;
private final int mStatsModality;
private final int mStatsAction;
private final int mStatsClient;
private final BiometricFrameworkStatsLogger mSink;
- @NonNull private final SensorManager mSensorManager;
+ @NonNull private final ALSProbe mALSProbe;
private long mFirstAcquireTimeMs;
- private boolean mLightSensorEnabled = false;
private boolean mShouldLogMetrics = true;
- private class ALSProbe implements Probe {
- private boolean mDestroyed = false;
-
- @Override
- public synchronized void enable() {
- if (!mDestroyed) {
- setLightSensorLoggingEnabled(getAmbientLightSensor(mSensorManager));
- }
- }
-
- @Override
- public synchronized void disable() {
- if (!mDestroyed) {
- setLightSensorLoggingEnabled(null);
- }
- }
-
- @Override
- public synchronized void destroy() {
- disable();
- mDestroyed = true;
- }
- }
-
- // report only the most recent value
- // consider com.android.server.display.utils.AmbientFilter or similar if need arises
- private volatile float mLastAmbientLux = 0;
-
- private final SensorEventListener mLightSensorListener = new SensorEventListener() {
- @Override
- public void onSensorChanged(SensorEvent event) {
- mLastAmbientLux = event.values[0];
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- // Not used.
- }
- };
-
/** Get a new logger with all unknown fields (for operations that do not require logs). */
public static BiometricLogger ofUnknown(@NonNull Context context) {
return new BiometricLogger(context, BiometricsProtoEnums.MODALITY_UNKNOWN,
@@ -105,6 +54,11 @@
}
/**
+ * Creates a new logger for an instance of a biometric operation.
+ *
+ * Do not reuse across operations. Instead, create a new one or use
+ * {@link #swapAction(Context, int)}.
+ *
* @param context system_server context
* @param statsModality One of {@link BiometricsProtoEnums} MODALITY_* constants.
* @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants.
@@ -125,7 +79,7 @@
mStatsAction = statsAction;
mStatsClient = statsClient;
mSink = logSink;
- mSensorManager = sensorManager;
+ mALSProbe = new ALSProbe(sensorManager);
}
/** Creates a new logger with the action replaced with the new action. */
@@ -136,6 +90,7 @@
/** Disable logging metrics and only log critical events, such as system health issues. */
public void disableMetrics() {
mShouldLogMetrics = false;
+ mALSProbe.destroy();
}
/** {@link BiometricsProtoEnums} CLIENT_* constants */
@@ -265,7 +220,7 @@
+ ", RequireConfirmation: " + requireConfirmation
+ ", State: " + authState
+ ", Latency: " + latency
- + ", Lux: " + mLastAmbientLux);
+ + ", Lux: " + mALSProbe.getCurrentLux());
} else {
Slog.v(TAG, "Authentication latency: " + latency);
}
@@ -276,7 +231,7 @@
mSink.authenticate(operationContext, mStatsModality, mStatsAction, mStatsClient,
Utils.isDebugEnabled(context, targetUserId),
- latency, authState, requireConfirmation, targetUserId, mLastAmbientLux);
+ latency, authState, requireConfirmation, targetUserId, mALSProbe.getCurrentLux());
}
/** Log enrollment outcome. */
@@ -290,7 +245,7 @@
+ ", User: " + targetUserId
+ ", Client: " + mStatsClient
+ ", Latency: " + latency
- + ", Lux: " + mLastAmbientLux
+ + ", Lux: " + mALSProbe.getCurrentLux()
+ ", Success: " + enrollSuccessful);
} else {
Slog.v(TAG, "Enroll latency: " + latency);
@@ -301,7 +256,7 @@
}
mSink.enroll(mStatsModality, mStatsAction, mStatsClient,
- targetUserId, latency, enrollSuccessful, mLastAmbientLux);
+ targetUserId, latency, enrollSuccessful, mALSProbe.getCurrentLux());
}
/** Report unexpected enrollment reported by the HAL. */
@@ -323,7 +278,9 @@
}
/**
- * Get a callback to start/stop ALS capture when a client runs.
+ * Get a callback to start/stop ALS capture when the client runs. Do not create
+ * multiple callbacks since there is at most one light sensor (they will all share
+ * a single probe sampling from that sensor).
*
* If the probe should not run for the entire operation, do not set startWithClient and
* start/stop the problem when needed.
@@ -331,53 +288,7 @@
* @param startWithClient if probe should start automatically when the operation starts.
*/
@NonNull
- public CallbackWithProbe<Probe> createALSCallback(boolean startWithClient) {
- return new CallbackWithProbe<>(new ALSProbe(), startWithClient);
- }
-
- /** The sensor to use for ALS logging. */
- @Nullable
- protected Sensor getAmbientLightSensor(@NonNull SensorManager sensorManager) {
- return mShouldLogMetrics ? sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) : null;
- }
-
- private void setLightSensorLoggingEnabled(@Nullable Sensor lightSensor) {
- if (DEBUG) {
- Slog.v(TAG, "capturing ambient light using: "
- + (lightSensor != null ? lightSensor : "[disabled]"));
- }
-
- if (lightSensor != null) {
- if (!mLightSensorEnabled) {
- mLightSensorEnabled = true;
- mLastAmbientLux = 0;
- int localAlsCounter;
- synchronized (sLock) {
- localAlsCounter = sAlsCounter++;
- }
-
- if (localAlsCounter == 0) {
- mSensorManager.registerListener(mLightSensorListener, lightSensor,
- SensorManager.SENSOR_DELAY_NORMAL);
- } else {
- Slog.e(TAG, "Ignoring request to subscribe to ALSProbe due to non-zero ALS"
- + " counter: " + localAlsCounter);
- Slog.e(TAG, Log.getStackTraceString(new Throwable()));
- }
- }
- } else {
- mLightSensorEnabled = false;
- mLastAmbientLux = 0;
- mSensorManager.unregisterListener(mLightSensorListener);
- int localAlsCounter;
- synchronized (sLock) {
- localAlsCounter = --sAlsCounter;
- }
- if (localAlsCounter != 0) {
- Slog.e(TAG, "Non-zero ALS counter after unsubscribing from ALSProbe: "
- + localAlsCounter);
- Slog.e(TAG, Log.getStackTraceString(new Throwable()));
- }
- }
+ public CallbackWithProbe<Probe> getAmbientLightProbe(boolean startWithClient) {
+ return new CallbackWithProbe<>(mALSProbe, startWithClient);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java
index 0d789f7..3566b43 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java
@@ -25,6 +25,7 @@
import android.annotation.NonNull;
import android.hardware.biometrics.BiometricStateListener;
import android.hardware.biometrics.IBiometricStateListener;
+import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
@@ -35,7 +36,7 @@
/**
* A callback for receiving notifications about biometric sensor state changes.
*/
-public class BiometricStateCallback implements ClientMonitorCallback {
+public class BiometricStateCallback implements ClientMonitorCallback, IBinder.DeathRecipient {
private static final String TAG = "BiometricStateCallback";
@@ -153,5 +154,25 @@
*/
public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
mBiometricStateListeners.add(listener);
+ try {
+ listener.asBinder().linkToDeath(this, 0 /* flags */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to link to death", e);
+ }
+ }
+
+ @Override
+ public void binderDied() {
+ // Do nothing, handled below
+ }
+
+ @Override
+ public void binderDied(IBinder who) {
+ Slog.w(TAG, "Callback binder died: " + who);
+ if (mBiometricStateListeners.removeIf(listener -> listener.asBinder().equals(who))) {
+ Slog.w(TAG, "Removed dead listener for " + who);
+ } else {
+ Slog.w(TAG, "No dead listeners found");
+ }
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index d0c58fd..ca4b747 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -131,7 +131,7 @@
@Override
protected ClientMonitorCallback wrapCallbackForStart(@NonNull ClientMonitorCallback callback) {
return new ClientMonitorCompositeCallback(
- getLogger().createALSCallback(true /* startWithClient */), callback);
+ getLogger().getAmbientLightProbe(true /* startWithClient */), callback);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index da78536..5d62cde 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -115,7 +115,7 @@
@Override
protected ClientMonitorCallback wrapCallbackForStart(@NonNull ClientMonitorCallback callback) {
return new ClientMonitorCompositeCallback(mPreviewHandleDeleterCallback,
- getLogger().createALSCallback(true /* startWithClient */), callback);
+ getLogger().getAmbientLightProbe(true /* startWithClient */), callback);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index 1935a5b..9baca98 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -101,7 +101,7 @@
@Override
protected ClientMonitorCallback wrapCallbackForStart(@NonNull ClientMonitorCallback callback) {
return new ClientMonitorCompositeCallback(
- getLogger().createALSCallback(true /* startWithClient */), callback);
+ getLogger().getAmbientLightProbe(true /* startWithClient */), callback);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
index 226e458..16d2f7a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
@@ -75,7 +75,7 @@
@Override
protected ClientMonitorCallback wrapCallbackForStart(@NonNull ClientMonitorCallback callback) {
return new ClientMonitorCompositeCallback(
- getLogger().createALSCallback(true /* startWithClient */), callback);
+ getLogger().getAmbientLightProbe(true /* startWithClient */), callback);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index e1626f0..b3f42be 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -16,6 +16,8 @@
package com.android.server.biometrics.sensors.fingerprint.aidl;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.TaskStackListener;
@@ -65,22 +67,28 @@
class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
implements Udfps, LockoutConsumer, PowerPressHandler {
private static final String TAG = "FingerprintAuthenticationClient";
-
- @NonNull private final LockoutCache mLockoutCache;
- @NonNull private final SensorOverlays mSensorOverlays;
- @NonNull private final FingerprintSensorPropertiesInternal mSensorProps;
- @NonNull private final CallbackWithProbe<Probe> mALSProbeCallback;
-
+ private static final int MESSAGE_IGNORE_AUTH = 1;
+ private static final int MESSAGE_AUTH_SUCCESS = 2;
+ private static final int MESSAGE_FINGER_UP = 3;
+ @NonNull
+ private final LockoutCache mLockoutCache;
+ @NonNull
+ private final SensorOverlays mSensorOverlays;
+ @NonNull
+ private final FingerprintSensorPropertiesInternal mSensorProps;
+ @NonNull
+ private final CallbackWithProbe<Probe> mALSProbeCallback;
+ private final Handler mHandler;
+ private final int mSkipWaitForPowerAcquireMessage;
+ private final int mSkipWaitForPowerVendorAcquireMessage;
+ private final long mFingerUpIgnoresPower = 500;
@Nullable
private ICancellationSignal mCancellationSignal;
private boolean mIsPointerDown;
- private final Handler mHandler;
-
- private static final int MESSAGE_IGNORE_AUTH = 1;
- private static final int MESSAGE_AUTH_SUCCESS = 2;
private long mWaitForAuthKeyguard;
private long mWaitForAuthBp;
private long mIgnoreAuthFor;
+ private Runnable mAuthSuccessRunnable;
FingerprintAuthenticationClient(
@NonNull Context context,
@@ -129,7 +137,7 @@
mLockoutCache = lockoutCache;
mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
mSensorProps = sensorProps;
- mALSProbeCallback = getLogger().createALSCallback(false /* startWithClient */);
+ mALSProbeCallback = getLogger().getAmbientLightProbe(false /* startWithClient */);
mHandler = handler;
mWaitForAuthKeyguard =
@@ -140,6 +148,13 @@
mIgnoreAuthFor =
context.getResources().getInteger(R.integer.config_sidefpsPostAuthDowntime);
+ mSkipWaitForPowerAcquireMessage =
+ context.getResources().getInteger(
+ R.integer.config_sidefpsSkipWaitForPowerAcquireMessage);
+ mSkipWaitForPowerVendorAcquireMessage =
+ context.getResources().getInteger(
+ R.integer.config_sidefpsSkipWaitForPowerVendorAcquireMessage);
+
if (mSensorProps.isAnySidefpsType()) {
if (Build.isDebuggable()) {
mWaitForAuthKeyguard = Settings.Secure.getIntForUser(context.getContentResolver(),
@@ -187,38 +202,55 @@
return false;
}
+ public void handleAuthenticate(
+ BiometricAuthenticator.Identifier identifier,
+ boolean authenticated,
+ ArrayList<Byte> token) {
+ if (authenticated && mSensorProps.isAnySidefpsType()) {
+ Slog.i(TAG, "(sideFPS): No power press detected, sending auth");
+ }
+ super.onAuthenticated(identifier, authenticated, token);
+ if (authenticated) {
+ mState = STATE_STOPPED;
+ mSensorOverlays.hide(getSensorId());
+ } else {
+ mState = STATE_STARTED_PAUSED_ATTEMPTED;
+ }
+ }
+
@Override
public void onAuthenticated(
BiometricAuthenticator.Identifier identifier,
boolean authenticated,
ArrayList<Byte> token) {
- long delay = 0;
- if (authenticated && mSensorProps.isAnySidefpsType()) {
- if (mHandler.hasMessages(MESSAGE_IGNORE_AUTH)) {
- Slog.i(TAG, "(sideFPS) Ignoring auth due to recent power press");
- onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true);
- return;
- }
- delay = isKeyguard() ? mWaitForAuthKeyguard : mWaitForAuthBp;
- Slog.i(TAG, "(sideFPS) Auth succeeded, sideFps waiting for power until: " + delay);
- }
-
- mHandler.postDelayed(
+ mHandler.post(
() -> {
+ long delay = 0;
if (authenticated && mSensorProps.isAnySidefpsType()) {
- Slog.i(TAG, "(sideFPS): No power press detected, sending auth");
+ if (mHandler.hasMessages(MESSAGE_IGNORE_AUTH)) {
+ Slog.i(TAG, "(sideFPS) Ignoring auth due to recent power press");
+ onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0,
+ true);
+ return;
+ }
+ delay = isKeyguard() ? mWaitForAuthKeyguard : mWaitForAuthBp;
+ Slog.i(TAG, "(sideFPS) Auth succeeded, sideFps waiting for power for: "
+ + delay + "ms");
}
- super.onAuthenticated(identifier, authenticated, token);
- if (authenticated) {
- mState = STATE_STOPPED;
- mSensorOverlays.hide(getSensorId());
- } else {
- mState = STATE_STARTED_PAUSED_ATTEMPTED;
+
+ if (mHandler.hasMessages(MESSAGE_FINGER_UP)) {
+ Slog.i(TAG, "Finger up detected, sending auth");
+ delay = 0;
}
- },
- MESSAGE_AUTH_SUCCESS,
- delay);
+
+ mAuthSuccessRunnable =
+ () -> handleAuthenticate(identifier, authenticated, token);
+ mHandler.postDelayed(
+ mAuthSuccessRunnable,
+ MESSAGE_AUTH_SUCCESS,
+ delay);
+ });
}
@Override
@@ -227,6 +259,30 @@
// for most ACQUIRED messages. See BiometricFingerprintConstants#FingerprintAcquired
mSensorOverlays.ifUdfps(controller -> controller.onAcquired(getSensorId(), acquiredInfo));
super.onAcquired(acquiredInfo, vendorCode);
+ if (mSensorProps.isAnySidefpsType()) {
+ final boolean shouldLookForVendor =
+ mSkipWaitForPowerAcquireMessage == FINGERPRINT_ACQUIRED_VENDOR;
+ final boolean acquireMessageMatch = acquiredInfo == mSkipWaitForPowerAcquireMessage;
+ final boolean vendorMessageMatch = vendorCode == mSkipWaitForPowerVendorAcquireMessage;
+ final boolean ignorePowerPress =
+ (acquireMessageMatch && !shouldLookForVendor) || (shouldLookForVendor
+ && acquireMessageMatch && vendorMessageMatch);
+
+ if (ignorePowerPress) {
+ Slog.d(TAG, "(sideFPS) onFingerUp");
+ mHandler.post(() -> {
+ if (mHandler.hasMessages(MESSAGE_AUTH_SUCCESS)) {
+ Slog.d(TAG, "(sideFPS) skipping wait for power");
+ mHandler.removeMessages(MESSAGE_AUTH_SUCCESS);
+ mHandler.post(mAuthSuccessRunnable);
+ } else {
+ mHandler.postDelayed(() -> {
+ }, MESSAGE_FINGER_UP, mFingerUpIgnoresPower);
+ }
+ });
+ }
+ }
+
}
@Override
@@ -259,21 +315,27 @@
private ICancellationSignal doAuthenticate() throws RemoteException {
final AidlSession session = getFreshDaemon();
+ final OperationContext opContext = getOperationContext();
+ getBiometricContext().subscribe(opContext, ctx -> {
+ if (session.hasContextMethods()) {
+ try {
+ session.getSession().onContextChanged(ctx);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to notify context changed", e);
+ }
+ }
+
+ // TODO(b/243836005): this should come via ctx
+ final boolean isAwake = getBiometricContext().isAwake();
+ if (isAwake) {
+ mALSProbeCallback.getProbe().enable();
+ } else {
+ mALSProbeCallback.getProbe().disable();
+ }
+ });
+
if (session.hasContextMethods()) {
- final OperationContext opContext = getOperationContext();
- final ICancellationSignal cancel =
- session.getSession().authenticateWithContext(mOperationId, opContext);
- getBiometricContext()
- .subscribe(
- opContext,
- ctx -> {
- try {
- session.getSession().onContextChanged(ctx);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to notify context changed", e);
- }
- });
- return cancel;
+ return session.getSession().authenticateWithContext(mOperationId, opContext);
} else {
return session.getSession().authenticate(mOperationId);
}
@@ -304,7 +366,6 @@
try {
mIsPointerDown = true;
mState = STATE_STARTED;
- mALSProbeCallback.getProbe().enable();
final AidlSession session = getFreshDaemon();
if (session.hasContextMethods()) {
@@ -333,7 +394,6 @@
try {
mIsPointerDown = false;
mState = STATE_STARTED_PAUSED_ATTEMPTED;
- mALSProbeCallback.getProbe().disable();
final AidlSession session = getFreshDaemon();
if (session.hasContextMethods()) {
@@ -418,14 +478,18 @@
public void onPowerPressed() {
if (mSensorProps.isAnySidefpsType()) {
Slog.i(TAG, "(sideFPS): onPowerPressed");
- if (mHandler.hasMessages(MESSAGE_AUTH_SUCCESS)) {
- Slog.i(TAG, "(sideFPS): Ignoring auth in queue");
- mHandler.removeMessages(MESSAGE_AUTH_SUCCESS);
- // Do not call onError() as that will send an additional callback to coex.
- onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true);
- }
- mHandler.removeMessages(MESSAGE_IGNORE_AUTH);
- mHandler.postDelayed(() -> {}, MESSAGE_IGNORE_AUTH, mIgnoreAuthFor);
+ mHandler.post(() -> {
+ if (mHandler.hasMessages(MESSAGE_AUTH_SUCCESS)) {
+ Slog.i(TAG, "(sideFPS): Ignoring auth in queue");
+ mHandler.removeMessages(MESSAGE_AUTH_SUCCESS);
+ // Do not call onError() as that will send an additional callback to coex.
+ onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true);
+ }
+ mHandler.removeMessages(MESSAGE_IGNORE_AUTH);
+ mHandler.postDelayed(() -> {
+ }, MESSAGE_IGNORE_AUTH, mIgnoreAuthFor);
+
+ });
}
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index f4f0a19..e0393b5 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -94,7 +94,7 @@
mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
mMaxTemplatesPerUser = maxTemplatesPerUser;
- mALSProbeCallback = getLogger().createALSCallback(false /* startWithClient */);
+ mALSProbeCallback = getLogger().getAmbientLightProbe(true /* startWithClient */);
mEnrollReason = enrollReason;
if (enrollReason == FingerprintManager.ENROLL_FIND_SENSOR) {
@@ -216,7 +216,6 @@
public void onPointerDown(int x, int y, float minor, float major) {
try {
mIsPointerDown = true;
- mALSProbeCallback.getProbe().enable();
final AidlSession session = getFreshDaemon();
if (session.hasContextMethods()) {
@@ -240,7 +239,6 @@
public void onPointerUp() {
try {
mIsPointerDown = false;
- mALSProbeCallback.getProbe().disable();
final AidlSession session = getFreshDaemon();
if (session.hasContextMethods()) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index 97fbb5f..7ed1a51 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -86,7 +86,7 @@
mLockoutFrameworkImpl = lockoutTracker;
mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
mSensorProps = sensorProps;
- mALSProbeCallback = getLogger().createALSCallback(false /* startWithClient */);
+ mALSProbeCallback = getLogger().getAmbientLightProbe(false /* startWithClient */);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
index 2a59c8c..5d9af53 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
@@ -84,7 +84,7 @@
@Override
protected ClientMonitorCallback wrapCallbackForStart(@NonNull ClientMonitorCallback callback) {
return new ClientMonitorCompositeCallback(
- getLogger().createALSCallback(true /* startWithClient */), callback);
+ getLogger().getAmbientLightProbe(true /* startWithClient */), callback);
}
@Override
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioEventLogger.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioEventLogger.java
new file mode 100644
index 0000000..48112c4
--- /dev/null
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioEventLogger.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.broadcastradio.hal2;
+
+import android.util.IndentingPrintWriter;
+import android.util.LocalLog;
+import android.util.Log;
+import android.util.Slog;
+
+final class RadioEventLogger {
+ private final String mTag;
+ private final LocalLog mEventLogger;
+
+ RadioEventLogger(String tag, int loggerQueueSize) {
+ mTag = tag;
+ mEventLogger = new LocalLog(loggerQueueSize);
+ }
+
+ void logRadioEvent(String logFormat, Object... args) {
+ String log = String.format(logFormat, args);
+ mEventLogger.log(log);
+ if (Log.isLoggable(mTag, Log.DEBUG)) {
+ Slog.d(mTag, log);
+ }
+ }
+
+ void dump(IndentingPrintWriter pw) {
+ mEventLogger.dump(pw);
+ }
+}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index 852aa66..0a23e38 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -55,12 +55,14 @@
class RadioModule {
private static final String TAG = "BcRadio2Srv.module";
+ private static final int RADIO_EVENT_LOGGER_QUEUE_SIZE = 25;
@NonNull private final IBroadcastRadio mService;
@NonNull public final RadioManager.ModuleProperties mProperties;
private final Object mLock;
@NonNull private final Handler mHandler;
+ @NonNull private final RadioEventLogger mEventLogger;
@GuardedBy("mLock")
private ITunerSession mHalTunerSession;
@@ -138,6 +140,7 @@
mService = Objects.requireNonNull(service);
mLock = Objects.requireNonNull(lock);
mHandler = new Handler(Looper.getMainLooper());
+ mEventLogger = new RadioEventLogger(TAG, RADIO_EVENT_LOGGER_QUEUE_SIZE);
}
public static @Nullable RadioModule tryLoadingModule(int idx, @NonNull String fqName,
@@ -176,13 +179,14 @@
public @NonNull TunerSession openSession(@NonNull android.hardware.radio.ITunerCallback userCb)
throws RemoteException {
- Slog.i(TAG, "Open TunerSession");
+ mEventLogger.logRadioEvent("Open TunerSession");
synchronized (mLock) {
if (mHalTunerSession == null) {
Mutable<ITunerSession> hwSession = new Mutable<>();
mService.openSession(mHalTunerCallback, (result, session) -> {
Convert.throwOnError("openSession", result);
hwSession.value = session;
+ mEventLogger.logRadioEvent("New HIDL 2.0 tuner session is opened");
});
mHalTunerSession = Objects.requireNonNull(hwSession.value);
}
@@ -207,7 +211,7 @@
// Copy the contents of mAidlTunerSessions into a local array because TunerSession.close()
// must be called without mAidlTunerSessions locked because it can call
// onTunerSessionClosed().
- Slog.i(TAG, "Close TunerSessions");
+ mEventLogger.logRadioEvent("Close TunerSessions");
TunerSession[] tunerSessions;
synchronized (mLock) {
tunerSessions = new TunerSession[mAidlTunerSessions.size()];
@@ -320,7 +324,7 @@
}
onTunerSessionProgramListFilterChanged(null);
if (mAidlTunerSessions.isEmpty() && mHalTunerSession != null) {
- Slog.i(TAG, "Closing HAL tuner session");
+ mEventLogger.logRadioEvent("Closing HAL tuner session");
try {
mHalTunerSession.close();
} catch (RemoteException ex) {
@@ -372,7 +376,7 @@
public android.hardware.radio.ICloseHandle addAnnouncementListener(@NonNull int[] enabledTypes,
@NonNull android.hardware.radio.IAnnouncementListener listener) throws RemoteException {
- Slog.i(TAG, "Add AnnouncementListener");
+ mEventLogger.logRadioEvent("Add AnnouncementListener");
ArrayList<Byte> enabledList = new ArrayList<>();
for (int type : enabledTypes) {
enabledList.add((byte)type);
@@ -409,7 +413,7 @@
}
Bitmap getImage(int id) {
- Slog.i(TAG, "Get image for id " + id);
+ mEventLogger.logRadioEvent("Get image for id %d", id);
if (id == 0) throw new IllegalArgumentException("Image ID is missing");
byte[] rawImage;
@@ -449,6 +453,10 @@
}
pw.decreaseIndent();
}
+ pw.printf("Radio module events:\n");
+ pw.increaseIndent();
+ mEventLogger.dump(pw);
+ pw.decreaseIndent();
pw.decreaseIndent();
}
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index 41f753c..918dc98 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -28,7 +28,6 @@
import android.hardware.radio.RadioManager;
import android.os.RemoteException;
import android.util.IndentingPrintWriter;
-import android.util.Log;
import android.util.MutableBoolean;
import android.util.MutableInt;
import android.util.Slog;
@@ -41,8 +40,10 @@
class TunerSession extends ITuner.Stub {
private static final String TAG = "BcRadio2Srv.session";
private static final String kAudioDeviceName = "Radio tuner source";
+ private static final int TUNER_EVENT_LOGGER_QUEUE_SIZE = 25;
private final Object mLock;
+ @NonNull private final RadioEventLogger mEventLogger;
private final RadioModule mModule;
private final ITunerSession mHwSession;
@@ -61,15 +62,12 @@
mHwSession = Objects.requireNonNull(hwSession);
mCallback = Objects.requireNonNull(callback);
mLock = Objects.requireNonNull(lock);
- }
-
- private boolean isDebugEnabled() {
- return Log.isLoggable(TAG, Log.DEBUG);
+ mEventLogger = new RadioEventLogger(TAG, TUNER_EVENT_LOGGER_QUEUE_SIZE);
}
@Override
public void close() {
- if (isDebugEnabled()) Slog.d(TAG, "Close");
+ mEventLogger.logRadioEvent("Close");
close(null);
}
@@ -81,7 +79,7 @@
* @param error Optional error to send to client before session is closed.
*/
public void close(@Nullable Integer error) {
- if (isDebugEnabled()) Slog.d(TAG, "Close on error " + error);
+ mEventLogger.logRadioEvent("Close on error %d", error);
synchronized (mLock) {
if (mIsClosed) return;
if (error != null) {
@@ -145,10 +143,8 @@
@Override
public void step(boolean directionDown, boolean skipSubChannel) throws RemoteException {
- if (isDebugEnabled()) {
- Slog.d(TAG, "Step with directionDown " + directionDown
- + " skipSubChannel " + skipSubChannel);
- }
+ mEventLogger.logRadioEvent("Step with direction %s, skipSubChannel? %s",
+ directionDown ? "down" : "up", skipSubChannel ? "yes" : "no");
synchronized (mLock) {
checkNotClosedLocked();
int halResult = mHwSession.step(!directionDown);
@@ -158,10 +154,8 @@
@Override
public void scan(boolean directionDown, boolean skipSubChannel) throws RemoteException {
- if (isDebugEnabled()) {
- Slog.d(TAG, "Scan with directionDown " + directionDown
- + " skipSubChannel " + skipSubChannel);
- }
+ mEventLogger.logRadioEvent("Scan with direction %s, skipSubChannel? %s",
+ directionDown ? "down" : "up", skipSubChannel ? "yes" : "no");
synchronized (mLock) {
checkNotClosedLocked();
int halResult = mHwSession.scan(!directionDown, skipSubChannel);
@@ -171,7 +165,7 @@
@Override
public void tune(ProgramSelector selector) throws RemoteException {
- if (isDebugEnabled()) Slog.d(TAG, "Tune with selector " + selector);
+ mEventLogger.logRadioEvent("Tune with selector %s", selector);
synchronized (mLock) {
checkNotClosedLocked();
int halResult = mHwSession.tune(Convert.programSelectorToHal(selector));
@@ -195,7 +189,7 @@
@Override
public Bitmap getImage(int id) {
- if (isDebugEnabled()) Slog.d(TAG, "Get image for " + id);
+ mEventLogger.logRadioEvent("Get image for %d", id);
return mModule.getImage(id);
}
@@ -208,7 +202,7 @@
@Override
public void startProgramListUpdates(ProgramList.Filter filter) throws RemoteException {
- if (isDebugEnabled()) Slog.d(TAG, "start programList updates " + filter);
+ mEventLogger.logRadioEvent("start programList updates %s", filter);
// If the AIDL client provides a null filter, it wants all updates, so use the most broad
// filter.
if (filter == null) {
@@ -267,7 +261,7 @@
@Override
public void stopProgramListUpdates() throws RemoteException {
- if (isDebugEnabled()) Slog.d(TAG, "Stop programList updates");
+ mEventLogger.logRadioEvent("Stop programList updates");
synchronized (mLock) {
checkNotClosedLocked();
mProgramInfoCache = null;
@@ -291,7 +285,7 @@
@Override
public boolean isConfigFlagSet(int flag) {
- if (isDebugEnabled()) Slog.d(TAG, "Is ConfigFlagSet for " + ConfigFlag.toString(flag));
+ mEventLogger.logRadioEvent("Is ConfigFlagSet for %s", ConfigFlag.toString(flag));
synchronized (mLock) {
checkNotClosedLocked();
@@ -313,9 +307,7 @@
@Override
public void setConfigFlag(int flag, boolean value) throws RemoteException {
- if (isDebugEnabled()) {
- Slog.d(TAG, "Set ConfigFlag " + ConfigFlag.toString(flag) + " = " + value);
- }
+ mEventLogger.logRadioEvent("Set ConfigFlag %s = %b", ConfigFlag.toString(flag), value);
synchronized (mLock) {
checkNotClosedLocked();
int halResult = mHwSession.setConfigFlag(flag, value);
@@ -351,6 +343,10 @@
pw.printf("ProgramInfoCache: %s\n", mProgramInfoCache);
pw.printf("Config: %s\n", mDummyConfig);
}
+ pw.printf("Tuner session events:\n");
+ pw.increaseIndent();
+ mEventLogger.dump(pw);
+ pw.decreaseIndent();
pw.decreaseIndent();
}
}
diff --git a/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java b/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java
index f2b4d42..81b56a3 100644
--- a/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java
+++ b/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java
@@ -16,24 +16,73 @@
package com.android.server.companion.virtual;
+import android.annotation.NonNull;
import android.companion.virtual.IVirtualDevice;
+import java.util.Set;
+
/**
* Virtual device manager local service interface.
* Only for use within system server.
*/
public abstract class VirtualDeviceManagerInternal {
+ /** Interface to listen to the creation and destruction of virtual displays. */
+ public interface VirtualDisplayListener {
+ /** Notifies that a virtual display was created. */
+ void onVirtualDisplayCreated(int displayId);
+
+ /** Notifies that a virtual display was removed. */
+ void onVirtualDisplayRemoved(int displayId);
+ }
+
+
+ /** Interface to listen to the changes on the list of app UIDs running on any virtual device. */
+ public interface AppsOnVirtualDeviceListener {
+ /** Notifies that running apps on any virtual device has changed */
+ void onAppsOnAnyVirtualDeviceChanged(Set<Integer> allRunningUids);
+ }
+
+ /** Register a listener for the creation and destruction of virtual displays. */
+ public abstract void registerVirtualDisplayListener(
+ @NonNull VirtualDisplayListener listener);
+
+ /** Unregister a listener for the creation and destruction of virtual displays. */
+ public abstract void unregisterVirtualDisplayListener(
+ @NonNull VirtualDisplayListener listener);
+
+ /** Register a listener for changes of running app UIDs on any virtual device. */
+ public abstract void registerAppsOnVirtualDeviceListener(
+ @NonNull AppsOnVirtualDeviceListener listener);
+
+ /** Unregister a listener for changes of running app UIDs on any virtual device. */
+ public abstract void unregisterAppsOnVirtualDeviceListener(
+ @NonNull AppsOnVirtualDeviceListener listener);
+
+ /**
+ * Notifies that the set of apps running on virtual devices has changed.
+ * This method only notifies the listeners when the union of running UIDs on all virtual devices
+ * has changed.
+ */
+ public abstract void onAppsOnVirtualDeviceChanged();
+
/**
* Validate the virtual device.
*/
public abstract boolean isValidVirtualDevice(IVirtualDevice virtualDevice);
/**
- * Notify a virtual display is removed.
+ * Notifies that a virtual display is created.
+ *
+ * @param displayId The display id of the created virtual display.
+ */
+ public abstract void onVirtualDisplayCreated(int displayId);
+
+ /**
+ * Notifies that a virtual display is removed.
*
* @param virtualDevice The virtual device where the virtual display located.
- * @param displayId The display id of the removed virtual display.
+ * @param displayId The display id of the removed virtual display.
*/
public abstract void onVirtualDisplayRemoved(IVirtualDevice virtualDevice, int displayId);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 9691b20..98238cc 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -4040,6 +4040,7 @@
mConfig.proxyInfo = profile.proxy;
mConfig.requiresInternetValidation = profile.requiresInternetValidation;
mConfig.excludeLocalRoutes = profile.excludeLocalRoutes;
+ mConfig.allowBypass = profile.isBypassable;
switch (profile.type) {
case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index db646df..31562c73 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -148,6 +148,12 @@
// The currently accepted nominal ambient light level.
private float mAmbientLux;
+ // The last calculated ambient light level (long time window).
+ private float mSlowAmbientLux;
+
+ // The last calculated ambient light level (short time window).
+ private float mFastAmbientLux;
+
// The last ambient lux value prior to passing the darkening or brightening threshold.
private float mPreThresholdLux;
@@ -439,6 +445,14 @@
return mAmbientLux;
}
+ float getSlowAmbientLux() {
+ return mSlowAmbientLux;
+ }
+
+ float getFastAmbientLux() {
+ return mFastAmbientLux;
+ }
+
private boolean setDisplayPolicy(int policy) {
if (mDisplayPolicy == policy) {
return false;
@@ -811,20 +825,20 @@
// proposed ambient light value since the slow value might be sufficiently far enough away
// from the fast value to cause a recalculation while its actually just converging on
// the fast value still.
- float slowAmbientLux = calculateAmbientLux(time, mAmbientLightHorizonLong);
- float fastAmbientLux = calculateAmbientLux(time, mAmbientLightHorizonShort);
+ mSlowAmbientLux = calculateAmbientLux(time, mAmbientLightHorizonLong);
+ mFastAmbientLux = calculateAmbientLux(time, mAmbientLightHorizonShort);
- if ((slowAmbientLux >= mAmbientBrighteningThreshold
- && fastAmbientLux >= mAmbientBrighteningThreshold
+ if ((mSlowAmbientLux >= mAmbientBrighteningThreshold
+ && mFastAmbientLux >= mAmbientBrighteningThreshold
&& nextBrightenTransition <= time)
- || (slowAmbientLux <= mAmbientDarkeningThreshold
- && fastAmbientLux <= mAmbientDarkeningThreshold
+ || (mSlowAmbientLux <= mAmbientDarkeningThreshold
+ && mFastAmbientLux <= mAmbientDarkeningThreshold
&& nextDarkenTransition <= time)) {
mPreThresholdLux = mAmbientLux;
- setAmbientLux(fastAmbientLux);
+ setAmbientLux(mFastAmbientLux);
if (mLoggingEnabled) {
Slog.d(TAG, "updateAmbientLux: "
- + ((fastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": "
+ + ((mFastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": "
+ "mBrighteningLuxThreshold=" + mAmbientBrighteningThreshold + ", "
+ "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", "
+ "mAmbientLux=" + mAmbientLux);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 9c86076..2deb056 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1629,7 +1629,14 @@
mTempBrightnessEvent.reason.set(mBrightnessReason);
mTempBrightnessEvent.hbmMax = mHbmController.getCurrentBrightnessMax();
mTempBrightnessEvent.hbmMode = mHbmController.getHighBrightnessMode();
- mTempBrightnessEvent.flags |= (mIsRbcActive ? BrightnessEvent.FLAG_RBC : 0);
+ mTempBrightnessEvent.flags = (mTempBrightnessEvent.flags
+ | (mIsRbcActive ? BrightnessEvent.FLAG_RBC : 0)
+ | (mPowerRequest.lowPowerMode ? BrightnessEvent.FLAG_LOW_POWER_MODE : 0));
+ mTempBrightnessEvent.physicalDisplayId = mUniqueDisplayId;
+ mTempBrightnessEvent.rbcStrength = mCdsi != null
+ ? mCdsi.getReduceBrightColorsStrength() : -1;
+ mTempBrightnessEvent.powerFactor = mPowerRequest.screenLowPowerBrightnessFactor;
+
// Temporary is what we use during slider interactions. We avoid logging those so that
// we don't spam logcat when the slider is being used.
boolean tempToTempTransition =
@@ -1637,6 +1644,15 @@
&& mLastBrightnessEvent.reason.reason == BrightnessReason.REASON_TEMPORARY;
if ((!mTempBrightnessEvent.equalsMainData(mLastBrightnessEvent) && !tempToTempTransition)
|| brightnessAdjustmentFlags != 0) {
+ float lastBrightness = mLastBrightnessEvent.brightness;
+ mTempBrightnessEvent.initialBrightness = lastBrightness;
+ mTempBrightnessEvent.fastAmbientLux =
+ mAutomaticBrightnessController == null
+ ? -1f : mAutomaticBrightnessController.getFastAmbientLux();
+ mTempBrightnessEvent.slowAmbientLux =
+ mAutomaticBrightnessController == null
+ ? -1f : mAutomaticBrightnessController.getSlowAmbientLux();
+ mTempBrightnessEvent.automaticBrightnessEnabled = mPowerRequest.useAutoBrightness;
mLastBrightnessEvent.copyFrom(mTempBrightnessEvent);
BrightnessEvent newEvent = new BrightnessEvent(mTempBrightnessEvent);
@@ -1646,6 +1662,9 @@
newEvent.flags |= (userSetBrightnessChanged ? BrightnessEvent.FLAG_USER_SET : 0);
Slog.i(TAG, newEvent.toString(/* includeTime= */ false));
+ if (userSetBrightnessChanged) {
+ logManualBrightnessEvent(newEvent);
+ }
if (mBrightnessEventRingBuffer != null) {
mBrightnessEventRingBuffer.append(newEvent);
}
@@ -2736,27 +2755,63 @@
}
}
+ private void logManualBrightnessEvent(BrightnessEvent event) {
+ float appliedHbmMaxNits =
+ event.hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF
+ ? -1f : convertToNits(event.hbmMax);
+
+ // thermalCapNits set to -1 if not currently capping max brightness
+ float appliedThermalCapNits =
+ event.thermalMax == PowerManager.BRIGHTNESS_MAX
+ ? -1f : convertToNits(event.thermalMax);
+
+ int appliedRbcStrength = event.isRbcEnabled() ? event.rbcStrength : -1;
+
+ float appliedPowerFactor = event.isLowPowerModeSet() ? event.powerFactor : -1f;
+
+ FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED,
+ convertToNits(event.initialBrightness),
+ convertToNits(event.brightness),
+ event.slowAmbientLux,
+ event.physicalDisplayId,
+ event.isShortTermModelActive(),
+ appliedPowerFactor,
+ appliedRbcStrength,
+ appliedHbmMaxNits,
+ appliedThermalCapNits,
+ event.automaticBrightnessEnabled,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL);
+ }
+
class BrightnessEvent {
static final int FLAG_RBC = 0x1;
static final int FLAG_INVALID_LUX = 0x2;
static final int FLAG_DOZE_SCALE = 0x4;
static final int FLAG_USER_SET = 0x8;
- static final int FLAG_IDLE_CURVE = 0x16;
+ static final int FLAG_IDLE_CURVE = 0x10;
+ static final int FLAG_LOW_POWER_MODE = 0x20;
public final BrightnessReason reason = new BrightnessReason();
public int displayId;
+ public String physicalDisplayId;
public float lux;
+ public float fastAmbientLux;
+ public float slowAmbientLux;
public float preThresholdLux;
public long time;
public float brightness;
+ public float initialBrightness;
public float recommendedBrightness;
public float preThresholdBrightness;
public float hbmMax;
+ public int rbcStrength;
public float thermalMax;
+ public float powerFactor;
public int hbmMode;
public int flags;
public int adjustmentFlags;
+ public boolean automaticBrightnessEnabled;
BrightnessEvent(BrightnessEvent that) {
copyFrom(that);
@@ -2769,71 +2824,115 @@
void copyFrom(BrightnessEvent that) {
displayId = that.displayId;
+ physicalDisplayId = that.physicalDisplayId;
time = that.time;
lux = that.lux;
+ fastAmbientLux = that.fastAmbientLux;
+ slowAmbientLux = that.slowAmbientLux;
preThresholdLux = that.preThresholdLux;
brightness = that.brightness;
+ initialBrightness = that.initialBrightness;
recommendedBrightness = that.recommendedBrightness;
preThresholdBrightness = that.preThresholdBrightness;
hbmMax = that.hbmMax;
+ rbcStrength = that.rbcStrength;
thermalMax = that.thermalMax;
+ powerFactor = that.powerFactor;
flags = that.flags;
hbmMode = that.hbmMode;
reason.set(that.reason);
adjustmentFlags = that.adjustmentFlags;
+ automaticBrightnessEnabled = that.automaticBrightnessEnabled;
}
void reset() {
time = SystemClock.uptimeMillis();
+ physicalDisplayId = "";
brightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+ initialBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
recommendedBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
- lux = 0;
- preThresholdLux = 0;
+ lux = 0f;
+ fastAmbientLux = 0f;
+ slowAmbientLux = 0f;
+ preThresholdLux = 0f;
preThresholdBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
hbmMax = PowerManager.BRIGHTNESS_MAX;
+ rbcStrength = 0;
+ powerFactor = 1f;
thermalMax = PowerManager.BRIGHTNESS_MAX;
flags = 0;
hbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
reason.set(null);
adjustmentFlags = 0;
+ automaticBrightnessEnabled = true;
+ }
+
+ boolean isRbcEnabled() {
+ return (flags & FLAG_RBC) != 0;
+ }
+
+ public boolean isShortTermModelActive() {
+ return (flags & FLAG_USER_SET) != 0;
+ }
+
+ public boolean isLowPowerModeSet() {
+ return (flags & FLAG_LOW_POWER_MODE) != 0;
}
boolean equalsMainData(BrightnessEvent that) {
// This equals comparison purposefully ignores time since it is regularly changing and
// we don't want to log a brightness event just because the time changed.
return displayId == that.displayId
+ && physicalDisplayId.equals(that.physicalDisplayId)
&& Float.floatToRawIntBits(brightness)
== Float.floatToRawIntBits(that.brightness)
+ && Float.floatToRawIntBits(initialBrightness)
+ == Float.floatToRawIntBits(that.initialBrightness)
&& Float.floatToRawIntBits(recommendedBrightness)
== Float.floatToRawIntBits(that.recommendedBrightness)
&& Float.floatToRawIntBits(preThresholdBrightness)
== Float.floatToRawIntBits(that.preThresholdBrightness)
&& Float.floatToRawIntBits(lux) == Float.floatToRawIntBits(that.lux)
+ && Float.floatToRawIntBits(fastAmbientLux)
+ == Float.floatToRawIntBits(that.fastAmbientLux)
+ && Float.floatToRawIntBits(slowAmbientLux)
+ == Float.floatToRawIntBits(that.slowAmbientLux)
&& Float.floatToRawIntBits(preThresholdLux)
== Float.floatToRawIntBits(that.preThresholdLux)
+ && rbcStrength == that.rbcStrength
&& Float.floatToRawIntBits(hbmMax) == Float.floatToRawIntBits(that.hbmMax)
&& hbmMode == that.hbmMode
&& Float.floatToRawIntBits(thermalMax)
== Float.floatToRawIntBits(that.thermalMax)
+ && Float.floatToRawIntBits(powerFactor)
+ == Float.floatToRawIntBits(that.powerFactor)
&& flags == that.flags
&& adjustmentFlags == that.adjustmentFlags
- && reason.equals(that.reason);
+ && reason.equals(that.reason)
+ && automaticBrightnessEnabled == that.automaticBrightnessEnabled;
}
public String toString(boolean includeTime) {
return (includeTime ? TimeUtils.formatForLogging(time) + " - " : "")
+ "BrightnessEvent: "
+ "disp=" + displayId
+ + ", physDisp=" + physicalDisplayId
+ ", brt=" + brightness + ((flags & FLAG_USER_SET) != 0 ? "(user_set)" : "")
+ + ", initBrt=" + initialBrightness
+ ", rcmdBrt=" + recommendedBrightness
+ ", preBrt=" + preThresholdBrightness
+ ", lux=" + lux
+ + ", fastAmbientLux=" + fastAmbientLux
+ + ", slowAmbientLux=" + slowAmbientLux
+ ", preLux=" + preThresholdLux
+ ", hbmMax=" + hbmMax
+ ", hbmMode=" + BrightnessInfo.hbmToString(hbmMode)
+ + ", rbcStrength=" + rbcStrength
+ + ", powerFactor=" + powerFactor
+ ", thrmMax=" + thermalMax
+ ", flags=" + flagsToString()
- + ", reason=" + reason.toString(adjustmentFlags);
+ + ", reason=" + reason.toString(adjustmentFlags)
+ + ", autoBrightness=" + automaticBrightnessEnabled;
}
@Override
@@ -2846,7 +2945,8 @@
+ ((flags & FLAG_RBC) != 0 ? "rbc " : "")
+ ((flags & FLAG_INVALID_LUX) != 0 ? "invalid_lux " : "")
+ ((flags & FLAG_DOZE_SCALE) != 0 ? "doze_scale " : "")
- + ((flags & FLAG_DOZE_SCALE) != 0 ? "idle_curve " : "");
+ + ((flags & FLAG_IDLE_CURVE) != 0 ? "idle_curve " : "")
+ + ((flags & FLAG_LOW_POWER_MODE) != 0 ? "low_power_mode " : "");
}
}
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 223b8c1..017b96c 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -740,7 +740,8 @@
mDisplayWhiteBalanceTintController.setActivated(isDisplayWhiteBalanceSettingEnabled()
&& !mNightDisplayTintController.isActivated()
&& !isAccessibilityEnabled()
- && dtm.needsLinearColorMatrix());
+ && dtm.needsLinearColorMatrix()
+ && mDisplayWhiteBalanceTintController.isAllowed());
boolean activated = mDisplayWhiteBalanceTintController.isActivated();
if (mDisplayWhiteBalanceListener != null && oldActivated != activated) {
@@ -1453,6 +1454,12 @@
*/
public class ColorDisplayServiceInternal {
+ /** Sets whether DWB should be allowed in the current state. */
+ public void setDisplayWhiteBalanceAllowed(boolean allowed) {
+ mDisplayWhiteBalanceTintController.setAllowed(allowed);
+ updateDisplayWhiteBalanceStatus();
+ }
+
/**
* Set the current CCT value for the display white balance transform, and if the transform
* is enabled, apply it.
@@ -1515,6 +1522,10 @@
return mReduceBrightColorsTintController.isActivated();
}
+ public int getReduceBrightColorsStrength() {
+ return mReduceBrightColorsTintController.getStrength();
+ }
+
/**
* Gets the computed brightness, in nits, when the reduce bright colors feature is applied
* at the current strength.
diff --git a/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java b/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java
index 936149c..93a78c1 100644
--- a/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java
+++ b/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java
@@ -61,12 +61,17 @@
boolean mSetUp = false;
private float[] mMatrixDisplayWhiteBalance = new float[16];
private Boolean mIsAvailable;
+ // This feature becomes disallowed if the device is in an unsupported strong/light state.
+ private boolean mIsAllowed = true;
@Override
public void setUp(Context context, boolean needsLinear) {
mSetUp = false;
final Resources res = context.getResources();
+ // Initialize with the config value for light mode, so it starts in the right state.
+ setAllowed(res.getBoolean(R.bool.config_displayWhiteBalanceLightModeAllowed));
+
ColorSpace.Rgb displayColorSpaceRGB = getDisplayColorSpaceFromSurfaceControl();
if (displayColorSpaceRGB == null) {
Slog.w(ColorDisplayService.TAG,
@@ -248,6 +253,7 @@
+ matrixToString(mDisplayColorSpaceRGB.getInverseTransform(), 3));
pw.println(" mMatrixDisplayWhiteBalance = "
+ matrixToString(mMatrixDisplayWhiteBalance, 4));
+ pw.println(" mIsAllowed = " + mIsAllowed);
}
}
@@ -263,6 +269,14 @@
}
}
+ public void setAllowed(boolean allowed) {
+ mIsAllowed = allowed;
+ }
+
+ public boolean isAllowed() {
+ return mIsAllowed;
+ }
+
private ColorSpace.Rgb makeRgbColorSpaceFromXYZ(float[] redGreenBlueXYZ, float[] whiteXYZ) {
return new ColorSpace.Rgb(
"Display Color Space",
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index d04b5a2..85d5b4f 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -65,6 +65,8 @@
// this effect.
private final float mHighLightAmbientColorTemperature;
+ private final boolean mLightModeAllowed;
+
private float mAmbientColorTemperature;
@VisibleForTesting
float mPendingAmbientColorTemperature;
@@ -148,6 +150,8 @@
* @param displayColorTemperatures
* The display color temperatures used to map the ambient color temperature to the display
* color temperature (or null if no mapping is necessary).
+ * @param lightModeAllowed
+ * Whether a lighter version should be applied when Strong Mode is not enabled.
*
* @throws NullPointerException
* - brightnessSensor is null;
@@ -171,7 +175,8 @@
float[] ambientColorTemperatures,
float[] displayColorTemperatures,
float[] strongAmbientColorTemperatures,
- float[] strongDisplayColorTemperatures) {
+ float[] strongDisplayColorTemperatures,
+ boolean lightModeAllowed) {
validateArguments(brightnessSensor, brightnessFilter, colorTemperatureSensor,
colorTemperatureFilter, throttler);
mBrightnessSensor = brightnessSensor;
@@ -186,6 +191,7 @@
mLastAmbientColorTemperature = -1.0f;
mAmbientColorTemperatureHistory = new History(/* size= */ 50);
mAmbientColorTemperatureOverride = -1.0f;
+ mLightModeAllowed = lightModeAllowed;
try {
mLowLightAmbientBrightnessToBiasSpline = new Spline.LinearSpline(
@@ -273,6 +279,8 @@
*/
public void setStrongModeEnabled(boolean enabled) {
mStrongModeEnabled = enabled;
+ mColorDisplayServiceInternal.setDisplayWhiteBalanceAllowed(mLightModeAllowed
+ || mStrongModeEnabled);
if (mEnabled) {
updateAmbientColorTemperature();
updateDisplayColorTemperature();
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
index 07821b0..62f813f 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
@@ -95,6 +95,8 @@
final float[] strongDisplayColorTemperatures = getFloatArray(resources,
com.android.internal.R.array
.config_displayWhiteBalanceStrongDisplayColorTemperatures);
+ final boolean lightModeAllowed = resources.getBoolean(
+ com.android.internal.R.bool.config_displayWhiteBalanceLightModeAllowed);
final DisplayWhiteBalanceController controller = new DisplayWhiteBalanceController(
brightnessSensor, brightnessFilter, colorTemperatureSensor, colorTemperatureFilter,
throttler, displayWhiteBalanceLowLightAmbientBrightnesses,
@@ -102,7 +104,7 @@
displayWhiteBalanceHighLightAmbientBrightnesses,
displayWhiteBalanceHighLightAmbientBiases, highLightAmbientColorTemperature,
ambientColorTemperatures, displayColorTemperatures, strongAmbientColorTemperatures,
- strongDisplayColorTemperatures);
+ strongDisplayColorTemperatures, lightModeAllowed);
brightnessSensor.setCallbacks(controller);
colorTemperatureSensor.setCallbacks(controller);
return controller;
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 4e0489a..fee1f5c 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -110,6 +110,10 @@
private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+ // A temporary dream component that, when present, takes precedence over user configured dream
+ // component.
+ private ComponentName mSystemDreamComponent;
+
private ComponentName mDreamOverlayServiceName;
private AmbientDisplayConfiguration mDozeConfig;
@@ -352,11 +356,21 @@
return chooseDreamForUser(doze, ActivityManager.getCurrentUser());
}
+ /**
+ * If doze is true, returns the doze component for the user.
+ * Otherwise, returns the system dream component, if present.
+ * Otherwise, returns the first valid user configured dream component.
+ */
private ComponentName chooseDreamForUser(boolean doze, int userId) {
if (doze) {
ComponentName dozeComponent = getDozeComponent(userId);
return validateDream(dozeComponent) ? dozeComponent : null;
}
+
+ if (mSystemDreamComponent != null) {
+ return mSystemDreamComponent;
+ }
+
ComponentName[] dreams = getDreamComponentsForUser(userId);
return dreams != null && dreams.length != 0 ? dreams[0] : null;
}
@@ -416,6 +430,21 @@
userId);
}
+ private void setSystemDreamComponentInternal(ComponentName componentName) {
+ synchronized (mLock) {
+ if (Objects.equals(mSystemDreamComponent, componentName)) {
+ return;
+ }
+
+ mSystemDreamComponent = componentName;
+
+ // Switch dream if currently dreaming and not dozing.
+ if (isDreamingInternal() && !mCurrentDreamIsDozing) {
+ startDreamInternal(false);
+ }
+ }
+ }
+
private ComponentName getDefaultDreamComponentForUser(int userId) {
String name = Settings.Secure.getStringForUser(mContext.getContentResolver(),
Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
@@ -668,6 +697,18 @@
}
@Override // Binder call
+ public void setSystemDreamComponent(ComponentName componentName) {
+ checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ DreamManagerService.this.setSystemDreamComponentInternal(componentName);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
public void registerDreamOverlayService(ComponentName overlayComponent) {
checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
@@ -842,6 +883,11 @@
public ComponentName getActiveDreamComponent(boolean doze) {
return getActiveDreamComponentInternal(doze);
}
+
+ @Override
+ public void requestDream() {
+ requestDreamInternal();
+ }
}
private final Runnable mSystemPropertiesChanged = new Runnable() {
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 5a40b30..0fac808 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -1786,8 +1786,8 @@
* from receiving events from the profile.
*/
public boolean isPermittedForProfile(int userId) {
- if (!mUserProfiles.isManagedProfile(userId)) {
- return true;
+ if (!mUserProfiles.canProfileUseBoundServices(userId)) {
+ return false;
}
DevicePolicyManager dpm =
(DevicePolicyManager) mContext.getSystemService(DEVICE_POLICY_SERVICE);
@@ -1862,10 +1862,16 @@
}
}
- public boolean isManagedProfile(int userId) {
+ public boolean canProfileUseBoundServices(int userId) {
synchronized (mCurrentProfiles) {
UserInfo user = mCurrentProfiles.get(userId);
- return user != null && user.isManagedProfile();
+ if (user == null) {
+ return false;
+ }
+ if (user.isManagedProfile() || user.isCloneProfile()) {
+ return false;
+ }
+ return true;
}
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 2f34ccd..d44a3b7 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -303,6 +303,7 @@
import com.android.server.notification.toast.TextToastRecord;
import com.android.server.notification.toast.ToastRecord;
import com.android.server.pm.PackageManagerService;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.statusbar.StatusBarManagerInternal;
@@ -532,6 +533,7 @@
private UriGrantsManagerInternal mUgmInternal;
private volatile RoleObserver mRoleObserver;
private UserManager mUm;
+ private UserManagerInternal mUmInternal;
private IPlatformCompat mPlatformCompat;
private ShortcutHelper mShortcutHelper;
private PermissionHelper mPermissionHelper;
@@ -818,7 +820,8 @@
final List<UserInfo> activeUsers = mUm.getUsers();
for (UserInfo userInfo : activeUsers) {
int userId = userInfo.getUserHandle().getIdentifier();
- if (isNASMigrationDone(userId) || mUm.isManagedProfile(userId)) {
+ if (isNASMigrationDone(userId)
+ || userInfo.isManagedProfile() || userInfo.isCloneProfile()) {
continue;
}
List<ComponentName> allowedComponents = mAssistants.getAllowedComponents(userId);
@@ -949,7 +952,9 @@
}
XmlUtils.beginDocument(parser, TAG_NOTIFICATION_POLICY);
boolean migratedManagedServices = false;
- boolean ineligibleForManagedServices = forRestore && mUm.isManagedProfile(userId);
+ UserInfo userInfo = mUmInternal.getUserInfo(userId);
+ boolean ineligibleForManagedServices = forRestore &&
+ (userInfo.isManagedProfile() || userInfo.isCloneProfile());
int outerDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
if (ZenModeConfig.ZEN_TAG.equals(parser.getName())) {
@@ -1823,7 +1828,7 @@
} else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
mUserProfiles.updateCache(context);
- if (!mUserProfiles.isManagedProfile(userId)) {
+ if (mUserProfiles.canProfileUseBoundServices(userId)) {
// reload per-user settings
mSettingsObserver.update(null);
// Refresh managed services
@@ -1837,7 +1842,7 @@
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
if (userId != USER_NULL) {
mUserProfiles.updateCache(context);
- if (!mUserProfiles.isManagedProfile(userId)) {
+ if (mUserProfiles.canProfileUseBoundServices(userId)) {
allowDefaultApprovedServices(userId);
}
}
@@ -1855,7 +1860,7 @@
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
mUserProfiles.updateCache(context);
mAssistants.onUserUnlocked(userId);
- if (!mUserProfiles.isManagedProfile(userId)) {
+ if (mUserProfiles.canProfileUseBoundServices(userId)) {
mConditionProviders.onUserUnlocked(userId);
mListeners.onUserUnlocked(userId);
mZenModeHelper.onUserUnlocked(userId);
@@ -2217,6 +2222,7 @@
mPackageManagerClient = packageManagerClient;
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);
+ mUmInternal = LocalServices.getService(UserManagerInternal.class);
mUsageStatsManagerInternal = usageStatsManagerInternal;
mAppOps = appOps;
mAppOpsService = iAppOps;
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 729c521..477b8da 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -86,7 +86,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -1328,17 +1327,16 @@
return null;
}
NotificationChannelGroup group = r.groups.get(groupId).clone();
- ArrayList channels = new ArrayList();
+ group.setChannels(new ArrayList<>());
int N = r.channels.size();
for (int i = 0; i < N; i++) {
final NotificationChannel nc = r.channels.valueAt(i);
if (includeDeleted || !nc.isDeleted()) {
if (groupId.equals(nc.getGroup())) {
- channels.add(nc);
+ group.addChannel(nc);
}
}
}
- group.setChannels(channels);
return group;
}
}
@@ -1351,10 +1349,7 @@
if (r == null) {
return null;
}
- if (r.groups.get(groupId) != null) {
- return r.groups.get(groupId).clone();
- }
- return null;
+ return r.groups.get(groupId);
}
}
@@ -1362,48 +1357,44 @@
public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty) {
Objects.requireNonNull(pkg);
- List<NotificationChannelGroup> groups = new ArrayList<>();
+ Map<String, NotificationChannelGroup> groups = new ArrayMap<>();
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
return ParceledListSlice.emptyList();
}
- Map<String, ArrayList<NotificationChannel>> groupedChannels = new HashMap();
+ NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null);
int N = r.channels.size();
for (int i = 0; i < N; i++) {
final NotificationChannel nc = r.channels.valueAt(i);
if (includeDeleted || !nc.isDeleted()) {
if (nc.getGroup() != null) {
if (r.groups.get(nc.getGroup()) != null) {
- ArrayList<NotificationChannel> channels = groupedChannels.getOrDefault(
- nc.getGroup(), new ArrayList<>());
- channels.add(nc);
- groupedChannels.put(nc.getGroup(), channels);
+ NotificationChannelGroup ncg = groups.get(nc.getGroup());
+ if (ncg == null) {
+ ncg = r.groups.get(nc.getGroup()).clone();
+ ncg.setChannels(new ArrayList<>());
+ groups.put(nc.getGroup(), ncg);
+
+ }
+ ncg.addChannel(nc);
}
} else {
- ArrayList<NotificationChannel> channels = groupedChannels.getOrDefault(
- null, new ArrayList<>());
- channels.add(nc);
- groupedChannels.put(null, channels);
+ nonGrouped.addChannel(nc);
}
}
}
- for (NotificationChannelGroup group : r.groups.values()) {
- ArrayList<NotificationChannel> channels =
- groupedChannels.getOrDefault(group.getId(), new ArrayList<>());
- if (includeEmpty || !channels.isEmpty()) {
- NotificationChannelGroup clone = group.clone();
- clone.setChannels(channels);
- groups.add(clone);
+ if (includeNonGrouped && nonGrouped.getChannels().size() > 0) {
+ groups.put(null, nonGrouped);
+ }
+ if (includeEmpty) {
+ for (NotificationChannelGroup group : r.groups.values()) {
+ if (!groups.containsKey(group.getId())) {
+ groups.put(group.getId(), group);
+ }
}
}
-
- if (includeNonGrouped && groupedChannels.containsKey(null)) {
- NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null);
- nonGrouped.setChannels(groupedChannels.get(null));
- groups.add(nonGrouped);
- }
- return new ParceledListSlice<>(groups);
+ return new ParceledListSlice<>(new ArrayList<>(groups.values()));
}
}
diff --git a/services/core/java/com/android/server/notification/ZenModeFiltering.java b/services/core/java/com/android/server/notification/ZenModeFiltering.java
index 7e36aed..db0ce2e 100644
--- a/services/core/java/com/android/server/notification/ZenModeFiltering.java
+++ b/services/core/java/com/android/server/notification/ZenModeFiltering.java
@@ -149,8 +149,13 @@
*/
public boolean shouldIntercept(int zen, NotificationManager.Policy policy,
NotificationRecord record) {
- // Zen mode is ignored for critical notifications.
- if (zen == ZEN_MODE_OFF || isCritical(record)) {
+ if (zen == ZEN_MODE_OFF) {
+ return false;
+ }
+
+ if (isCritical(record)) {
+ // Zen mode is ignored for critical notifications.
+ ZenLog.traceNotIntercepted(record, "criticalNotification");
return false;
}
// Make an exception to policy for the notification saying that policy has changed
@@ -168,6 +173,7 @@
case Global.ZEN_MODE_ALARMS:
if (isAlarm(record)) {
// Alarms only
+ ZenLog.traceNotIntercepted(record, "alarm");
return false;
}
ZenLog.traceIntercepted(record, "alarmsOnly");
@@ -184,6 +190,7 @@
ZenLog.traceIntercepted(record, "!allowAlarms");
return true;
}
+ ZenLog.traceNotIntercepted(record, "allowedAlarm");
return false;
}
if (isEvent(record)) {
@@ -191,6 +198,7 @@
ZenLog.traceIntercepted(record, "!allowEvents");
return true;
}
+ ZenLog.traceNotIntercepted(record, "allowedEvent");
return false;
}
if (isReminder(record)) {
@@ -198,6 +206,7 @@
ZenLog.traceIntercepted(record, "!allowReminders");
return true;
}
+ ZenLog.traceNotIntercepted(record, "allowedReminder");
return false;
}
if (isMedia(record)) {
@@ -205,6 +214,7 @@
ZenLog.traceIntercepted(record, "!allowMedia");
return true;
}
+ ZenLog.traceNotIntercepted(record, "allowedMedia");
return false;
}
if (isSystem(record)) {
@@ -212,6 +222,7 @@
ZenLog.traceIntercepted(record, "!allowSystem");
return true;
}
+ ZenLog.traceNotIntercepted(record, "allowedSystem");
return false;
}
if (isConversation(record)) {
@@ -253,6 +264,7 @@
ZenLog.traceIntercepted(record, "!priority");
return true;
default:
+ ZenLog.traceNotIntercepted(record, "unknownZenMode");
return false;
}
}
@@ -271,10 +283,12 @@
}
private static boolean shouldInterceptAudience(int source, NotificationRecord record) {
- if (!audienceMatches(source, record.getContactAffinity())) {
- ZenLog.traceIntercepted(record, "!audienceMatches");
+ float affinity = record.getContactAffinity();
+ if (!audienceMatches(source, affinity)) {
+ ZenLog.traceIntercepted(record, "!audienceMatches,affinity=" + affinity);
return true;
}
+ ZenLog.traceNotIntercepted(record, "affinity=" + affinity);
return false;
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index d426679..4c23ab8 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -326,7 +326,7 @@
public String addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule,
String reason) {
- if (!isSystemRule(automaticZenRule)) {
+ if (!ZenModeConfig.SYSTEM_AUTHORITY.equals(pkg)) {
PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
if (component == null) {
component = getActivityInfo(automaticZenRule.getConfigurationActivity());
@@ -582,11 +582,6 @@
}
}
- private boolean isSystemRule(AutomaticZenRule rule) {
- return rule.getOwner() != null
- && ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
- }
-
private ServiceInfo getServiceInfo(ComponentName owner) {
Intent queryIntent = new Intent();
queryIntent.setComponent(owner);
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 339d5d4fe..c3b4792 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -43,6 +43,7 @@
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.SharedLibraryInfo;
+import android.content.pm.UserInfo;
import android.content.pm.VersionedPackage;
import android.net.Uri;
import android.os.Binder;
@@ -163,6 +164,18 @@
return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}
+ if (PackageManagerServiceUtils.isSystemApp(uninstalledPs)
+ && ((deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0)) {
+ UserInfo userInfo = mUserManagerInternal.getUserInfo(userId);
+ if (userInfo == null || (!userInfo.isAdmin() && !mUserManagerInternal.getUserInfo(
+ mUserManagerInternal.getProfileParentId(userId)).isAdmin())) {
+ Slog.w(TAG, "Not removing package " + packageName
+ + " as only admin user (or their profile) may downgrade system apps");
+ EventLog.writeEvent(0x534e4554, "170646036", -1, packageName);
+ return PackageManager.DELETE_FAILED_USER_RESTRICTED;
+ }
+ }
+
disabledSystemPs = mPm.mSettings.getDisabledSystemPkgLPr(packageName);
// Static shared libs can be declared by any package, so let us not
// allow removing a package if it provides a lib others depend on.
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 701ac73c..00fb065 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -18,6 +18,7 @@
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.os.UserManager.DISALLOW_USER_SWITCH;
import android.Manifest;
import android.accounts.Account;
@@ -1760,6 +1761,19 @@
}
@Override
+ public boolean isUserSwitcherEnabled(@UserIdInt int mUserId) {
+ boolean multiUserSettingOn = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.USER_SWITCHER_ENABLED,
+ Resources.getSystem().getBoolean(com.android.internal
+ .R.bool.config_showUserSwitcherByDefault) ? 1 : 0) != 0;
+
+ return UserManager.supportsMultipleUsers()
+ && !hasUserRestriction(DISALLOW_USER_SWITCH, mUserId)
+ && !UserManager.isDeviceInDemoMode(mContext)
+ && multiUserSettingOn;
+ }
+
+ @Override
public boolean isRestricted(@UserIdInt int userId) {
if (userId != UserHandle.getCallingUserId()) {
checkCreateUsersPermission("query isRestricted for user " + userId);
@@ -2049,7 +2063,6 @@
originatingUserId, local);
localChanged = updateLocalRestrictionsForTargetUsersLR(originatingUserId, local,
updatedLocalTargetUserIds);
-
if (isDeviceOwner) {
// Remember the global restriction owner userId to be able to make a distinction
// in getUserRestrictionSource on who set local policies.
@@ -4432,45 +4445,60 @@
null, // use default PullAtomMetadata values
BackgroundThread.getExecutor(),
this::onPullAtom);
+ statsManager.setPullAtomCallback(
+ FrameworkStatsLog.MULTI_USER_INFO,
+ null, // use default PullAtomMetadata values
+ BackgroundThread.getExecutor(),
+ this::onPullAtom);
}
/** Writes a UserInfo pulled atom for each user on the device. */
private int onPullAtom(int atomTag, List<StatsEvent> data) {
- if (atomTag != FrameworkStatsLog.USER_INFO) {
+ if (atomTag == FrameworkStatsLog.USER_INFO) {
+ final List<UserInfo> users = getUsersInternal(true, true, true);
+ final int size = users.size();
+ if (size > 1) {
+ for (int idx = 0; idx < size; idx++) {
+ final UserInfo user = users.get(idx);
+ final int userTypeStandard = UserManager.getUserTypeForStatsd(user.userType);
+ final String userTypeCustom = (userTypeStandard == FrameworkStatsLog
+ .USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__TYPE_UNKNOWN)
+ ?
+ user.userType : null;
+
+ boolean isUserRunningUnlocked;
+ synchronized (mUserStates) {
+ isUserRunningUnlocked =
+ mUserStates.get(user.id, -1) == UserState.STATE_RUNNING_UNLOCKED;
+ }
+
+ data.add(FrameworkStatsLog.buildStatsEvent(FrameworkStatsLog.USER_INFO,
+ user.id,
+ userTypeStandard,
+ userTypeCustom,
+ user.flags,
+ user.creationTime,
+ user.lastLoggedInTime,
+ isUserRunningUnlocked
+ ));
+ }
+ }
+ } else if (atomTag == FrameworkStatsLog.MULTI_USER_INFO) {
+ if (UserManager.getMaxSupportedUsers() > 1) {
+ int deviceOwnerUserId = UserHandle.USER_NULL;
+
+ synchronized (mRestrictionsLock) {
+ deviceOwnerUserId = mDeviceOwnerUserId;
+ }
+
+ data.add(FrameworkStatsLog.buildStatsEvent(FrameworkStatsLog.MULTI_USER_INFO,
+ UserManager.getMaxSupportedUsers(),
+ isUserSwitcherEnabled(deviceOwnerUserId)));
+ }
+ } else {
Slogf.e(LOG_TAG, "Unexpected atom tag: %d", atomTag);
return android.app.StatsManager.PULL_SKIP;
}
- final List<UserInfo> users = getUsersInternal(true, true, true);
- final int size = users.size();
- for (int idx = 0; idx < size; idx++) {
- final UserInfo user = users.get(idx);
- if (user.id == UserHandle.USER_SYSTEM) {
- // Skip user 0. It's not interesting. We already know it exists, is running, and (if
- // we know the device configuration) its userType.
- continue;
- }
-
- final int userTypeStandard = UserManager.getUserTypeForStatsd(user.userType);
- final String userTypeCustom = (userTypeStandard ==
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__TYPE_UNKNOWN) ?
- user.userType : null;
-
- boolean isUserRunningUnlocked;
- synchronized (mUserStates) {
- isUserRunningUnlocked =
- mUserStates.get(user.id, -1) == UserState.STATE_RUNNING_UNLOCKED;
- }
-
- data.add(FrameworkStatsLog.buildStatsEvent(FrameworkStatsLog.USER_INFO,
- user.id,
- userTypeStandard,
- userTypeCustom,
- user.flags,
- user.creationTime,
- user.lastLoggedInTime,
- isUserRunningUnlocked
- ));
- }
return android.app.StatsManager.PULL_SUCCESS;
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 1381614..014d580 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -2665,7 +2665,6 @@
final Permission bp = mRegistry.getPermission(permName);
final boolean appSupportsRuntimePermissions =
pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M;
- String legacyActivityRecognitionPermission = null;
if (DEBUG_INSTALL && bp != null) {
Log.i(TAG, "Package " + friendlyName
@@ -2689,47 +2688,12 @@
// Cache newImplicitPermissions before modifing permissionsState as for the
// shared uids the original and new state are the same object
if (!origState.hasPermissionState(permName)
- && (pkg.getImplicitPermissions().contains(permName)
- || (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) {
- if (pkg.getImplicitPermissions().contains(permName)) {
+ && (pkg.getImplicitPermissions().contains(permName))) {
// If permName is an implicit permission, try to auto-grant
newImplicitPermissions.add(permName);
-
if (DEBUG_PERMISSIONS) {
Slog.i(TAG, permName + " is newly added for " + friendlyName);
}
- } else {
- // Special case for Activity Recognition permission. Even if AR
- // permission is not an implicit permission we want to add it to the
- // list (try to auto-grant it) if the app was installed on a device
- // before AR permission was split, regardless of if the app now requests
- // the new AR permission or has updated its target SDK and AR is no
- // longer implicit to it. This is a compatibility workaround for apps
- // when AR permission was split in Q.
- // TODO(zhanghai): This calls into SystemConfig, which generally
- // shouldn't cause deadlock, but maybe we should keep a cache of the
- // split permission list and just eliminate the possibility.
- final List<PermissionManager.SplitPermissionInfo> permissionList =
- getSplitPermissionInfos();
- int numSplitPerms = permissionList.size();
- for (int splitPermNum = 0; splitPermNum < numSplitPerms;
- splitPermNum++) {
- PermissionManager.SplitPermissionInfo sp = permissionList.get(
- splitPermNum);
- String splitPermName = sp.getSplitPermission();
- if (sp.getNewPermissions().contains(permName)
- && origState.isPermissionGranted(splitPermName)) {
- legacyActivityRecognitionPermission = splitPermName;
- newImplicitPermissions.add(permName);
-
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, permName + " is newly added for "
- + friendlyName);
- }
- break;
- }
- }
- }
}
// TODO(b/140256621): The package instant app method has been removed
@@ -2863,8 +2827,7 @@
// Hard restricted permissions cannot be held.
} else if (!permissionPolicyInitialized
|| (!hardRestricted || restrictionExempt)) {
- if ((origPermState != null && origPermState.isGranted())
- || legacyActivityRecognitionPermission != null) {
+ if ((origPermState != null && origPermState.isGranted())) {
if (!uidState.grantPermission(bp)) {
wasChanged = true;
}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index dad9584..5a2fb18 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -571,8 +571,7 @@
/**
* Called when there has been user activity.
*/
- public void onUserActivity(int displayGroupId, @PowerManager.UserActivityEvent int event,
- int uid) {
+ public void onUserActivity(int displayGroupId, int event, int uid) {
if (DEBUG) {
Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
}
diff --git a/services/core/java/com/android/server/power/PowerGroup.java b/services/core/java/com/android/server/power/PowerGroup.java
index 9fe53fb..fec61ac 100644
--- a/services/core/java/com/android/server/power/PowerGroup.java
+++ b/services/core/java/com/android/server/power/PowerGroup.java
@@ -74,8 +74,6 @@
private long mLastPowerOnTime;
private long mLastUserActivityTime;
private long mLastUserActivityTimeNoChangeLights;
- @PowerManager.UserActivityEvent
- private int mLastUserActivityEvent;
/** Timestamp (milliseconds since boot) of the last time the power group was awoken.*/
private long mLastWakeTime;
/** Timestamp (milliseconds since boot) of the last time the power group was put to sleep. */
@@ -246,7 +244,7 @@
return true;
}
- boolean dozeLocked(long eventTime, int uid, @PowerManager.GoToSleepReason int reason) {
+ boolean dozeLocked(long eventTime, int uid, int reason) {
if (eventTime < getLastWakeTimeLocked() || !isInteractive(mWakefulness)) {
return false;
}
@@ -255,14 +253,9 @@
try {
reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX,
Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN));
- long millisSinceLastUserActivity = eventTime - Math.max(
- mLastUserActivityTimeNoChangeLights, mLastUserActivityTime);
Slog.i(TAG, "Powering off display group due to "
- + PowerManager.sleepReasonToString(reason)
- + " (groupId= " + getGroupId() + ", uid= " + uid
- + ", millisSinceLastUserActivity=" + millisSinceLastUserActivity
- + ", lastUserActivityEvent=" + PowerManager.userActivityEventToString(
- mLastUserActivityEvent) + ")...");
+ + PowerManager.sleepReasonToString(reason) + " (groupId= " + getGroupId()
+ + ", uid= " + uid + ")...");
setSandmanSummonedLocked(/* isSandmanSummoned= */ true);
setWakefulnessLocked(WAKEFULNESS_DOZING, eventTime, uid, reason, /* opUid= */ 0,
@@ -273,16 +266,14 @@
return true;
}
- boolean sleepLocked(long eventTime, int uid, @PowerManager.GoToSleepReason int reason) {
+ boolean sleepLocked(long eventTime, int uid, int reason) {
if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "sleepPowerGroup");
try {
- Slog.i(TAG,
- "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ", reason="
- + PowerManager.sleepReasonToString(reason) + ")...");
+ Slog.i(TAG, "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ")...");
setSandmanSummonedLocked(/* isSandmanSummoned= */ true);
setWakefulnessLocked(WAKEFULNESS_ASLEEP, eventTime, uid, reason, /* opUid= */0,
/* opPackageName= */ null, /* details= */ null);
@@ -296,20 +287,16 @@
return mLastUserActivityTime;
}
- void setLastUserActivityTimeLocked(long lastUserActivityTime,
- @PowerManager.UserActivityEvent int event) {
+ void setLastUserActivityTimeLocked(long lastUserActivityTime) {
mLastUserActivityTime = lastUserActivityTime;
- mLastUserActivityEvent = event;
}
public long getLastUserActivityTimeNoChangeLightsLocked() {
return mLastUserActivityTimeNoChangeLights;
}
- public void setLastUserActivityTimeNoChangeLightsLocked(long time,
- @PowerManager.UserActivityEvent int event) {
+ public void setLastUserActivityTimeNoChangeLightsLocked(long time) {
mLastUserActivityTimeNoChangeLights = time;
- mLastUserActivityEvent = event;
}
public int getUserActivitySummaryLocked() {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index bc93cb3..dbf05f1 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1169,7 +1169,6 @@
return;
}
- Slog.i(TAG, "onFlip(): Face " + (isFaceDown ? "down." : "up."));
mIsFaceDown = isFaceDown;
if (isFaceDown) {
final long currentTime = mClock.uptimeMillis();
@@ -1889,13 +1888,12 @@
// Called from native code.
@SuppressWarnings("unused")
- private void userActivityFromNative(long eventTime, @PowerManager.UserActivityEvent int event,
- int displayId, int flags) {
+ private void userActivityFromNative(long eventTime, int event, int displayId, int flags) {
userActivityInternal(displayId, eventTime, event, flags, Process.SYSTEM_UID);
}
- private void userActivityInternal(int displayId, long eventTime,
- @PowerManager.UserActivityEvent int event, int flags, int uid) {
+ private void userActivityInternal(int displayId, long eventTime, int event, int flags,
+ int uid) {
synchronized (mLock) {
if (displayId == Display.INVALID_DISPLAY) {
if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {
@@ -1946,12 +1944,11 @@
@GuardedBy("mLock")
private boolean userActivityNoUpdateLocked(final PowerGroup powerGroup, long eventTime,
- @PowerManager.UserActivityEvent int event, int flags, int uid) {
+ int event, int flags, int uid) {
final int groupId = powerGroup.getGroupId();
if (DEBUG_SPEW) {
Slog.d(TAG, "userActivityNoUpdateLocked: groupId=" + groupId
- + ", eventTime=" + eventTime
- + ", event=" + PowerManager.userActivityEventToString(event)
+ + ", eventTime=" + eventTime + ", event=" + event
+ ", flags=0x" + Integer.toHexString(flags) + ", uid=" + uid);
}
@@ -1986,7 +1983,7 @@
if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
if (eventTime > powerGroup.getLastUserActivityTimeNoChangeLightsLocked()
&& eventTime > powerGroup.getLastUserActivityTimeLocked()) {
- powerGroup.setLastUserActivityTimeNoChangeLightsLocked(eventTime, event);
+ powerGroup.setLastUserActivityTimeNoChangeLightsLocked(eventTime);
mDirty |= DIRTY_USER_ACTIVITY;
if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
mDirty |= DIRTY_QUIESCENT;
@@ -1996,7 +1993,7 @@
}
} else {
if (eventTime > powerGroup.getLastUserActivityTimeLocked()) {
- powerGroup.setLastUserActivityTimeLocked(eventTime, event);
+ powerGroup.setLastUserActivityTimeLocked(eventTime);
mDirty |= DIRTY_USER_ACTIVITY;
if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
mDirty |= DIRTY_QUIESCENT;
@@ -2023,8 +2020,7 @@
@WakeReason int reason, String details, int uid, String opPackageName, int opUid) {
if (DEBUG_SPEW) {
Slog.d(TAG, "wakePowerGroupLocked: eventTime=" + eventTime
- + ", groupId=" + powerGroup.getGroupId()
- + ", reason=" + PowerManager.wakeReasonToString(reason) + ", uid=" + uid);
+ + ", groupId=" + powerGroup.getGroupId() + ", uid=" + uid);
}
if (mForceSuspendActive || !mSystemReady) {
return;
@@ -2047,11 +2043,11 @@
@GuardedBy("mLock")
private boolean dozePowerGroupLocked(final PowerGroup powerGroup, long eventTime,
- @GoToSleepReason int reason, int uid) {
+ int reason, int uid) {
if (DEBUG_SPEW) {
Slog.d(TAG, "dozePowerGroup: eventTime=" + eventTime
- + ", groupId=" + powerGroup.getGroupId()
- + ", reason=" + PowerManager.sleepReasonToString(reason) + ", uid=" + uid);
+ + ", groupId=" + powerGroup.getGroupId() + ", reason=" + reason
+ + ", uid=" + uid);
}
if (!mSystemReady || !mBootCompleted) {
@@ -2062,12 +2058,10 @@
}
@GuardedBy("mLock")
- private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime,
- @GoToSleepReason int reason, int uid) {
+ private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime, int reason,
+ int uid) {
if (DEBUG_SPEW) {
- Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime
- + ", groupId=" + powerGroup.getGroupId()
- + ", reason=" + PowerManager.sleepReasonToString(reason) + ", uid=" + uid);
+ Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime + ", uid=" + uid);
}
if (!mBootCompleted || !mSystemReady) {
return false;
@@ -2128,10 +2122,7 @@
case WAKEFULNESS_DOZING:
traceMethodName = "goToSleep";
Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason)
- + " (uid " + uid + ", screenOffTimeout=" + mScreenOffTimeoutSetting
- + ", activityTimeoutWM=" + mUserActivityTimeoutOverrideFromWindowManager
- + ", maxDimRatio=" + mMaximumScreenDimRatioConfig
- + ", maxDimDur=" + mMaximumScreenDimDurationConfig + ")...");
+ + " (uid " + uid + ")...");
mLastGlobalSleepTime = eventTime;
mLastGlobalSleepReason = reason;
@@ -4216,7 +4207,7 @@
void onUserActivity() {
synchronized (mLock) {
mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP).setLastUserActivityTimeLocked(
- mClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_OTHER);
+ mClock.uptimeMillis());
}
}
@@ -5599,8 +5590,7 @@
}
@Override // Binder call
- public void userActivity(int displayId, long eventTime,
- @PowerManager.UserActivityEvent int event, int flags) {
+ public void userActivity(int displayId, long eventTime, int event, int flags) {
final long now = mClock.uptimeMillis();
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 53b8b53..690dd10 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -21,7 +21,6 @@
import android.hardware.fingerprint.IUdfpsHbmListener;
import android.os.Bundle;
import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
import android.view.InsetsState.InternalInsetsType;
import android.view.InsetsVisibilities;
import android.view.WindowInsetsController.Appearance;
@@ -162,11 +161,6 @@
boolean requestWindowMagnificationConnection(boolean request);
/**
- * Handles a logging command from the WM shell command.
- */
- void handleWindowManagerLoggingCommand(String[] args, ParcelFileDescriptor outFd);
-
- /**
* @see com.android.internal.statusbar.IStatusBar#setNavigationBarLumaSamplingEnabled(int,
* boolean)
*/
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index bec3754..653b51a9 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -62,7 +62,6 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
@@ -664,15 +663,6 @@
}
@Override
- public void handleWindowManagerLoggingCommand(String[] args, ParcelFileDescriptor outFd) {
- if (mBar != null) {
- try {
- mBar.handleWindowManagerLoggingCommand(args, outFd);
- } catch (RemoteException ex) { }
- }
- }
-
- @Override
public void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {
if (mBar != null) {
try {
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index a375d0a..83caa0e 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -71,7 +71,8 @@
IGNORED_FOR_POWER(VibrationProto.IGNORED_FOR_POWER),
IGNORED_FOR_RINGER_MODE(VibrationProto.IGNORED_FOR_RINGER_MODE),
IGNORED_FOR_SETTINGS(VibrationProto.IGNORED_FOR_SETTINGS),
- IGNORED_SUPERSEDED(VibrationProto.IGNORED_SUPERSEDED);
+ IGNORED_SUPERSEDED(VibrationProto.IGNORED_SUPERSEDED),
+ IGNORED_FROM_VIRTUAL_DEVICE(VibrationProto.IGNORED_FROM_VIRTUAL_DEVICE);
private final int mProtoEnumValue;
@@ -87,6 +88,7 @@
public final VibrationAttributes attrs;
public final long id;
public final int uid;
+ public final int displayId;
public final String opPkg;
public final String reason;
public final IBinder token;
@@ -113,12 +115,13 @@
private final CountDownLatch mCompletionLatch = new CountDownLatch(1);
Vibration(IBinder token, int id, CombinedVibration effect,
- VibrationAttributes attrs, int uid, String opPkg, String reason) {
+ VibrationAttributes attrs, int uid, int displayId, String opPkg, String reason) {
this.token = token;
this.mEffect = effect;
this.id = id;
this.attrs = attrs;
this.uid = uid;
+ this.displayId = displayId;
this.opPkg = opPkg;
this.reason = reason;
mStatus = Vibration.Status.RUNNING;
@@ -236,7 +239,7 @@
/** Return {@link Vibration.DebugInfo} with read-only debug information about this vibration. */
public Vibration.DebugInfo getDebugInfo() {
return new Vibration.DebugInfo(mStatus, mStats, mEffect, mOriginalEffect, /* scale= */ 0,
- attrs, uid, opPkg, reason);
+ attrs, uid, displayId, opPkg, reason);
}
/** Return {@link VibrationStats.StatsInfo} with read-only metrics about this vibration. */
@@ -304,13 +307,14 @@
private final float mScale;
private final VibrationAttributes mAttrs;
private final int mUid;
+ private final int mDisplayId;
private final String mOpPkg;
private final String mReason;
private final Status mStatus;
DebugInfo(Status status, VibrationStats stats, @Nullable CombinedVibration effect,
@Nullable CombinedVibration originalEffect, float scale, VibrationAttributes attrs,
- int uid, String opPkg, String reason) {
+ int uid, int displayId, String opPkg, String reason) {
mCreateTime = stats.getCreateTimeDebug();
mStartTime = stats.getStartTimeDebug();
mEndTime = stats.getEndTimeDebug();
@@ -320,6 +324,7 @@
mScale = scale;
mAttrs = attrs;
mUid = uid;
+ mDisplayId = displayId;
mOpPkg = opPkg;
mReason = reason;
mStatus = status;
@@ -349,6 +354,8 @@
.append(mAttrs)
.append(", uid: ")
.append(mUid)
+ .append(", displayId: ")
+ .append(mDisplayId)
.append(", opPkg: ")
.append(mOpPkg)
.append(", reason: ")
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index 8e6a290..6012993 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -56,10 +56,12 @@
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
+import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
+import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
import java.util.ArrayList;
import java.util.Arrays;
@@ -157,6 +159,7 @@
final UidObserver mUidObserver;
@VisibleForTesting
final SettingsBroadcastReceiver mSettingChangeReceiver;
+ final VirtualDeviceListener mVirtualDeviceListener;
@GuardedBy("mLock")
private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>();
@@ -193,6 +196,7 @@
mSettingObserver = new SettingsContentObserver(handler);
mUidObserver = new UidObserver();
mSettingChangeReceiver = new SettingsBroadcastReceiver();
+ mVirtualDeviceListener = new VirtualDeviceListener();
mSystemUiPackage = LocalServices.getService(PackageManagerInternal.class)
.getSystemUiServiceComponent().getPackageName();
@@ -257,6 +261,13 @@
}
});
+ VirtualDeviceManagerInternal vdm = LocalServices.getService(
+ VirtualDeviceManagerInternal.class);
+ if (vdm != null) {
+ vdm.registerVirtualDisplayListener(mVirtualDeviceListener);
+ vdm.registerAppsOnVirtualDeviceListener(mVirtualDeviceListener);
+ }
+
registerSettingsChangeReceiver(USER_SWITCHED_INTENT_FILTER);
registerSettingsChangeReceiver(INTERNAL_RINGER_MODE_CHANGED_INTENT_FILTER);
@@ -364,13 +375,17 @@
* null otherwise.
*/
@Nullable
- public Vibration.Status shouldIgnoreVibration(int uid, VibrationAttributes attrs) {
+ public Vibration.Status shouldIgnoreVibration(int uid, int displayId,
+ VibrationAttributes attrs) {
final int usage = attrs.getUsage();
synchronized (mLock) {
if (!mUidObserver.isUidForeground(uid)
&& !BACKGROUND_PROCESS_USAGE_ALLOWLIST.contains(usage)) {
return Vibration.Status.IGNORED_BACKGROUND;
}
+ if (mVirtualDeviceListener.isAppOrDisplayOnAnyVirtualDevice(uid, displayId)) {
+ return Vibration.Status.IGNORED_FROM_VIRTUAL_DEVICE;
+ }
if (mBatterySaverMode && !BATTERY_SAVER_USAGE_ALLOWLIST.contains(usage)) {
return Vibration.Status.IGNORED_FOR_POWER;
@@ -741,4 +756,73 @@
public void onUidProcAdjChanged(int uid) {
}
}
+
+ /**
+ * Implementation of Virtual Device listeners for the changes of virtual displays and of apps
+ * running on any virtual device.
+ */
+ final class VirtualDeviceListener implements
+ VirtualDeviceManagerInternal.VirtualDisplayListener,
+ VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener {
+ @GuardedBy("mLock")
+ private final Set<Integer> mVirtualDisplays = new HashSet<>();
+ @GuardedBy("mLock")
+ private final Set<Integer> mAppsOnVirtualDevice = new HashSet<>();
+
+
+ @Override
+ public void onVirtualDisplayCreated(int displayId) {
+ synchronized (mLock) {
+ mVirtualDisplays.add(displayId);
+ }
+ }
+
+ @Override
+ public void onVirtualDisplayRemoved(int displayId) {
+ synchronized (mLock) {
+ mVirtualDisplays.remove(displayId);
+ }
+ }
+
+
+ @Override
+ public void onAppsOnAnyVirtualDeviceChanged(Set<Integer> allRunningUids) {
+ synchronized (mLock) {
+ mAppsOnVirtualDevice.clear();
+ mAppsOnVirtualDevice.addAll(allRunningUids);
+ }
+ }
+
+ /**
+ * @param uid: uid of the calling app.
+ * @param displayId: the id of a Display.
+ * @return Returns true if:
+ * <ul>
+ * <li> the displayId is valid, and it's owned by a virtual device.</li>
+ * <li> the displayId is invalid, and the calling app (uid) is running on a virtual
+ * device.</li>
+ * </ul>
+ */
+ public boolean isAppOrDisplayOnAnyVirtualDevice(int uid, int displayId) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ // The default display is the primary physical display on the phone.
+ return false;
+ }
+
+ synchronized (mLock) {
+ if (displayId == Display.INVALID_DISPLAY) {
+ // There is no Display object associated with the Context of calling
+ // {@link SystemVibratorManager}, checking the calling UID instead.
+ return mAppsOnVirtualDevice.contains(uid);
+ } else {
+ // Other valid display IDs representing valid logical displays will be
+ // checked
+ // against the active virtual displays set built with the registered
+ // {@link VirtualDisplayListener}.
+ return mVirtualDisplays.contains(displayId);
+ }
+ }
+ }
+
+ }
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 2f12a82..9727558 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -58,6 +58,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
+import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -378,9 +379,9 @@
}
@Override // Binder call
- public void vibrate(int uid, String opPkg, @NonNull CombinedVibration effect,
+ public void vibrate(int uid, int displayId, String opPkg, @NonNull CombinedVibration effect,
@Nullable VibrationAttributes attrs, String reason, IBinder token) {
- vibrateInternal(uid, opPkg, effect, attrs, reason, token);
+ vibrateInternal(uid, displayId, opPkg, effect, attrs, reason, token);
}
/**
@@ -389,8 +390,9 @@
*/
@Nullable
@VisibleForTesting
- Vibration vibrateInternal(int uid, String opPkg, @NonNull CombinedVibration effect,
- @Nullable VibrationAttributes attrs, String reason, IBinder token) {
+ Vibration vibrateInternal(int uid, int displayId, String opPkg,
+ @NonNull CombinedVibration effect, @Nullable VibrationAttributes attrs,
+ String reason, IBinder token) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate, reason = " + reason);
try {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.VIBRATE, "vibrate");
@@ -406,7 +408,7 @@
attrs = fixupVibrationAttributes(attrs, effect);
// Create Vibration.Stats as close to the received request as possible, for tracking.
Vibration vib = new Vibration(token, mNextVibrationId.getAndIncrement(), effect, attrs,
- uid, opPkg, reason);
+ uid, displayId, opPkg, reason);
fillVibrationFallbacks(vib, effect);
if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
@@ -424,7 +426,7 @@
Vibration.Status status = null;
// Check if user settings or DnD is set to ignore this vibration.
- status = shouldIgnoreVibrationLocked(vib.uid, vib.opPkg, vib.attrs);
+ status = shouldIgnoreVibrationLocked(vib.uid, vib.displayId, vib.opPkg, vib.attrs);
// Check if something has external control, assume it's more important.
if ((status == null) && (mCurrentExternalVibration != null)) {
@@ -629,7 +631,7 @@
Vibration vib = mCurrentVibration.getVibration();
Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(
- vib.uid, vib.opPkg, vib.attrs);
+ vib.uid, vib.displayId, vib.opPkg, vib.attrs);
if (inputDevicesChanged || (ignoreStatus != null)) {
if (DEBUG) {
@@ -659,7 +661,7 @@
continue;
}
Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(
- vib.uid, vib.opPkg, vib.attrs);
+ vib.uid, Display.DEFAULT_DISPLAY, vib.opPkg, vib.attrs);
if (ignoreStatus == null) {
effect = mVibrationScaler.scale(effect, vib.attrs.getUsage());
} else {
@@ -780,6 +782,12 @@
+ attrs);
}
break;
+ case IGNORED_FROM_VIRTUAL_DEVICE:
+ if (DEBUG) {
+ Slog.d(TAG, "Ignoring incoming vibration because it came from a virtual"
+ + " device, attrs= " + attrs);
+ }
+ break;
default:
if (DEBUG) {
Slog.d(TAG, "Vibration for uid=" + uid + " and with attrs=" + attrs
@@ -894,9 +902,10 @@
*/
@GuardedBy("mLock")
@Nullable
- private Vibration.Status shouldIgnoreVibrationLocked(int uid, String opPkg,
+ private Vibration.Status shouldIgnoreVibrationLocked(int uid, int displayId, String opPkg,
VibrationAttributes attrs) {
- Vibration.Status statusFromSettings = mVibrationSettings.shouldIgnoreVibration(uid, attrs);
+ Vibration.Status statusFromSettings = mVibrationSettings.shouldIgnoreVibration(uid,
+ displayId, attrs);
if (statusFromSettings != null) {
return statusFromSettings;
}
@@ -1442,6 +1451,9 @@
return new Vibration.DebugInfo(
mStatus, stats, /* effect= */ null, /* originalEffect= */ null, scale,
externalVibration.getVibrationAttributes(), externalVibration.getUid(),
+ // TODO(b/243604888): propagating displayID from IExternalVibration instead of
+ // using INVALID_DISPLAY for all external vibrations.
+ Display.INVALID_DISPLAY,
externalVibration.getPackage(), /* reason= */ null);
}
@@ -1647,8 +1659,10 @@
boolean alreadyUnderExternalControl = false;
boolean waitForCompletion = false;
synchronized (mLock) {
+ // TODO(b/243604888): propagating displayID from IExternalVibration instead of
+ // using INVALID_DISPLAY for all external vibrations.
Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(
- vib.getUid(), vib.getPackage(), attrs);
+ vib.getUid(), Display.INVALID_DISPLAY, vib.getPackage(), attrs);
if (ignoreStatus != null) {
vibHolder.scale = IExternalVibratorService.SCALE_MUTE;
// Failed to start the vibration, end it and report metrics right away.
@@ -1840,8 +1854,8 @@
// only cancel background vibrations.
IBinder deathBinder = commonOptions.background ? VibratorManagerService.this
: mShellCallbacksToken;
- Vibration vib = vibrateInternal(Binder.getCallingUid(), SHELL_PACKAGE_NAME, combined,
- attrs, commonOptions.description, deathBinder);
+ Vibration vib = vibrateInternal(Binder.getCallingUid(), Display.DEFAULT_DISPLAY,
+ SHELL_PACKAGE_NAME, combined, attrs, commonOptions.description, deathBinder);
if (vib != null && !commonOptions.background) {
try {
vib.waitForEnd();
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 635cf0e..d572b1b 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -79,6 +79,7 @@
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO;
+import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY;
@@ -313,7 +314,6 @@
import android.util.TypedXmlSerializer;
import android.util.proto.ProtoOutputStream;
import android.view.AppTransitionAnimationSpec;
-import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.InputApplicationHandle;
@@ -357,6 +357,7 @@
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.WindowManagerService.H;
import com.android.server.wm.utils.InsetUtils;
+import com.android.server.wm.utils.WmDisplayCutout;
import dalvik.annotation.optimization.NeverCompile;
@@ -1582,13 +1583,6 @@
if (newParent != null && isState(RESUMED)) {
newParent.setResumedActivity(this, "onParentChanged");
- if (mStartingWindow != null && mStartingData != null
- && mStartingData.mAssociatedTask == null && newParent.isEmbedded()) {
- // The starting window should keep covering its task when the activity is
- // reparented to a task fragment that may not fill the task bounds.
- associateStartingDataWithTask();
- attachStartingSurfaceToAssociatedTask();
- }
mImeInsetsFrozenUntilStartInput = false;
}
@@ -2679,14 +2673,17 @@
}
}
+ /** Called when the starting window is added to this activity. */
void attachStartingWindow(@NonNull WindowState startingWindow) {
startingWindow.mStartingData = mStartingData;
mStartingWindow = startingWindow;
+ // The snapshot type may have called associateStartingDataWithTask().
if (mStartingData != null && mStartingData.mAssociatedTask != null) {
attachStartingSurfaceToAssociatedTask();
}
}
+ /** Makes starting window always fill the associated task. */
private void attachStartingSurfaceToAssociatedTask() {
// Associate the configuration of starting window with the task.
overrideConfigurationPropagation(mStartingWindow, mStartingData.mAssociatedTask);
@@ -2694,6 +2691,7 @@
mStartingData.mAssociatedTask.mSurfaceControl);
}
+ /** Called when the starting window is not added yet but its data is known to fill the task. */
private void associateStartingDataWithTask() {
mStartingData.mAssociatedTask = task;
task.forAllActivities(r -> {
@@ -2703,6 +2701,16 @@
});
}
+ /** Associates and attaches an added starting window to the current task. */
+ void associateStartingWindowWithTaskIfNeeded() {
+ if (mStartingWindow == null || mStartingData == null
+ || mStartingData.mAssociatedTask != null) {
+ return;
+ }
+ associateStartingDataWithTask();
+ attachStartingSurfaceToAssociatedTask();
+ }
+
void removeStartingWindow() {
boolean prevEligibleForLetterboxEducation = isEligibleForLetterboxEducation();
@@ -8811,9 +8819,25 @@
* Returns the min aspect ratio of this activity.
*/
float getMinAspectRatio() {
- if (info.applicationInfo == null || !info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO) || (
- info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY)
- && !ActivityInfo.isFixedOrientationPortrait(getRequestedOrientation()))) {
+ if (info.applicationInfo == null) {
+ return info.getMinAspectRatio();
+ }
+
+ if (!info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO)) {
+ return info.getMinAspectRatio();
+ }
+
+ if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY)
+ && !ActivityInfo.isFixedOrientationPortrait(getRequestedOrientation())) {
+ return info.getMinAspectRatio();
+ }
+
+ if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN)
+ && getParent().getConfiguration().orientation == ORIENTATION_PORTRAIT
+ && getParent().getWindowConfiguration().getWindowingMode()
+ == WINDOWING_MODE_FULLSCREEN) {
+ // We are using the parent configuration here as this is the most recent one that gets
+ // passed to onConfigurationChanged when a relevant change takes place
return info.getMinAspectRatio();
}
@@ -9694,9 +9718,8 @@
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
final int dw = rotated ? display.mBaseDisplayHeight : display.mBaseDisplayWidth;
final int dh = rotated ? display.mBaseDisplayWidth : display.mBaseDisplayHeight;
- final DisplayCutout cutout = display.calculateDisplayCutoutForRotation(rotation)
- .getDisplayCutout();
- policy.getNonDecorInsetsLw(rotation, cutout, mNonDecorInsets[rotation]);
+ final WmDisplayCutout cutout = display.calculateDisplayCutoutForRotation(rotation);
+ policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]);
mStableInsets[rotation].set(mNonDecorInsets[rotation]);
policy.convertNonDecorInsetsToStableInsets(mStableInsets[rotation], rotation);
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 0c97e1c..fc3320e 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2455,6 +2455,7 @@
mInTask = null;
mInTaskFragment = null;
+ mAddingToTaskFragment = null;
mAddingToTask = false;
mNewTaskInfo = null;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index d4bbc86..7e310b4 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -226,6 +226,7 @@
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
import android.view.WindowManager;
+import android.window.BackAnimationAdaptor;
import android.window.BackNavigationInfo;
import android.window.IWindowOrganizerController;
import android.window.SplashScreenView.SplashScreenViewParcelable;
@@ -457,7 +458,7 @@
private final ClientLifecycleManager mLifecycleManager;
@Nullable
- private final BackNavigationController mBackNavigationController;
+ final BackNavigationController mBackNavigationController;
private TaskChangeNotificationController mTaskChangeNotificationController;
/** The controller for all operations related to locktask. */
@@ -1486,7 +1487,7 @@
a.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
a.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
a.resizeMode = RESIZE_MODE_UNRESIZEABLE;
- a.configChanges = ActivityInfo.CONFIG_ORIENTATION;
+ a.configChanges = 0xffffffff;
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchActivityType(ACTIVITY_TYPE_DREAM);
@@ -1836,13 +1837,14 @@
@Override
public BackNavigationInfo startBackNavigation(boolean requestAnimation,
- IWindowFocusObserver observer) {
+ IWindowFocusObserver observer, BackAnimationAdaptor backAnimationAdaptor) {
mAmInternal.enforceCallingPermission(START_TASKS_FROM_RECENTS,
"startBackNavigation()");
if (mBackNavigationController == null) {
return null;
}
- return mBackNavigationController.startBackNavigation(requestAnimation, observer);
+ return mBackNavigationController.startBackNavigation(
+ requestAnimation, observer, backAnimationAdaptor);
}
/**
diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
index 9a94a4f..d345227 100644
--- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java
+++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
@@ -22,6 +22,7 @@
import static com.android.server.wm.WindowState.BLAST_TIMEOUT_DURATION;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.os.Trace;
import android.util.ArraySet;
import android.util.Slog;
@@ -63,6 +64,15 @@
class BLASTSyncEngine {
private static final String TAG = "BLASTSyncEngine";
+ /** No specific method. Used by override specifiers. */
+ public static final int METHOD_UNDEFINED = -1;
+
+ /** No sync method. Apps will draw/present internally and just report. */
+ public static final int METHOD_NONE = 0;
+
+ /** Sync with BLAST. Apps will draw and then send the buffer to be applied in sync. */
+ public static final int METHOD_BLAST = 1;
+
interface TransactionReadyListener {
void onTransactionReady(int mSyncId, SurfaceControl.Transaction transaction);
}
@@ -85,6 +95,7 @@
*/
class SyncGroup {
final int mSyncId;
+ final int mSyncMethod;
final TransactionReadyListener mListener;
final Runnable mOnTimeout;
boolean mReady = false;
@@ -92,8 +103,9 @@
private SurfaceControl.Transaction mOrphanTransaction = null;
private String mTraceName;
- private SyncGroup(TransactionReadyListener listener, int id, String name) {
+ private SyncGroup(TransactionReadyListener listener, int id, String name, int method) {
mSyncId = id;
+ mSyncMethod = method;
mListener = listener;
mOnTimeout = () -> {
Slog.w(TAG, "Sync group " + mSyncId + " timeout");
@@ -271,16 +283,13 @@
* Prepares a {@link SyncGroup} that is not active yet. Caller must call {@link #startSyncSet}
* before calling {@link #addToSyncSet(int, WindowContainer)} on any {@link WindowContainer}.
*/
- SyncGroup prepareSyncSet(TransactionReadyListener listener, String name) {
- return new SyncGroup(listener, mNextSyncId++, name);
+ SyncGroup prepareSyncSet(TransactionReadyListener listener, String name, int method) {
+ return new SyncGroup(listener, mNextSyncId++, name, method);
}
- int startSyncSet(TransactionReadyListener listener) {
- return startSyncSet(listener, BLAST_TIMEOUT_DURATION, "");
- }
-
- int startSyncSet(TransactionReadyListener listener, long timeoutMs, String name) {
- final SyncGroup s = prepareSyncSet(listener, name);
+ int startSyncSet(TransactionReadyListener listener, long timeoutMs, String name,
+ int method) {
+ final SyncGroup s = prepareSyncSet(listener, name, method);
startSyncSet(s, timeoutMs);
return s.mSyncId;
}
@@ -302,6 +311,11 @@
scheduleTimeout(s, timeoutMs);
}
+ @Nullable
+ SyncGroup getSyncSet(int id) {
+ return mActiveSyncs.get(id);
+ }
+
boolean hasActiveSync() {
return mActiveSyncs.size() != 0;
}
diff --git a/services/core/java/com/android/server/wm/BackNaviAnimationController.java b/services/core/java/com/android/server/wm/BackNaviAnimationController.java
new file mode 100644
index 0000000..ecc7534
--- /dev/null
+++ b/services/core/java/com/android/server/wm/BackNaviAnimationController.java
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.view.RemoteAnimationTarget.MODE_CLOSING;
+import static android.view.RemoteAnimationTarget.MODE_OPENING;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
+
+import android.annotation.NonNull;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
+import android.view.WindowInsets;
+import android.window.BackNavigationInfo;
+import android.window.IBackAnimationRunner;
+import android.window.IBackNaviAnimationController;
+
+import com.android.server.wm.utils.InsetUtils;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Controls the back navigation animation.
+ * This is throw-away code and should only be used for Android T, most code is duplicated from
+ * RecentsAnimationController which should be stable to handle animation leash resources/flicker/
+ * fixed rotation, etc. Remove this class at U and migrate to shell transition.
+ */
+public class BackNaviAnimationController implements IBinder.DeathRecipient {
+ private static final String TAG = BackNavigationController.TAG;
+ // Constant for a yet-to-be-calculated {@link RemoteAnimationTarget#Mode} state
+ private static final int MODE_UNKNOWN = -1;
+
+ // The activity which host this animation
+ private ActivityRecord mTargetActivityRecord;
+ // The original top activity
+ private ActivityRecord mTopActivity;
+
+ private final DisplayContent mDisplayContent;
+ private final WindowManagerService mWindowManagerService;
+ private final BackNavigationController mBackNavigationController;
+
+ // We start the BackAnimationController in a pending-start state since we need to wait for
+ // the wallpaper/activity to draw before we can give control to the handler to start animating
+ // the visible task surfaces
+ private boolean mPendingStart;
+ private IBackAnimationRunner mRunner;
+ final IBackNaviAnimationController mRemoteController;
+ private boolean mLinkedToDeathOfRunner;
+
+ private final ArrayList<TaskAnimationAdapter> mPendingAnimations = new ArrayList<>();
+
+ BackNaviAnimationController(IBackAnimationRunner runner,
+ BackNavigationController backNavigationController, int displayId) {
+ mRunner = runner;
+ mBackNavigationController = backNavigationController;
+ mWindowManagerService = mBackNavigationController.mWindowManagerService;
+ mDisplayContent = mWindowManagerService.mRoot.getDisplayContent(displayId);
+
+ mRemoteController = new IBackNaviAnimationController.Stub() {
+ @Override
+ public void finish(boolean triggerBack) {
+ synchronized (mWindowManagerService.getWindowManagerLock()) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mWindowManagerService.inSurfaceTransaction(() -> {
+ mWindowManagerService.mAtmService.deferWindowLayout();
+ try {
+ if (triggerBack) {
+ mDisplayContent.mFixedRotationTransitionListener
+ .notifyRecentsWillBeTop();
+ if (mTopActivity != null) {
+ mWindowManagerService.mTaskSnapshotController
+ .recordTaskSnapshot(mTopActivity.getTask(), false);
+ // TODO consume moveTaskToBack?
+ mTopActivity.commitVisibility(false, false, true);
+ }
+ } else {
+ mTargetActivityRecord.mTaskSupervisor
+ .scheduleLaunchTaskBehindComplete(
+ mTargetActivityRecord.token);
+ }
+ cleanupAnimation();
+ } finally {
+ mWindowManagerService.mAtmService.continueWindowLayout();
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+ };
+ }
+
+ /**
+ * @param targetActivity The home or opening activity which should host the wallpaper
+ * @param topActivity The current top activity before animation start.
+ */
+ void initialize(ActivityRecord targetActivity, ActivityRecord topActivity) {
+ mTargetActivityRecord = targetActivity;
+ mTopActivity = topActivity;
+ final Task topTask = mTopActivity.getTask();
+
+ createAnimationAdapter(topTask, (type, anim) -> topTask.forAllWindows(
+ win -> {
+ win.onAnimationFinished(type, anim);
+ }, true));
+ final Task homeTask = mTargetActivityRecord.getRootTask();
+ createAnimationAdapter(homeTask, (type, anim) -> homeTask.forAllWindows(
+ win -> {
+ win.onAnimationFinished(type, anim);
+ }, true));
+ try {
+ linkToDeathOfRunner();
+ } catch (RemoteException e) {
+ cancelAnimation();
+ return;
+ }
+
+ if (targetActivity.windowsCanBeWallpaperTarget()) {
+ mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ mDisplayContent.setLayoutNeeded();
+ }
+
+ mWindowManagerService.mWindowPlacerLocked.performSurfacePlacement();
+
+ mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(targetActivity);
+ mPendingStart = true;
+ }
+
+ void cleanupAnimation() {
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
+
+ removeAnimationAdapter(taskAdapter);
+ taskAdapter.onCleanup();
+ }
+ mTargetActivityRecord.mLaunchTaskBehind = false;
+ // Clear references to the runner
+ unlinkToDeathOfRunner();
+ mRunner = null;
+
+ // Update the input windows after the animation is complete
+ final InputMonitor inputMonitor = mDisplayContent.getInputMonitor();
+ inputMonitor.updateInputWindowsLw(true /*force*/);
+
+ mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation();
+ mBackNavigationController.finishAnimation();
+ }
+
+ void removeAnimationAdapter(TaskAnimationAdapter taskAdapter) {
+ taskAdapter.onRemove();
+ mPendingAnimations.remove(taskAdapter);
+ }
+
+ void checkAnimationReady(WallpaperController wallpaperController) {
+ if (mPendingStart) {
+ final boolean wallpaperReady = !isTargetOverWallpaper()
+ || (wallpaperController.getWallpaperTarget() != null
+ && wallpaperController.wallpaperTransitionReady());
+ if (wallpaperReady) {
+ startAnimation();
+ }
+ }
+ }
+
+ boolean isWallpaperVisible(WindowState w) {
+ return w != null && w.mAttrs.type == TYPE_BASE_APPLICATION
+ && ((w.mActivityRecord != null && mTargetActivityRecord == w.mActivityRecord)
+ || isAnimatingTask(w.getTask()))
+ && isTargetOverWallpaper() && w.isOnScreen();
+ }
+
+ boolean isAnimatingTask(Task task) {
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ if (task == mPendingAnimations.get(i).mTask) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void linkFixedRotationTransformIfNeeded(@NonNull WindowToken wallpaper) {
+ if (mTargetActivityRecord == null) {
+ return;
+ }
+ wallpaper.linkFixedRotationTransform(mTargetActivityRecord);
+ }
+
+ private void linkToDeathOfRunner() throws RemoteException {
+ if (!mLinkedToDeathOfRunner) {
+ mRunner.asBinder().linkToDeath(this, 0);
+ mLinkedToDeathOfRunner = true;
+ }
+ }
+
+ private void unlinkToDeathOfRunner() {
+ if (mLinkedToDeathOfRunner) {
+ mRunner.asBinder().unlinkToDeath(this, 0);
+ mLinkedToDeathOfRunner = false;
+ }
+ }
+
+ void startAnimation() {
+ if (!mPendingStart) {
+ // Skip starting if we've already started or canceled the animation
+ return;
+ }
+ // Create the app targets
+ final RemoteAnimationTarget[] appTargets = createAppAnimations();
+
+ // Skip the animation if there is nothing to animate
+ if (appTargets.length == 0) {
+ cancelAnimation();
+ return;
+ }
+
+ mPendingStart = false;
+
+ try {
+ mRunner.onAnimationStart(mRemoteController, BackNavigationInfo.TYPE_RETURN_TO_HOME,
+ appTargets, null /* wallpapers */, null /*nonApps*/);
+ } catch (RemoteException e) {
+ cancelAnimation();
+ }
+ }
+
+ @Override
+ public void binderDied() {
+ cancelAnimation();
+ }
+
+ TaskAnimationAdapter createAnimationAdapter(Task task,
+ SurfaceAnimator.OnAnimationFinishedCallback finishedCallback) {
+ final TaskAnimationAdapter taskAdapter = new TaskAnimationAdapter(task,
+ mTargetActivityRecord, this::cancelAnimation);
+ // borrow from recents since we cannot start back animation if recents is playing
+ task.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */,
+ ANIMATION_TYPE_RECENTS, finishedCallback);
+ task.commitPendingTransaction();
+ mPendingAnimations.add(taskAdapter);
+ return taskAdapter;
+ }
+
+ private RemoteAnimationTarget[] createAppAnimations() {
+ final ArrayList<RemoteAnimationTarget> targets = new ArrayList<>();
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
+ final RemoteAnimationTarget target =
+ taskAdapter.createRemoteAnimationTarget(INVALID_TASK_ID, MODE_UNKNOWN);
+ if (target != null) {
+ targets.add(target);
+ } else {
+ removeAnimationAdapter(taskAdapter);
+ }
+ }
+ return targets.toArray(new RemoteAnimationTarget[targets.size()]);
+ }
+
+ private void cancelAnimation() {
+ synchronized (mWindowManagerService.getWindowManagerLock()) {
+ // Notify the runner and clean up the animation immediately
+ // Note: In the fallback case, this can trigger multiple onAnimationCancel() calls
+ // to the runner if we this actually triggers cancel twice on the caller
+ try {
+ mRunner.onAnimationCancelled();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to cancel recents animation", e);
+ }
+ cleanupAnimation();
+ }
+ }
+
+ private boolean isTargetOverWallpaper() {
+ if (mTargetActivityRecord == null) {
+ return false;
+ }
+ return mTargetActivityRecord.windowsCanBeWallpaperTarget();
+ }
+
+ private static class TaskAnimationAdapter implements AnimationAdapter {
+ private final Task mTask;
+ private SurfaceControl mCapturedLeash;
+ private SurfaceAnimator.OnAnimationFinishedCallback mCapturedFinishCallback;
+ @SurfaceAnimator.AnimationType private int mLastAnimationType;
+ private RemoteAnimationTarget mTarget;
+ private final ActivityRecord mTargetActivityRecord;
+ private final Runnable mCancelCallback;
+
+ private final Rect mBounds = new Rect();
+ // The bounds of the target relative to its parent.
+ private final Rect mLocalBounds = new Rect();
+
+ TaskAnimationAdapter(Task task, ActivityRecord target, Runnable cancelCallback) {
+ mTask = task;
+ mBounds.set(mTask.getBounds());
+
+ mLocalBounds.set(mBounds);
+ Point tmpPos = new Point();
+ mTask.getRelativePosition(tmpPos);
+ mLocalBounds.offsetTo(tmpPos.x, tmpPos.y);
+ mTargetActivityRecord = target;
+ mCancelCallback = cancelCallback;
+ }
+
+ // Keep overrideTaskId and overrideMode now, if we need to add other type of back animation
+ // on legacy transition system then they can be useful.
+ RemoteAnimationTarget createRemoteAnimationTarget(int overrideTaskId, int overrideMode) {
+ ActivityRecord topApp = mTask.getTopRealVisibleActivity();
+ if (topApp == null) {
+ topApp = mTask.getTopVisibleActivity();
+ }
+ final WindowState mainWindow = topApp != null
+ ? topApp.findMainWindow()
+ : null;
+ if (mainWindow == null) {
+ return null;
+ }
+ final Rect insets =
+ mainWindow.getInsetsStateWithVisibilityOverride().calculateInsets(
+ mBounds, WindowInsets.Type.systemBars(),
+ false /* ignoreVisibility */).toRect();
+ InsetUtils.addInsets(insets, mainWindow.mActivityRecord.getLetterboxInsets());
+ final int mode = overrideMode != MODE_UNKNOWN
+ ? overrideMode
+ : topApp.getActivityType() == mTargetActivityRecord.getActivityType()
+ ? MODE_OPENING
+ : MODE_CLOSING;
+ if (overrideTaskId < 0) {
+ overrideTaskId = mTask.mTaskId;
+ }
+ mTarget = new RemoteAnimationTarget(overrideTaskId, mode, mCapturedLeash,
+ !topApp.fillsParent(), new Rect(),
+ insets, mTask.getPrefixOrderIndex(), new Point(mBounds.left, mBounds.top),
+ mLocalBounds, mBounds, mTask.getWindowConfiguration(),
+ true /* isNotInRecents */, null, null, mTask.getTaskInfo(),
+ topApp.checkEnterPictureInPictureAppOpsState());
+ return mTarget;
+ }
+ @Override
+ public boolean getShowWallpaper() {
+ return false;
+ }
+ @Override
+ public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t,
+ @SurfaceAnimator.AnimationType int type,
+ @NonNull SurfaceAnimator.OnAnimationFinishedCallback finishCallback) {
+ t.setPosition(animationLeash, mLocalBounds.left, mLocalBounds.top);
+ final Rect tmpRect = new Rect();
+ tmpRect.set(mLocalBounds);
+ tmpRect.offsetTo(0, 0);
+ t.setWindowCrop(animationLeash, tmpRect);
+ mCapturedLeash = animationLeash;
+ mCapturedFinishCallback = finishCallback;
+ mLastAnimationType = type;
+ }
+
+ @Override
+ public void onAnimationCancelled(SurfaceControl animationLeash) {
+ mCancelCallback.run();
+ }
+
+ void onRemove() {
+ mCapturedFinishCallback.onAnimationFinished(mLastAnimationType, this);
+ }
+
+ void onCleanup() {
+ final SurfaceControl.Transaction pendingTransaction = mTask.getPendingTransaction();
+ if (!mTask.isAttached()) {
+ // Apply the task's pending transaction in case it is detached and its transaction
+ // is not reachable.
+ pendingTransaction.apply();
+ }
+ }
+
+ @Override
+ public long getDurationHint() {
+ return 0;
+ }
+
+ @Override
+ public long getStatusBarTransitionsStartTime() {
+ return SystemClock.uptimeMillis();
+ }
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) { }
+
+ @Override
+ public void dumpDebug(ProtoOutputStream proto) { }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index d9ab971..35a39c0 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -34,6 +34,7 @@
import android.view.IWindowFocusObserver;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
+import android.window.BackAnimationAdaptor;
import android.window.BackNavigationInfo;
import android.window.OnBackInvokedCallbackInfo;
import android.window.TaskSnapshot;
@@ -46,9 +47,15 @@
* Controller to handle actions related to the back gesture on the server side.
*/
class BackNavigationController {
- private static final String TAG = "BackNavigationController";
- private WindowManagerService mWindowManagerService;
+ static final String TAG = "BackNavigationController";
+ WindowManagerService mWindowManagerService;
private IWindowFocusObserver mFocusObserver;
+ // TODO (b/241808055) Find a appropriate time to remove during refactor
+ // Execute back animation with legacy transition system. Temporary flag for easier debugging.
+ static final boolean USE_TRANSITION =
+ SystemProperties.getInt("persist.wm.debug.predictive_back_ani_trans", 1) != 0;
+
+ BackNaviAnimationController mBackNaviAnimationController;
/**
* Returns true if the back predictability feature is enabled
@@ -72,7 +79,7 @@
@VisibleForTesting
@Nullable
BackNavigationInfo startBackNavigation(boolean requestAnimation,
- IWindowFocusObserver observer) {
+ IWindowFocusObserver observer, BackAnimationAdaptor backAnimationAdaptor) {
final WindowManagerService wmService = mWindowManagerService;
final SurfaceControl.Transaction tx = wmService.mTransactionFactory.get();
mFocusObserver = observer;
@@ -259,6 +266,8 @@
&& requestAnimation
// Only create a new leash if no leash has been created.
// Otherwise return null for animation target to avoid conflict.
+ // TODO isAnimating, recents can cancel app transition animation, can't back
+ // cancel like recents?
&& !removedWindowContainer.hasCommittedReparentToAnimationLeash();
if (prepareAnimation) {
@@ -266,19 +275,21 @@
currentTask.getTaskInfo().configuration.windowConfiguration;
infoBuilder.setTaskWindowConfiguration(taskWindowConfiguration);
- // Prepare a leash to animate the current top window
- // TODO(b/220934562): Use surface animator to better manage animation conflicts.
- SurfaceControl animLeash = removedWindowContainer.makeAnimationLeash()
- .setName("BackPreview Leash for " + removedWindowContainer)
- .setHidden(false)
- .setBLASTLayer()
- .build();
- removedWindowContainer.reparentSurfaceControl(tx, animLeash);
- animationLeashParent = removedWindowContainer.getAnimationLeashParent();
- topAppTarget = createRemoteAnimationTargetLocked(removedWindowContainer,
- currentActivity,
- currentTask, animLeash);
- infoBuilder.setDepartingAnimationTarget(topAppTarget);
+ if (!USE_TRANSITION) {
+ // Prepare a leash to animate the current top window
+ // TODO(b/220934562): Use surface animator to better manage animation conflicts.
+ SurfaceControl animLeash = removedWindowContainer.makeAnimationLeash()
+ .setName("BackPreview Leash for " + removedWindowContainer)
+ .setHidden(false)
+ .setBLASTLayer()
+ .build();
+ removedWindowContainer.reparentSurfaceControl(tx, animLeash);
+ animationLeashParent = removedWindowContainer.getAnimationLeashParent();
+ topAppTarget = createRemoteAnimationTargetLocked(removedWindowContainer,
+ currentActivity,
+ currentTask, animLeash);
+ infoBuilder.setDepartingAnimationTarget(topAppTarget);
+ }
}
//TODO(207481538) Remove once the infrastructure to support per-activity screenshot is
@@ -293,21 +304,32 @@
// Special handling for back to home animation
if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && prepareAnimation
&& prevTask != null) {
- currentTask.mBackGestureStarted = true;
- // Make launcher show from behind by marking its top activity as visible and
- // launch-behind to bump its visibility for the duration of the back gesture.
- prevActivity = prevTask.getTopNonFinishingActivity();
- if (prevActivity != null) {
- if (!prevActivity.mVisibleRequested) {
- prevActivity.setVisibility(true);
+ if (USE_TRANSITION && mBackNaviAnimationController == null) {
+ if (backAnimationAdaptor != null
+ && backAnimationAdaptor.getSupportType() == backType) {
+ mBackNaviAnimationController = new BackNaviAnimationController(
+ backAnimationAdaptor.getRunner(), this,
+ currentActivity.getDisplayId());
+ prepareBackToHomeTransition(currentTask, prevTask);
+ infoBuilder.setPrepareAnimation(true);
}
- prevActivity.mLaunchTaskBehind = true;
- ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
- "Setting Activity.mLauncherTaskBehind to true. Activity=%s",
- prevActivity);
- prevActivity.mRootWindowContainer.ensureActivitiesVisible(
- null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */);
+ } else {
+ currentTask.mBackGestureStarted = true;
+ // Make launcher show from behind by marking its top activity as visible and
+ // launch-behind to bump its visibility for the duration of the back gesture.
+ prevActivity = prevTask.getTopNonFinishingActivity();
+ if (prevActivity != null) {
+ if (!prevActivity.mVisibleRequested) {
+ prevActivity.setVisibility(true);
+ }
+ prevActivity.mLaunchTaskBehind = true;
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Setting Activity.mLauncherTaskBehind to true. Activity=%s",
+ prevActivity);
+ prevActivity.mRootWindowContainer.ensureActivitiesVisible(
+ null /* starting */, 0 /* configChanges */,
+ false /* preserveWindows */);
+ }
}
}
} // Release wm Lock
@@ -388,29 +410,30 @@
BackNavigationInfo.KEY_TRIGGER_BACK);
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, "
+ "task=%s, prevActivity=%s", backType, task, prevActivity);
-
- if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && prepareAnimation) {
- if (triggerBack) {
- if (surfaceControl != null && surfaceControl.isValid()) {
- // When going back to home, hide the task surface before it is re-parented to
- // avoid flicker.
- SurfaceControl.Transaction t = windowContainer.getSyncTransaction();
- t.hide(surfaceControl);
- t.apply();
+ if (!USE_TRANSITION) {
+ if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && prepareAnimation) {
+ if (triggerBack) {
+ if (surfaceControl != null && surfaceControl.isValid()) {
+ // When going back to home, hide the task surface before it is re-parented
+ // to avoid flicker.
+ SurfaceControl.Transaction t = windowContainer.getSyncTransaction();
+ t.hide(surfaceControl);
+ t.apply();
+ }
}
+ if (prevActivity != null && !triggerBack) {
+ // Restore the launch-behind state.
+ task.mTaskSupervisor.scheduleLaunchTaskBehindComplete(prevActivity.token);
+ prevActivity.mLaunchTaskBehind = false;
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
+ prevActivity);
+ }
+ } else {
+ task.mBackGestureStarted = false;
}
- if (prevActivity != null && !triggerBack) {
- // Restore the launch-behind state.
- task.mTaskSupervisor.scheduleLaunchTaskBehindComplete(prevActivity.token);
- prevActivity.mLaunchTaskBehind = false;
- ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
- "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
- prevActivity);
- }
- } else if (task != null) {
- task.mBackGestureStarted = false;
+ resetSurfaces(windowContainer);
}
- resetSurfaces(windowContainer);
if (mFocusObserver != null) {
focusedWindow.unregisterFocusObserver(mFocusObserver);
@@ -465,4 +488,21 @@
void setWindowManager(WindowManagerService wm) {
mWindowManagerService = wm;
}
+
+ private void prepareBackToHomeTransition(Task currentTask, Task homeTask) {
+ final DisplayContent dc = currentTask.getDisplayContent();
+ final ActivityRecord homeActivity = homeTask.getTopNonFinishingActivity();
+ if (!homeActivity.mVisibleRequested) {
+ homeActivity.setVisibility(true);
+ }
+ homeActivity.mLaunchTaskBehind = true;
+ dc.ensureActivitiesVisible(
+ null /* starting */, 0 /* configChanges */,
+ false /* preserveWindows */, true);
+ mBackNaviAnimationController.initialize(homeActivity, currentTask.getTopMostActivity());
+ }
+
+ void finishAnimation() {
+ mBackNaviAnimationController = null;
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b645254..603a792 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -61,6 +61,7 @@
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
import static android.view.WindowManager.LayoutParams;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -94,6 +95,7 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WALLPAPER;
@@ -182,11 +184,13 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
+import android.os.WorkSource;
import android.provider.Settings;
import android.util.ArraySet;
import android.util.DisplayMetrics;
@@ -438,7 +442,7 @@
*/
final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
- /** @see #computeCompatSmallestWidth(boolean, int, int, int) */
+ /** @see #computeCompatSmallestWidth(boolean, int, int) */
private final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
/**
@@ -698,10 +702,33 @@
*/
private boolean mInEnsureActivitiesVisible = false;
- // Used to indicate that the movement of child tasks to top will not move the display to top as
- // well and thus won't change the top resumed / focused record
+ /**
+ * Used to indicate that the movement of child tasks to top will not move the display to top as
+ * well and thus won't change the top resumed / focused record
+ */
boolean mDontMoveToTop;
+ /** Used for windows that want to keep the screen awake. */
+ private PowerManager.WakeLock mHoldScreenWakeLock;
+
+ /** The current window causing mHoldScreenWakeLock to be held. */
+ private WindowState mHoldScreenWindow;
+
+ /**
+ * Used during updates to temporarily store what will become the next value for
+ * mHoldScreenWindow.
+ */
+ private WindowState mTmpHoldScreenWindow;
+
+ /** Last window that obscures all windows below. */
+ private WindowState mObscuringWindow;
+
+ /** Last window which obscured a window holding the screen locked. */
+ private WindowState mLastWakeLockObscuringWindow;
+
+ /** Last window to hold the screen locked. */
+ private WindowState mLastWakeLockHoldingWindow;
+
/**
* The helper of policy controller.
*
@@ -914,7 +941,7 @@
if (isDisplayed && w.isObscuringDisplay()) {
// This window completely covers everything behind it, so we want to leave all
// of them as undimmed (for performance reasons).
- root.mObscuringWindow = w;
+ mObscuringWindow = w;
mTmpApplySurfaceChangesTransactionState.obscured = true;
}
@@ -928,6 +955,15 @@
}
if (w.mHasSurface && isDisplayed) {
+ if ((w.mAttrs.flags & FLAG_KEEP_SCREEN_ON) != 0) {
+ mTmpHoldScreenWindow = w;
+ } else if (w == mLastWakeLockHoldingWindow) {
+ ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON,
+ "handleNotObscuredLocked: %s was holding screen wakelock but no longer "
+ + "has FLAG_KEEP_SCREEN_ON!!! called by%s",
+ w, Debug.getCallers(10));
+ }
+
final int type = w.mAttrs.type;
if (type == TYPE_SYSTEM_DIALOG
|| type == TYPE_SYSTEM_ERROR
@@ -946,7 +982,9 @@
final int preferredModeId = getDisplayPolicy().getRefreshRatePolicy()
.getPreferredModeId(w);
- if (w.isFocused() && mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
+
+ if (w.getWindowingMode() != WINDOWING_MODE_PINNED
+ && mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
&& preferredModeId != 0) {
mTmpApplySurfaceChangesTransactionState.preferredModeId = preferredModeId;
}
@@ -1035,6 +1073,7 @@
mCurrentUniqueDisplayId = display.getUniqueId();
mOffTokenAcquirer = mRootWindowContainer.mDisplayOffTokenAcquirer;
mWallpaperController = new WallpaperController(mWmService, this);
+ mWallpaperController.resetLargestDisplay(display);
display.getDisplayInfo(mDisplayInfo);
display.getMetrics(mDisplayMetrics);
mSystemGestureExclusionLimit = mWmService.mConstants.mSystemGestureExclusionLimitDp
@@ -1047,6 +1086,11 @@
calculatePrivacyIndicatorBoundsForRotation(mDisplayInfo.rotation));
initializeDisplayBaseInfo();
+ mHoldScreenWakeLock = mWmService.mPowerManager.newWakeLock(
+ PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE,
+ TAG_WM + "/displayId:" + mDisplayId, mDisplayId);
+ mHoldScreenWakeLock.setReferenceCounted(false);
+
mAppTransition = new AppTransition(mWmService.mContext, mWmService, this);
mAppTransition.registerListenerLocked(mWmService.mActivityManagerAppTransitionNotifier);
mAppTransition.registerListenerLocked(mFixedRotationTransitionListener);
@@ -1107,6 +1151,37 @@
mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this);
}
+ private void beginHoldScreenUpdate() {
+ mTmpHoldScreenWindow = null;
+ mObscuringWindow = null;
+ }
+
+ private void finishHoldScreenUpdate() {
+ final boolean hold = mTmpHoldScreenWindow != null;
+ if (hold && mTmpHoldScreenWindow != mHoldScreenWindow) {
+ mHoldScreenWakeLock.setWorkSource(new WorkSource(mTmpHoldScreenWindow.mSession.mUid));
+ }
+ mHoldScreenWindow = mTmpHoldScreenWindow;
+ mTmpHoldScreenWindow = null;
+
+ final boolean state = mHoldScreenWakeLock.isHeld();
+ if (hold != state) {
+ if (hold) {
+ ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to %s",
+ mHoldScreenWindow);
+ mLastWakeLockHoldingWindow = mHoldScreenWindow;
+ mLastWakeLockObscuringWindow = null;
+ mHoldScreenWakeLock.acquire();
+ } else {
+ ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by %s",
+ mObscuringWindow);
+ mLastWakeLockHoldingWindow = null;
+ mLastWakeLockObscuringWindow = mObscuringWindow;
+ mHoldScreenWakeLock.release();
+ }
+ }
+ }
+
@Override
void migrateToNewSurfaceControl(Transaction t) {
t.remove(mSurfaceControl);
@@ -2014,7 +2089,7 @@
// the top of the method, the caller is obligated to call computeNewConfigurationLocked().
// By updating the Display info here it will be available to
// #computeScreenConfiguration() later.
- updateDisplayAndOrientation(getConfiguration().uiMode, null /* outConfig */);
+ updateDisplayAndOrientation(null /* outConfig */);
// NOTE: We disable the rotation in the emulator because
// it doesn't support hardware OpenGL emulation yet.
@@ -2064,7 +2139,7 @@
* changed.
* Do not call if {@link WindowManagerService#mDisplayReady} == false.
*/
- private DisplayInfo updateDisplayAndOrientation(int uiMode, Configuration outConfig) {
+ private DisplayInfo updateDisplayAndOrientation(Configuration outConfig) {
// Use the effective "visual" dimensions based on current rotation
final int rotation = getRotation();
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
@@ -2076,18 +2151,16 @@
final DisplayCutout displayCutout = wmDisplayCutout.getDisplayCutout();
final RoundedCorners roundedCorners = calculateRoundedCornersForRotation(rotation);
- final int appWidth = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
- displayCutout);
- final int appHeight = mDisplayPolicy.getNonDecorDisplayHeight(dh, rotation,
- displayCutout);
+ final Rect appFrame = mDisplayPolicy.getNonDecorDisplayFrame(dw, dh, rotation,
+ wmDisplayCutout);
mDisplayInfo.rotation = rotation;
mDisplayInfo.logicalWidth = dw;
mDisplayInfo.logicalHeight = dh;
mDisplayInfo.logicalDensityDpi = mBaseDisplayDensity;
mDisplayInfo.physicalXDpi = mBaseDisplayPhysicalXDpi;
mDisplayInfo.physicalYDpi = mBaseDisplayPhysicalYDpi;
- mDisplayInfo.appWidth = appWidth;
- mDisplayInfo.appHeight = appHeight;
+ mDisplayInfo.appWidth = appFrame.width();
+ mDisplayInfo.appHeight = appFrame.height();
if (isDefaultDisplay) {
mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
@@ -2101,7 +2174,7 @@
mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
}
- computeSizeRangesAndScreenLayout(mDisplayInfo, rotated, uiMode, dw, dh,
+ computeSizeRangesAndScreenLayout(mDisplayInfo, rotated, dw, dh,
mDisplayMetrics.density, outConfig);
mWmService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId,
@@ -2191,10 +2264,8 @@
outConfig.windowConfiguration.setMaxBounds(0, 0, dw, dh);
outConfig.windowConfiguration.setBounds(outConfig.windowConfiguration.getMaxBounds());
- final int uiMode = getConfiguration().uiMode;
- final DisplayCutout displayCutout =
- calculateDisplayCutoutForRotation(rotation).getDisplayCutout();
- computeScreenAppConfiguration(outConfig, dw, dh, rotation, uiMode, displayCutout);
+ final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(rotation);
+ computeScreenAppConfiguration(outConfig, dw, dh, rotation, wmDisplayCutout);
final DisplayInfo displayInfo = new DisplayInfo(mDisplayInfo);
displayInfo.rotation = rotation;
@@ -2203,38 +2274,35 @@
final Rect appBounds = outConfig.windowConfiguration.getAppBounds();
displayInfo.appWidth = appBounds.width();
displayInfo.appHeight = appBounds.height();
+ final DisplayCutout displayCutout = wmDisplayCutout.getDisplayCutout();
displayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout;
- computeSizeRangesAndScreenLayout(displayInfo, rotated, uiMode, dw, dh,
+ computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh,
mDisplayMetrics.density, outConfig);
return displayInfo;
}
/** Compute configuration related to application without changing current display. */
private void computeScreenAppConfiguration(Configuration outConfig, int dw, int dh,
- int rotation, int uiMode, DisplayCutout displayCutout) {
- final int appWidth = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
- displayCutout);
- final int appHeight = mDisplayPolicy.getNonDecorDisplayHeight(dh, rotation,
- displayCutout);
- mDisplayPolicy.getNonDecorInsetsLw(rotation, displayCutout, mTmpRect);
- final int leftInset = mTmpRect.left;
- final int topInset = mTmpRect.top;
+ int rotation, WmDisplayCutout wmDisplayCutout) {
+ final DisplayFrames displayFrames =
+ mDisplayPolicy.getSimulatedDisplayFrames(rotation, dw, dh, wmDisplayCutout);
+ final Rect appFrame =
+ mDisplayPolicy.getNonDecorDisplayFrameWithSimulatedFrame(displayFrames);
// AppBounds at the root level should mirror the app screen size.
- outConfig.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */,
- leftInset + appWidth /* right */, topInset + appHeight /* bottom */);
+ outConfig.windowConfiguration.setAppBounds(appFrame);
outConfig.windowConfiguration.setRotation(rotation);
outConfig.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
final float density = mDisplayMetrics.density;
- outConfig.screenWidthDp = (int) (mDisplayPolicy.getConfigDisplayWidth(dw, dh, rotation,
- uiMode, displayCutout) / density + 0.5f);
- outConfig.screenHeightDp = (int) (mDisplayPolicy.getConfigDisplayHeight(dw, dh, rotation,
- uiMode, displayCutout) / density + 0.5f);
+ final Point configSize =
+ mDisplayPolicy.getConfigDisplaySizeWithSimulatedFrame(displayFrames);
+ outConfig.screenWidthDp = (int) (configSize.x / density + 0.5f);
+ outConfig.screenHeightDp = (int) (configSize.y / density + 0.5f);
outConfig.compatScreenWidthDp = (int) (outConfig.screenWidthDp / mCompatibleScreenScale);
outConfig.compatScreenHeightDp = (int) (outConfig.screenHeightDp / mCompatibleScreenScale);
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
- outConfig.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, uiMode, dw, dh);
+ outConfig.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dw, dh);
outConfig.windowConfiguration.setDisplayRotation(rotation);
}
@@ -2243,7 +2311,7 @@
* Do not call if mDisplayReady == false.
*/
void computeScreenConfiguration(Configuration config) {
- final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode, config);
+ final DisplayInfo displayInfo = updateDisplayAndOrientation(config);
final int dw = displayInfo.logicalWidth;
final int dh = displayInfo.logicalHeight;
mTmpRect.set(0, 0, dw, dh);
@@ -2252,8 +2320,8 @@
config.windowConfiguration.setWindowingMode(getWindowingMode());
config.windowConfiguration.setDisplayWindowingMode(getWindowingMode());
- computeScreenAppConfiguration(config, dw, dh, displayInfo.rotation, config.uiMode,
- displayInfo.displayCutout);
+ computeScreenAppConfiguration(config, dw, dh, displayInfo.rotation,
+ calculateDisplayCutoutForRotation(getRotation()));
config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK)
| ((displayInfo.flags & Display.FLAG_ROUND) != 0
@@ -2342,7 +2410,7 @@
mWmService.mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
}
- private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh) {
+ private int computeCompatSmallestWidth(boolean rotated, int dw, int dh) {
mTmpDisplayMetrics.setTo(mDisplayMetrics);
final DisplayMetrics tmpDm = mTmpDisplayMetrics;
final int unrotDw, unrotDh;
@@ -2353,25 +2421,20 @@
unrotDw = dw;
unrotDh = dh;
}
- int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw,
- unrotDh);
- sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh,
- unrotDw);
- sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw,
- unrotDh);
- sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh,
- unrotDw);
+ int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
+ sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
+ sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
+ sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
return sw;
}
- private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
+ private int reduceCompatConfigWidthSize(int curSize, int rotation,
DisplayMetrics dm, int dw, int dh) {
- final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
- rotation).getDisplayCutout();
- dm.noncompatWidthPixels = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
- displayCutout);
- dm.noncompatHeightPixels = mDisplayPolicy.getNonDecorDisplayHeight(dh, rotation,
- displayCutout);
+ final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(rotation);
+ final Rect nonDecorSize = mDisplayPolicy.getNonDecorDisplayFrame(dw, dh, rotation,
+ wmDisplayCutout);
+ dm.noncompatWidthPixels = nonDecorSize.width();
+ dm.noncompatHeightPixels = nonDecorSize.height();
float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
if (curSize == 0 || size < curSize) {
@@ -2381,7 +2444,7 @@
}
private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
- int uiMode, int dw, int dh, float density, Configuration outConfig) {
+ int dw, int dh, float density, Configuration outConfig) {
// We need to determine the smallest width that will occur under normal
// operation. To this, start with the base screen size and compute the
@@ -2399,37 +2462,34 @@
displayInfo.smallestNominalAppHeight = 1<<30;
displayInfo.largestNominalAppWidth = 0;
displayInfo.largestNominalAppHeight = 0;
- adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, uiMode, unrotDw, unrotDh);
- adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw);
- adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh);
- adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw);
+ adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
+ adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
+ adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
+ adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
if (outConfig == null) {
return;
}
int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
- sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode);
- sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode);
- sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode);
- sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
outConfig.smallestScreenWidthDp =
(int) (displayInfo.smallestNominalAppWidth / density + 0.5f);
outConfig.screenLayout = sl;
}
- private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh,
- int uiMode) {
+ private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh) {
// Get the display cutout at this rotation.
- final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
- rotation).getDisplayCutout();
+ final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(rotation);
// Get the app screen size at this rotation.
- int w = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayCutout);
- int h = mDisplayPolicy.getNonDecorDisplayHeight(dh, rotation, displayCutout);
+ final Rect size = mDisplayPolicy.getNonDecorDisplayFrame(dw, dh, rotation, wmDisplayCutout);
// Compute the screen layout size class for this rotation.
- int longSize = w;
- int shortSize = h;
+ int longSize = size.width();
+ int shortSize = size.height();
if (longSize < shortSize) {
int tmp = longSize;
longSize = shortSize;
@@ -2440,25 +2500,20 @@
return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
}
- private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation,
- int uiMode, int dw, int dh) {
- final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
- rotation).getDisplayCutout();
- final int width = mDisplayPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode,
- displayCutout);
- if (width < displayInfo.smallestNominalAppWidth) {
- displayInfo.smallestNominalAppWidth = width;
+ private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
+ final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(rotation);
+ final Point size = mDisplayPolicy.getConfigDisplaySize(dw, dh, rotation, wmDisplayCutout);
+ if (size.x < displayInfo.smallestNominalAppWidth) {
+ displayInfo.smallestNominalAppWidth = size.x;
}
- if (width > displayInfo.largestNominalAppWidth) {
- displayInfo.largestNominalAppWidth = width;
+ if (size.x > displayInfo.largestNominalAppWidth) {
+ displayInfo.largestNominalAppWidth = size.x;
}
- final int height = mDisplayPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode,
- displayCutout);
- if (height < displayInfo.smallestNominalAppHeight) {
- displayInfo.smallestNominalAppHeight = height;
+ if (size.y < displayInfo.smallestNominalAppHeight) {
+ displayInfo.smallestNominalAppHeight = size.y;
}
- if (height > displayInfo.largestNominalAppHeight) {
- displayInfo.largestNominalAppHeight = height;
+ if (size.y > displayInfo.largestNominalAppHeight) {
+ displayInfo.largestNominalAppHeight = size.y;
}
}
@@ -3196,13 +3251,18 @@
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
mPointerEventDispatcher.dispose();
setRotationAnimation(null);
+ // Unlink death from remote to clear the reference from binder -> mRemoteInsetsDeath
+ // -> this DisplayContent.
+ setRemoteInsetsController(null);
mWmService.mAnimator.removeDisplayLocked(mDisplayId);
mOverlayLayer.release();
+ mWindowingLayer.release();
mInputMonitor.onDisplayRemoved();
mWmService.mDisplayNotificationController.dispatchDisplayRemoved(this);
mWmService.mAccessibilityController.onDisplayRemoved(mDisplayId);
mRootWindowContainer.mTaskSupervisor
.getKeyguardController().onDisplayRemoved(mDisplayId);
+ mWallpaperController.resetLargestDisplay(mDisplay);
} finally {
mDisplayReady = false;
}
@@ -3304,6 +3364,14 @@
mAsyncRotationController.keepAppearanceInPreviousRotation();
}
} else if (isRotationChanging()) {
+ if (displayChange != null) {
+ final boolean seamless = mDisplayRotation.shouldRotateSeamlessly(
+ displayChange.getStartRotation(), displayChange.getEndRotation(),
+ false /* forceUpdate */);
+ if (seamless) {
+ t.onSeamlessRotating(this);
+ }
+ }
mWmService.mLatencyTracker.onActionStart(ACTION_ROTATE_SCREEN);
controller.mTransitionMetricsReporter.associate(t,
startTime -> mWmService.mLatencyTracker.onActionEnd(ACTION_ROTATE_SCREEN));
@@ -3452,6 +3520,16 @@
}
pw.println();
+ pw.print(prefix + "mHoldScreenWindow="); pw.print(mHoldScreenWindow);
+ pw.println();
+ pw.print(prefix + "mObscuringWindow="); pw.print(mObscuringWindow);
+ pw.println();
+ pw.print(prefix + "mLastWakeLockHoldingWindow="); pw.print(mLastWakeLockHoldingWindow);
+ pw.println();
+ pw.print(prefix + "mLastWakeLockObscuringWindow=");
+ pw.println(mLastWakeLockObscuringWindow);
+
+ pw.println();
mWallpaperController.dump(pw, " ");
if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() > 0) {
@@ -4400,13 +4478,20 @@
*/
@VisibleForTesting
InsetsControlTarget computeImeControlTarget() {
+ if (mImeInputTarget == null) {
+ // A special case that if there is no IME input target while the IME is being killed,
+ // in case seeing unexpected IME surface visibility change when delivering the IME leash
+ // to the remote insets target during the IME restarting, but the focus window is not in
+ // multi-windowing mode, return null target until the next input target updated.
+ return null;
+ }
+
+ final WindowState imeInputTarget = mImeInputTarget.getWindowState();
if (!isImeControlledByApp() && mRemoteInsetsControlTarget != null
- || (mImeInputTarget != null
- && getImeHostOrFallback(mImeInputTarget.getWindowState())
- == mRemoteInsetsControlTarget)) {
+ || getImeHostOrFallback(imeInputTarget) == mRemoteInsetsControlTarget) {
return mRemoteInsetsControlTarget;
} else {
- return mImeInputTarget != null ? mImeInputTarget.getWindowState() : null;
+ return imeInputTarget;
}
}
@@ -4665,6 +4750,8 @@
void applySurfaceChangesTransaction() {
final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
+ beginHoldScreenUpdate();
+
mTmpUpdateAllDrawn.clear();
if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
@@ -4740,6 +4827,8 @@
// can now be shown.
activity.updateAllDrawn();
}
+
+ finishHoldScreenUpdate();
}
private void getBounds(Rect out, @Rotation int rotation) {
@@ -5766,6 +5855,8 @@
updateRecording();
}
}
+ // Notify wallpaper controller of any size changes.
+ mWallpaperController.resetLargestDisplay(mDisplay);
// Dispatch pending Configuration to WindowContext if the associated display changes to
// un-suspended state from suspended.
if (isSuspendedState(lastDisplayState)
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 1a34c93..713c13e 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -19,15 +19,19 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.view.Display.TYPE_INTERNAL;
+import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES;
import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
+import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.ITYPE_RIGHT_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsState.ITYPE_TOP_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
@@ -103,6 +107,7 @@
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.PixelFormat;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.gui.DropInputMode;
@@ -127,6 +132,8 @@
import android.view.InsetsState;
import android.view.InsetsState.InternalInsetsType;
import android.view.InsetsVisibilities;
+import android.view.PrivacyIndicatorBounds;
+import android.view.RoundedCorners;
import android.view.Surface;
import android.view.View;
import android.view.ViewDebug;
@@ -136,7 +143,6 @@
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
-import android.view.WindowManagerPolicyConstants;
import android.view.accessibility.AccessibilityManager;
import android.window.ClientWindowFrames;
@@ -160,6 +166,7 @@
import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wallpaper.WallpaperManagerInternal;
+import com.android.server.wm.utils.WmDisplayCutout;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -355,6 +362,7 @@
private WindowState mTopFullscreenOpaqueWindowState;
private boolean mTopIsFullscreen;
private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
+ private boolean mForceConsumeSystemBars;
private boolean mForceShowSystemBars;
private boolean mShowingDream;
@@ -383,6 +391,16 @@
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
+ // TODO (b/235842600): Use public type once we can treat task bar as navigation bar.
+ private static final int[] STABLE_TYPES = new int[]{
+ ITYPE_TOP_DISPLAY_CUTOUT, ITYPE_RIGHT_DISPLAY_CUTOUT, ITYPE_BOTTOM_DISPLAY_CUTOUT,
+ ITYPE_LEFT_DISPLAY_CUTOUT, ITYPE_NAVIGATION_BAR, ITYPE_STATUS_BAR, ITYPE_CLIMATE_BAR
+ };
+ private static final int[] NON_DECOR_TYPES = new int[]{
+ ITYPE_TOP_DISPLAY_CUTOUT, ITYPE_RIGHT_DISPLAY_CUTOUT, ITYPE_BOTTOM_DISPLAY_CUTOUT,
+ ITYPE_LEFT_DISPLAY_CUTOUT, ITYPE_NAVIGATION_BAR
+ };
+
private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
private final WindowManagerInternal.AppTransitionListener mAppTransitionListener;
@@ -1545,6 +1563,13 @@
}
/**
+ * @return true if the system bars are forced to be consumed
+ */
+ public boolean areSystemBarsForcedConsumedLw() {
+ return mForceConsumeSystemBars;
+ }
+
+ /**
* @return true if the system bars are forced to stay visible
*/
public boolean areSystemBarsForcedShownLw() {
@@ -2007,35 +2032,6 @@
return mUiContext;
}
- private int getNavigationBarWidth(int rotation, int uiMode, int position) {
- if (mNavigationBar == null) {
- return 0;
- }
- LayoutParams lp = mNavigationBar.mAttrs;
- if (lp.paramsForRotation != null
- && lp.paramsForRotation.length == 4
- && lp.paramsForRotation[rotation] != null) {
- lp = lp.paramsForRotation[rotation];
- }
- Insets providedInsetsSize = null;
- if (lp.providedInsets != null) {
- for (InsetsFrameProvider provider : lp.providedInsets) {
- if (provider.type != ITYPE_NAVIGATION_BAR) {
- continue;
- }
- providedInsetsSize = provider.insetsSize;
- }
- }
- if (providedInsetsSize != null) {
- if (position == NAV_BAR_LEFT) {
- return providedInsetsSize.left;
- } else if (position == NAV_BAR_RIGHT) {
- return providedInsetsSize.right;
- }
- }
- return lp.width;
- }
-
@VisibleForTesting
void setCanSystemBarsBeShownByUser(boolean canBeShown) {
mCanSystemBarsBeShownByUser = canBeShown;
@@ -2057,45 +2053,24 @@
}
/**
- * Return the display width available after excluding any screen
- * decorations that could never be removed in Honeycomb. That is, system bar or
- * button bar.
+ * Return the display frame available after excluding any screen decorations that could never be
+ * removed in Honeycomb. That is, system bar or button bar.
+ *
+ * @return display frame excluding all non-decor insets.
*/
- public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
- DisplayCutout displayCutout) {
- int width = fullWidth;
- if (hasNavigationBar()) {
- final int navBarPosition = navigationBarPosition(rotation);
- if (navBarPosition == NAV_BAR_LEFT || navBarPosition == NAV_BAR_RIGHT) {
- width -= getNavigationBarWidth(rotation, uiMode, navBarPosition);
- }
- }
- if (displayCutout != null) {
- width -= displayCutout.getSafeInsetLeft() + displayCutout.getSafeInsetRight();
- }
- return width;
+ Rect getNonDecorDisplayFrame(int fullWidth, int fullHeight, int rotation,
+ WmDisplayCutout cutout) {
+ final DisplayFrames displayFrames =
+ getSimulatedDisplayFrames(rotation, fullWidth, fullHeight, cutout);
+ return getNonDecorDisplayFrameWithSimulatedFrame(displayFrames);
}
- @VisibleForTesting
- int getNavigationBarHeight(int rotation) {
- if (mNavigationBar == null) {
- return 0;
- }
- LayoutParams lp = mNavigationBar.mAttrs.forRotation(rotation);
- Insets providedInsetsSize = null;
- if (lp.providedInsets != null) {
- for (InsetsFrameProvider provider : lp.providedInsets) {
- if (provider.type != ITYPE_NAVIGATION_BAR) {
- continue;
- }
- providedInsetsSize = provider.insetsSize;
- if (providedInsetsSize != null) {
- return providedInsetsSize.bottom;
- }
- break;
- }
- }
- return lp.height;
+ Rect getNonDecorDisplayFrameWithSimulatedFrame(DisplayFrames displayFrames) {
+ final Rect nonDecorInsets =
+ getInsetsWithInternalTypes(displayFrames, NON_DECOR_TYPES).toRect();
+ final Rect displayFrame = new Rect(displayFrames.mInsetsState.getDisplayFrame());
+ displayFrame.inset(nonDecorInsets);
+ return displayFrame;
}
/**
@@ -2117,53 +2092,23 @@
}
/**
- * Return the display height available after excluding any screen
- * decorations that could never be removed in Honeycomb. That is, system bar or
- * button bar.
- */
- public int getNonDecorDisplayHeight(int fullHeight, int rotation, DisplayCutout displayCutout) {
- int height = fullHeight;
- final int navBarPosition = navigationBarPosition(rotation);
- if (navBarPosition == NAV_BAR_BOTTOM) {
- height -= getNavigationBarHeight(rotation);
- }
- if (displayCutout != null) {
- height -= displayCutout.getSafeInsetTop() + displayCutout.getSafeInsetBottom();
- }
- return height;
- }
-
- /**
- * Return the available screen width that we should report for the
+ * Return the available screen size that we should report for the
* configuration. This must be no larger than
- * {@link #getNonDecorDisplayWidth(int, int, int, int, DisplayCutout)}; it may be smaller
+ * {@link #getNonDecorDisplayFrame(int, int, int, DisplayCutout)}; it may be smaller
* than that to account for more transient decoration like a status bar.
*/
- public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
- DisplayCutout displayCutout) {
- return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayCutout);
+ public Point getConfigDisplaySize(int fullWidth, int fullHeight, int rotation,
+ WmDisplayCutout wmDisplayCutout) {
+ final DisplayFrames displayFrames = getSimulatedDisplayFrames(rotation, fullWidth,
+ fullHeight, wmDisplayCutout);
+ return getConfigDisplaySizeWithSimulatedFrame(displayFrames);
}
- /**
- * Return the available screen height that we should report for the
- * configuration. This must be no larger than
- * {@link #getNonDecorDisplayHeight(int, int, DisplayCutout)}; it may be smaller
- * than that to account for more transient decoration like a status bar.
- */
- public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
- DisplayCutout displayCutout) {
- // There is a separate status bar at the top of the display. We don't count that as part
- // of the fixed decor, since it can hide; however, for purposes of configurations,
- // we do want to exclude it since applications can't generally use that part
- // of the screen.
- int statusBarHeight = mStatusBarHeightForRotation[rotation];
- if (displayCutout != null) {
- // If there is a cutout, it may already have accounted for some part of the status
- // bar height.
- statusBarHeight = Math.max(0, statusBarHeight - displayCutout.getSafeInsetTop());
- }
- return getNonDecorDisplayHeight(fullHeight, rotation, displayCutout)
- - statusBarHeight;
+ Point getConfigDisplaySizeWithSimulatedFrame(DisplayFrames displayFrames) {
+ final Insets insets = getInsetsWithInternalTypes(displayFrames, STABLE_TYPES);
+ Rect configFrame = new Rect(displayFrames.mInsetsState.getDisplayFrame());
+ configFrame.inset(insets);
+ return new Point(configFrame.width(), configFrame.height());
}
/**
@@ -2195,48 +2140,75 @@
* Calculates the stable insets without running a layout.
*
* @param displayRotation the current display rotation
+ * @param displayWidth full display width
+ * @param displayHeight full display height
* @param displayCutout the current display cutout
* @param outInsets the insets to return
*/
- public void getStableInsetsLw(int displayRotation, DisplayCutout displayCutout,
- Rect outInsets) {
- outInsets.setEmpty();
+ public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
+ WmDisplayCutout displayCutout, Rect outInsets) {
+ final DisplayFrames displayFrames = getSimulatedDisplayFrames(displayRotation,
+ displayWidth, displayHeight, displayCutout);
+ getStableInsetsWithSimulatedFrame(displayFrames, outInsets);
+ }
- // Navigation bar and status bar.
- getNonDecorInsetsLw(displayRotation, displayCutout, outInsets);
- convertNonDecorInsetsToStableInsets(outInsets, displayRotation);
+ void getStableInsetsWithSimulatedFrame(DisplayFrames displayFrames, Rect outInsets) {
+ // Navigation bar, status bar, and cutout.
+ outInsets.set(getInsetsWithInternalTypes(displayFrames, STABLE_TYPES).toRect());
}
/**
* Calculates the insets for the areas that could never be removed in Honeycomb, i.e. system
- * bar or button bar. See {@link #getNonDecorDisplayWidth}.
- * @param displayRotation the current display rotation
- * @param displayCutout the current display cutout
+ * bar or button bar. See {@link #getNonDecorDisplayFrame}.
+ *
+ * @param displayRotation the current display rotation
+ * @param fullWidth the width of the display, including all insets
+ * @param fullHeight the height of the display, including all insets
+ * @param cutout the current display cutout
* @param outInsets the insets to return
*/
- public void getNonDecorInsetsLw(int displayRotation, DisplayCutout displayCutout,
- Rect outInsets) {
- outInsets.setEmpty();
+ public void getNonDecorInsetsLw(int displayRotation, int fullWidth, int fullHeight,
+ WmDisplayCutout cutout, Rect outInsets) {
+ final DisplayFrames displayFrames =
+ getSimulatedDisplayFrames(displayRotation, fullWidth, fullHeight, cutout);
+ getNonDecorInsetsWithSimulatedFrame(displayFrames, outInsets);
+ }
- // Only navigation bar
- if (hasNavigationBar()) {
- final int uiMode = mService.mPolicy.getUiMode();
- int position = navigationBarPosition(displayRotation);
- if (position == NAV_BAR_BOTTOM) {
- outInsets.bottom = getNavigationBarHeight(displayRotation);
- } else if (position == NAV_BAR_RIGHT) {
- outInsets.right = getNavigationBarWidth(displayRotation, uiMode, position);
- } else if (position == NAV_BAR_LEFT) {
- outInsets.left = getNavigationBarWidth(displayRotation, uiMode, position);
- }
- }
+ void getNonDecorInsetsWithSimulatedFrame(DisplayFrames displayFrames, Rect outInsets) {
+ outInsets.set(getInsetsWithInternalTypes(displayFrames, NON_DECOR_TYPES).toRect());
+ }
- if (displayCutout != null) {
- outInsets.left += displayCutout.getSafeInsetLeft();
- outInsets.top += displayCutout.getSafeInsetTop();
- outInsets.right += displayCutout.getSafeInsetRight();
- outInsets.bottom += displayCutout.getSafeInsetBottom();
- }
+ DisplayFrames getSimulatedDisplayFrames(int displayRotation, int fullWidth,
+ int fullHeight, WmDisplayCutout cutout) {
+ final DisplayInfo info = new DisplayInfo(mDisplayContent.getDisplayInfo());
+ info.rotation = displayRotation;
+ info.logicalWidth = fullWidth;
+ info.logicalHeight = fullHeight;
+ info.displayCutout = cutout.getDisplayCutout();
+ final RoundedCorners roundedCorners =
+ mDisplayContent.calculateRoundedCornersForRotation(displayRotation);
+ final PrivacyIndicatorBounds indicatorBounds =
+ mDisplayContent.calculatePrivacyIndicatorBoundsForRotation(displayRotation);
+ final DisplayFrames displayFrames = new DisplayFrames(getDisplayId(), new InsetsState(),
+ info, cutout, roundedCorners, indicatorBounds);
+ simulateLayoutDisplay(displayFrames);
+ return displayFrames;
+ }
+
+ @VisibleForTesting
+ Insets getInsets(DisplayFrames displayFrames, @InsetsType int type) {
+ final InsetsState state = displayFrames.mInsetsState;
+ final Insets insets = state.calculateInsets(state.getDisplayFrame(), type,
+ true /* ignoreVisibility */);
+ return insets;
+ }
+
+ Insets getInsetsWithInternalTypes(DisplayFrames displayFrames,
+ @InternalInsetsType int[] types) {
+ final InsetsState state = displayFrames.mInsetsState;
+ final Insets insets = state.calculateInsetsWithInternalTypes(state.getDisplayFrame(), types,
+ true /* ignoreVisibility */);
+ return insets;
}
@NavigationBarPosition
@@ -2256,17 +2228,6 @@
}
/**
- * @return The side of the screen where navigation bar is positioned.
- * @see WindowManagerPolicyConstants#NAV_BAR_LEFT
- * @see WindowManagerPolicyConstants#NAV_BAR_RIGHT
- * @see WindowManagerPolicyConstants#NAV_BAR_BOTTOM
- */
- @NavigationBarPosition
- public int getNavBarPosition() {
- return mNavigationBarPosition;
- }
-
- /**
* A new window has been focused.
*/
public void focusChangedLw(WindowState lastFocus, WindowState newFocus) {
@@ -2510,6 +2471,10 @@
// We need to force showing system bars when the multi-window or freeform root task is
// visible.
mForceShowSystemBars = multiWindowTaskVisible || freeformRootTaskVisible;
+ // We need to force the consumption of the system bars if they are force shown or if they
+ // are controlled by a remote insets controller.
+ mForceConsumeSystemBars = mForceShowSystemBars
+ || mDisplayContent.getInsetsPolicy().remoteInsetsControllerControlsSystemBars(win);
mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);
final boolean topAppHidesStatusBar = topAppHidesStatusBar();
diff --git a/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java b/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java
index 3f6fb622..e3a2065 100644
--- a/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java
+++ b/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java
@@ -22,6 +22,8 @@
import android.util.SparseArray;
import android.view.DisplayInfo;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
/**
@@ -52,19 +54,21 @@
/**
- * Returns, for the given displayId, a set of display infos. Set contains each supported device
- * state.
+ * Returns, for the given displayId, a list of unique display infos. List contains each
+ * supported device state.
+ * <p>List contents are guaranteed to be unique, but returned as a list rather than a set to
+ * minimize copies needed to make an iteraable data structure.
*/
- public Set<DisplayInfo> getPossibleDisplayInfos(int displayId) {
+ public List<DisplayInfo> getPossibleDisplayInfos(int displayId) {
// Update display infos before returning, since any cached values would have been removed
// in response to any display event. This model avoids re-computing the cache for every
// display change event (which occurs extremely frequently in the normal usage of the
// device).
updatePossibleDisplayInfos(displayId);
if (!mDisplayInfos.contains(displayId)) {
- return new ArraySet<>();
+ return new ArrayList<>();
}
- return Set.copyOf(mDisplayInfos.get(displayId));
+ return List.copyOf(mDisplayInfos.get(displayId));
}
/**
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b79c6f4..7f22242 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -28,7 +28,6 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
@@ -178,15 +177,9 @@
private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
private Object mLastWindowFreezeSource = null;
- private Session mHoldScreen = null;
private float mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
private long mUserActivityTimeout = -1;
private boolean mUpdateRotation = false;
- // Following variables are for debugging screen wakelock only.
- // Last window that requires screen wakelock
- WindowState mHoldScreenWindow = null;
- // Last window that obscures all windows below
- WindowState mObscuringWindow = null;
// Only set while traversing the default display based on its content.
// Affects the behavior of mirroring on secondary displays.
private boolean mObscureApplicationContentOnSecondaryDisplays = false;
@@ -803,7 +796,6 @@
UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
}
- mHoldScreen = null;
mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mUserActivityTimeout = -1;
mObscureApplicationContentOnSecondaryDisplays = false;
@@ -847,6 +839,10 @@
if (recentsAnimationController != null) {
recentsAnimationController.checkAnimationReady(defaultDisplay.mWallpaperController);
}
+ final BackNaviAnimationController bnac = mWmService.getBackNaviAnimationController();
+ if (bnac != null) {
+ bnac.checkAnimationReady(defaultDisplay.mWallpaperController);
+ }
for (int displayNdx = 0; displayNdx < mChildren.size(); ++displayNdx) {
final DisplayContent displayContent = mChildren.get(displayNdx);
@@ -916,7 +912,6 @@
}
}
- mWmService.setHoldScreenLocked(mHoldScreen);
if (!mWmService.mDisplayFrozen) {
final float brightnessOverride = mScreenBrightnessOverride < PowerManager.BRIGHTNESS_MIN
|| mScreenBrightnessOverride > PowerManager.BRIGHTNESS_MAX
@@ -996,9 +991,6 @@
}
private void applySurfaceChangesTransaction() {
- mHoldScreenWindow = null;
- mObscuringWindow = null;
-
// TODO(multi-display): Support these features on secondary screens.
final DisplayContent defaultDc = mDefaultDisplay;
final DisplayInfo defaultInfo = defaultDc.getDisplayInfo();
@@ -1073,15 +1065,6 @@
}
}
if (w.mHasSurface && canBeSeen) {
- if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {
- mHoldScreen = w.mSession;
- mHoldScreenWindow = w;
- } else if (w == mWmService.mLastWakeLockHoldingWindow) {
- ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON,
- "handleNotObscuredLocked: %s was holding screen wakelock but no longer "
- + "has FLAG_KEEP_SCREEN_ON!!! called by%s",
- w, Debug.getCallers(10));
- }
if (!syswin && w.mAttrs.screenBrightness >= 0
&& Float.isNaN(mScreenBrightnessOverride)) {
mScreenBrightnessOverride = w.mAttrs.screenBrightness;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c44ae09..9186eb2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -60,10 +60,7 @@
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -1433,6 +1430,13 @@
final TaskFragment childTaskFrag = child.asTaskFragment();
if (childTaskFrag != null && childTaskFrag.asTask() == null) {
childTaskFrag.setMinDimensions(mMinWidth, mMinHeight);
+
+ // The starting window should keep covering its task when a pure TaskFragment is added
+ // because its bounds may not fill the task.
+ final ActivityRecord top = getTopMostActivity();
+ if (top != null) {
+ top.associateStartingWindowWithTaskIfNeeded();
+ }
}
}
@@ -1890,8 +1894,7 @@
}
final int newWinMode = getWindowingMode();
- if ((prevWinMode != newWinMode) && (mDisplayContent != null)
- && shouldStartChangeTransition(prevWinMode, newWinMode)) {
+ if (shouldStartChangeTransition(prevWinMode, mTmpPrevBounds)) {
initializeChangeTransition(mTmpPrevBounds);
}
@@ -2142,10 +2145,16 @@
bounds.offset(horizontalDiff, verticalDiff);
}
- private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
+ private boolean shouldStartChangeTransition(int prevWinMode, @NonNull Rect prevBounds) {
if (!isLeafTask() || !canStartChangeTransition()) {
return false;
}
+ final int newWinMode = getWindowingMode();
+ if (mTransitionController.inTransition(this)) {
+ final Rect newBounds = getConfiguration().windowConfiguration.getBounds();
+ return prevWinMode != newWinMode || prevBounds.width() != newBounds.width()
+ || prevBounds.height() != newBounds.height();
+ }
// Only do an animation into and out-of freeform mode for now. Other mode
// transition animations are currently handled by system-ui.
return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
@@ -4968,23 +4977,17 @@
dc.prepareAppTransition(TRANSIT_NONE);
mTaskSupervisor.mNoAnimActivities.add(r);
} else {
- int transit = TRANSIT_OLD_ACTIVITY_OPEN;
- if (newTask) {
- if (r.mLaunchTaskBehind) {
- transit = TRANSIT_OLD_TASK_OPEN_BEHIND;
- } else {
- // If a new task is being launched, then mark the existing top activity as
- // supporting picture-in-picture while pausing only if the starting activity
- // would not be considered an overlay on top of the current activity
- // (eg. not fullscreen, or the assistant)
- enableEnterPipOnTaskSwitch(pipCandidate,
- null /* toFrontTask */, r, options);
- transit = TRANSIT_OLD_TASK_OPEN;
- }
- }
dc.prepareAppTransition(TRANSIT_OPEN);
mTaskSupervisor.mNoAnimActivities.remove(r);
}
+ if (newTask && !r.mLaunchTaskBehind) {
+ // If a new task is being launched, then mark the existing top activity as
+ // supporting picture-in-picture while pausing only if the starting activity
+ // would not be considered an overlay on top of the current activity
+ // (eg. not fullscreen, or the assistant)
+ enableEnterPipOnTaskSwitch(pipCandidate,
+ null /* toFrontTask */, r, options);
+ }
boolean doShow = true;
if (newTask) {
// Even though this activity is starting fresh, we still need
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 679a231..da731e8 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -98,6 +98,7 @@
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.am.HostingRecord;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.wm.utils.WmDisplayCutout;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -2208,11 +2209,13 @@
mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
final DisplayPolicy policy = rootTask.mDisplayContent.getDisplayPolicy();
- policy.getNonDecorInsetsLw(displayInfo.rotation,
- displayInfo.displayCutout, mTmpInsets);
+ final WmDisplayCutout cutout =
+ rootTask.mDisplayContent.calculateDisplayCutoutForRotation(displayInfo.rotation);
+ final DisplayFrames displayFrames = policy.getSimulatedDisplayFrames(displayInfo.rotation,
+ displayInfo.logicalWidth, displayInfo.logicalHeight, cutout);
+ policy.getNonDecorInsetsWithSimulatedFrame(displayFrames, mTmpInsets);
intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, mTmpInsets);
-
- policy.convertNonDecorInsetsToStableInsets(mTmpInsets, displayInfo.rotation);
+ policy.getStableInsetsWithSimulatedFrame(displayFrames, mTmpInsets);
intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
}
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index d615583..8c037a7 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -45,6 +45,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.view.RemoteAnimationDefinition;
+import android.view.WindowManager;
import android.window.ITaskFragmentOrganizer;
import android.window.ITaskFragmentOrganizerController;
import android.window.TaskFragmentInfo;
@@ -138,12 +139,12 @@
new SparseArray<>();
/**
- * List of {@link TaskFragmentTransaction#getTransactionToken()} that have been sent to the
- * organizer. If the transaction is sent during a transition, the
- * {@link TransitionController} will wait until the transaction is finished.
+ * Map from {@link TaskFragmentTransaction#getTransactionToken()} to the
+ * {@link Transition#getSyncId()} that has been deferred. {@link TransitionController} will
+ * wait until the organizer finished handling the {@link TaskFragmentTransaction}.
* @see #onTransactionFinished(IBinder)
*/
- private final List<IBinder> mRunningTransactions = new ArrayList<>();
+ private final ArrayMap<IBinder, Integer> mDeferredTransitions = new ArrayMap<>();
TaskFragmentOrganizerState(ITaskFragmentOrganizer organizer, int pid, int uid) {
mOrganizer = organizer;
@@ -190,9 +191,9 @@
taskFragment.removeImmediately();
mOrganizedTaskFragments.remove(taskFragment);
}
- for (int i = mRunningTransactions.size() - 1; i >= 0; i--) {
+ for (int i = mDeferredTransitions.size() - 1; i >= 0; i--) {
// Cleanup any running transaction to unblock the current transition.
- onTransactionFinished(mRunningTransactions.get(i));
+ onTransactionFinished(mDeferredTransitions.keyAt(i));
}
mOrganizer.asBinder().unlinkToDeath(this, 0 /*flags*/);
}
@@ -357,19 +358,34 @@
if (!mWindowOrganizerController.getTransitionController().isCollecting()) {
return;
}
+ final int transitionId = mWindowOrganizerController.getTransitionController()
+ .getCollectingTransitionId();
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
- "Defer transition ready for TaskFragmentTransaction=%s", transactionToken);
- mRunningTransactions.add(transactionToken);
+ "Defer transition id=%d for TaskFragmentTransaction=%s", transitionId,
+ transactionToken);
+ mDeferredTransitions.put(transactionToken, transitionId);
mWindowOrganizerController.getTransitionController().deferTransitionReady();
}
/** Called when the transaction is finished. */
void onTransactionFinished(@NonNull IBinder transactionToken) {
- if (!mRunningTransactions.remove(transactionToken)) {
+ if (!mDeferredTransitions.containsKey(transactionToken)) {
+ return;
+ }
+ final int transitionId = mDeferredTransitions.remove(transactionToken);
+ if (!mWindowOrganizerController.getTransitionController().isCollecting()
+ || mWindowOrganizerController.getTransitionController()
+ .getCollectingTransitionId() != transitionId) {
+ // This can happen when the transition is timeout or abort.
+ ProtoLog.w(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
+ "Deferred transition id=%d has been continued before the"
+ + " TaskFragmentTransaction=%s is finished",
+ transitionId, transactionToken);
return;
}
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
- "Continue transition ready for TaskFragmentTransaction=%s", transactionToken);
+ "Continue transition id=%d for TaskFragmentTransaction=%s", transitionId,
+ transactionToken);
mWindowOrganizerController.getTransitionController().continueTransitionReady();
}
}
@@ -469,16 +485,31 @@
}
@Override
- public void onTransactionHandled(@NonNull ITaskFragmentOrganizer organizer,
- @NonNull IBinder transactionToken, @NonNull WindowContainerTransaction wct) {
+ public void onTransactionHandled(@NonNull IBinder transactionToken,
+ @NonNull WindowContainerTransaction wct,
+ @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) {
+ // Keep the calling identity to avoid unsecure change.
synchronized (mGlobalLock) {
- // Keep the calling identity to avoid unsecure change.
- mWindowOrganizerController.applyTransaction(wct);
- final TaskFragmentOrganizerState state = validateAndGetState(organizer);
+ applyTransaction(wct, transitionType, shouldApplyIndependently);
+ final TaskFragmentOrganizerState state = validateAndGetState(
+ wct.getTaskFragmentOrganizer());
state.onTransactionFinished(transactionToken);
}
}
+ @Override
+ public void applyTransaction(@NonNull WindowContainerTransaction wct,
+ @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) {
+ // Keep the calling identity to avoid unsecure change.
+ synchronized (mGlobalLock) {
+ if (wct.isEmpty()) {
+ return;
+ }
+ mWindowOrganizerController.applyTaskFragmentTransactionLocked(wct, transitionType,
+ shouldApplyIndependently);
+ }
+ }
+
/**
* Gets the {@link RemoteAnimationDefinition} set on the given organizer if exists. Returns
* {@code null} if it doesn't, or if the organizer has activity(ies) embedded in untrusted mode.
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 2d3e437..8e389d3 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
@@ -68,6 +69,7 @@
import android.content.pm.ActivityInfo;
import android.graphics.Point;
import android.graphics.Rect;
+import android.hardware.HardwareBuffer;
import android.os.Binder;
import android.os.IBinder;
import android.os.IRemoteCallback;
@@ -205,6 +207,9 @@
/** @see #setCanPipOnFinish */
private boolean mCanPipOnFinish = true;
+ private boolean mIsSeamlessRotation = false;
+ private IContainerFreezer mContainerFreezer = null;
+
Transition(@TransitionType int type, @TransitionFlags int flags,
TransitionController controller, BLASTSyncEngine syncEngine) {
mType = type;
@@ -265,10 +270,31 @@
return mTargetDisplays.contains(dc);
}
+ /** Set a transition to be a seamless-rotation. */
void setSeamlessRotation(@NonNull WindowContainer wc) {
final ChangeInfo info = mChanges.get(wc);
if (info == null) return;
info.mFlags = info.mFlags | ChangeInfo.FLAG_SEAMLESS_ROTATION;
+ onSeamlessRotating(wc.getDisplayContent());
+ }
+
+ /**
+ * Called when it's been determined that this is transition is a seamless rotation. This should
+ * be called before any WM changes have happened.
+ */
+ void onSeamlessRotating(@NonNull DisplayContent dc) {
+ // Don't need to do anything special if everything is using BLAST sync already.
+ if (mSyncEngine.getSyncSet(mSyncId).mSyncMethod == BLASTSyncEngine.METHOD_BLAST) return;
+ if (mContainerFreezer == null) {
+ mContainerFreezer = new ScreenshotFreezer();
+ }
+ mIsSeamlessRotation = true;
+ final WindowState top = dc.getDisplayPolicy().getTopFullscreenOpaqueWindow();
+ if (top != null) {
+ top.mSyncMethodOverride = BLASTSyncEngine.METHOD_BLAST;
+ ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Override sync-method for %s "
+ + "because seamless rotating", top.getName());
+ }
}
/**
@@ -285,6 +311,11 @@
}
}
+ /** Only for testing. */
+ void setContainerFreezer(IContainerFreezer freezer) {
+ mContainerFreezer = freezer;
+ }
+
@TransitionState
int getState() {
return mState;
@@ -314,13 +345,18 @@
return mState == STATE_COLLECTING || mState == STATE_STARTED;
}
- /** Starts collecting phase. Once this starts, all relevant surface operations are sync. */
+ @VisibleForTesting
void startCollecting(long timeoutMs) {
+ startCollecting(timeoutMs, TransitionController.SYNC_METHOD);
+ }
+
+ /** Starts collecting phase. Once this starts, all relevant surface operations are sync. */
+ void startCollecting(long timeoutMs, int method) {
if (mState != STATE_PENDING) {
throw new IllegalStateException("Attempting to re-use a transition");
}
mState = STATE_COLLECTING;
- mSyncId = mSyncEngine.startSyncSet(this, timeoutMs, TAG);
+ mSyncId = mSyncEngine.startSyncSet(this, timeoutMs, TAG, method);
mController.mTransitionTracer.logState(this);
}
@@ -415,6 +451,37 @@
}
/**
+ * Records that a particular container is changing visibly (ie. something about it is changing
+ * while it remains visible). This only effects windows that are already in the collecting
+ * transition.
+ */
+ void collectVisibleChange(WindowContainer wc) {
+ if (mSyncEngine.getSyncSet(mSyncId).mSyncMethod == BLASTSyncEngine.METHOD_BLAST) {
+ // All windows are synced already.
+ return;
+ }
+ if (!isInTransition(wc)) return;
+
+ if (mContainerFreezer == null) {
+ mContainerFreezer = new ScreenshotFreezer();
+ }
+ Transition.ChangeInfo change = mChanges.get(wc);
+ if (change == null || !change.mVisible || !wc.isVisibleRequested()) return;
+ // Note: many more tests have already been done by caller.
+ mContainerFreezer.freeze(wc, change.mAbsoluteBounds);
+ }
+
+ /**
+ * @return {@code true} if `wc` is a participant or is a descendant of one.
+ */
+ boolean isInTransition(WindowContainer wc) {
+ for (WindowContainer p = wc; p != null; p = p.getParent()) {
+ if (mParticipants.contains(p)) return true;
+ }
+ return false;
+ }
+
+ /**
* Specifies configuration change explicitly for the window container, so it can be chosen as
* transition target. This is usually used with transition mode
* {@link android.view.WindowManager#TRANSIT_CHANGE}.
@@ -531,6 +598,10 @@
displays.add(target.getDisplayContent());
}
}
+ // Remove screenshot layers if necessary
+ if (mContainerFreezer != null) {
+ mContainerFreezer.cleanUp(t);
+ }
// Need to update layers on involved displays since they were all paused while
// the animation played. This puts the layers back into the correct order.
mController.mBuildingFinishLayers = true;
@@ -817,6 +888,19 @@
transaction);
if (mOverrideOptions != null) {
info.setAnimationOptions(mOverrideOptions);
+ if (mOverrideOptions.getType() == ANIM_OPEN_CROSS_PROFILE_APPS) {
+ for (int i = 0; i < mTargets.size(); ++i) {
+ final TransitionInfo.Change c = info.getChanges().get(i);
+ final ActivityRecord ar = mTargets.get(i).asActivityRecord();
+ if (ar == null || c.getMode() != TRANSIT_OPEN) continue;
+ int flags = c.getFlags();
+ flags |= ar.mUserId == ar.mWmService.mCurrentUserId
+ ? TransitionInfo.FLAG_CROSS_PROFILE_OWNER_THUMBNAIL
+ : TransitionInfo.FLAG_CROSS_PROFILE_WORK_THUMBNAIL;
+ c.setFlags(flags);
+ break;
+ }
+ }
}
// TODO(b/188669821): Move to animation impl in shell.
@@ -1810,6 +1894,8 @@
*/
void deferTransitionReady() {
++mReadyTracker.mDeferReadyDepth;
+ // Make sure it wait until #continueTransitionReady() is called.
+ mSyncEngine.setReady(mSyncId, false);
}
/** This undoes one call to {@link #deferTransitionReady}. */
@@ -1982,4 +2068,111 @@
return sortedTargets;
}
}
+
+ /**
+ * Interface for freezing a container's content during sync preparation. Really just one impl
+ * but broken into an interface for testing (since you can't take screenshots in unit tests).
+ */
+ interface IContainerFreezer {
+ /**
+ * Makes sure a particular window is "frozen" for the remainder of a sync.
+ *
+ * @return whether the freeze was successful. It fails if `wc` is already in a frozen window
+ * or is not visible/ready.
+ */
+ boolean freeze(@NonNull WindowContainer wc, @NonNull Rect bounds);
+
+ /** Populates `t` with operations that clean-up any state created to set-up the freeze. */
+ void cleanUp(SurfaceControl.Transaction t);
+ }
+
+ /**
+ * Freezes container content by taking a screenshot. Because screenshots are heavy, usage of
+ * any container "freeze" is currently explicit. WM code needs to be prudent about which
+ * containers to freeze.
+ */
+ @VisibleForTesting
+ private class ScreenshotFreezer implements IContainerFreezer {
+ /** Values are the screenshot "surfaces" or null if it was frozen via BLAST override. */
+ private final ArrayMap<WindowContainer, SurfaceControl> mSnapshots = new ArrayMap<>();
+
+ /** Takes a screenshot and puts it at the top of the container's surface. */
+ @Override
+ public boolean freeze(@NonNull WindowContainer wc, @NonNull Rect bounds) {
+ if (!wc.isVisibleRequested()) return false;
+
+ // Check if any parents have already been "frozen". If so, `wc` is already part of that
+ // snapshot, so just skip it.
+ for (WindowContainer p = wc; p != null; p = p.getParent()) {
+ if (mSnapshots.containsKey(p)) return false;
+ }
+
+ if (mIsSeamlessRotation) {
+ WindowState top = wc.getDisplayContent() == null ? null
+ : wc.getDisplayContent().getDisplayPolicy().getTopFullscreenOpaqueWindow();
+ if (top != null && (top == wc || top.isDescendantOf(wc))) {
+ // Don't use screenshots for seamless windows: these will use BLAST even if not
+ // BLAST mode.
+ mSnapshots.put(wc, null);
+ return true;
+ }
+ }
+
+ ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Screenshotting %s [%s]",
+ wc.toString(), bounds.toString());
+
+ Rect cropBounds = new Rect(bounds);
+ cropBounds.offsetTo(0, 0);
+ SurfaceControl.LayerCaptureArgs captureArgs =
+ new SurfaceControl.LayerCaptureArgs.Builder(wc.getSurfaceControl())
+ .setSourceCrop(cropBounds)
+ .setCaptureSecureLayers(true)
+ .setAllowProtected(true)
+ .build();
+ SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
+ SurfaceControl.captureLayers(captureArgs);
+ final HardwareBuffer buffer = screenshotBuffer == null ? null
+ : screenshotBuffer.getHardwareBuffer();
+ if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) {
+ // This can happen when display is not ready.
+ Slog.w(TAG, "Failed to capture screenshot for " + wc);
+ return false;
+ }
+ SurfaceControl snapshotSurface = wc.makeAnimationLeash()
+ .setName("transition snapshot: " + wc.toString())
+ .setOpaque(true)
+ .setParent(wc.getSurfaceControl())
+ .setSecure(screenshotBuffer.containsSecureLayers())
+ .setCallsite("Transition.ScreenshotSync")
+ .setBLASTLayer()
+ .build();
+ mSnapshots.put(wc, snapshotSurface);
+ SurfaceControl.Transaction t = wc.mWmService.mTransactionFactory.get();
+
+ t.setBuffer(snapshotSurface, buffer);
+ t.setDataSpace(snapshotSurface, screenshotBuffer.getColorSpace().getDataSpace());
+ t.show(snapshotSurface);
+
+ // Place it on top of anything else in the container.
+ t.setLayer(snapshotSurface, Integer.MAX_VALUE);
+ t.apply();
+ t.close();
+
+ // Detach the screenshot on the sync transaction (the screenshot is just meant to
+ // freeze the window until the sync transaction is applied (with all its other
+ // corresponding changes), so this is how we unfreeze it.
+ wc.getSyncTransaction().reparent(snapshotSurface, null /* newParent */);
+ return true;
+ }
+
+ @Override
+ public void cleanUp(SurfaceControl.Transaction t) {
+ for (int i = 0; i < mSnapshots.size(); ++i) {
+ SurfaceControl snap = mSnapshots.valueAt(i);
+ // May be null if it was frozen via BLAST override.
+ if (snap == null) continue;
+ t.remove(snap);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 846aa3e..23928ae 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -46,6 +46,7 @@
import android.window.TransitionRequestInfo;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.ProtoLogGroup;
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.LocalServices;
@@ -64,6 +65,11 @@
private static final boolean SHELL_TRANSITIONS_ROTATION =
SystemProperties.getBoolean("persist.wm.debug.shell_transit_rotate", false);
+ /** Which sync method to use for transition syncs. */
+ static final int SYNC_METHOD =
+ android.os.SystemProperties.getBoolean("persist.wm.debug.shell_transit_blast", true)
+ ? BLASTSyncEngine.METHOD_BLAST : BLASTSyncEngine.METHOD_NONE;
+
/** The same as legacy APP_TRANSITION_TIMEOUT_MS. */
private static final int DEFAULT_TIMEOUT_MS = 5000;
/** Less duration for CHANGE type because it does not involve app startup. */
@@ -160,6 +166,12 @@
/** Starts Collecting */
void moveToCollecting(@NonNull Transition transition) {
+ moveToCollecting(transition, SYNC_METHOD);
+ }
+
+ /** Starts Collecting */
+ @VisibleForTesting
+ void moveToCollecting(@NonNull Transition transition, int method) {
if (mCollectingTransition != null) {
throw new IllegalStateException("Simultaneous transition collection not supported.");
}
@@ -167,7 +179,7 @@
// Distinguish change type because the response time is usually expected to be not too long.
final long timeoutMs =
transition.mType == TRANSIT_CHANGE ? CHANGE_TIMEOUT_MS : DEFAULT_TIMEOUT_MS;
- mCollectingTransition.startCollecting(timeoutMs);
+ mCollectingTransition.startCollecting(timeoutMs, method);
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Start collecting in Transition: %s",
mCollectingTransition);
dispatchLegacyAppTransitionPending();
@@ -215,6 +227,17 @@
}
/**
+ * @return the collecting transition sync Id. This should only be called when there is a
+ * collecting transition.
+ */
+ int getCollectingTransitionId() {
+ if (mCollectingTransition == null) {
+ throw new IllegalStateException("There is no collecting transition");
+ }
+ return mCollectingTransition.getSyncId();
+ }
+
+ /**
* @return {@code true} if transition is actively collecting changes and `wc` is one of them.
* This is {@code false} once a transition is playing.
*/
@@ -228,10 +251,7 @@
*/
boolean inCollectingTransition(@NonNull WindowContainer wc) {
if (!isCollecting()) return false;
- for (WindowContainer p = wc; p != null; p = p.getParent()) {
- if (mCollectingTransition.mParticipants.contains(p)) return true;
- }
- return false;
+ return mCollectingTransition.isInTransition(wc);
}
/**
@@ -247,9 +267,7 @@
*/
boolean inPlayingTransition(@NonNull WindowContainer wc) {
for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
- for (WindowContainer p = wc; p != null; p = p.getParent()) {
- if (mPlayingTransitions.get(i).mParticipants.contains(p)) return true;
- }
+ if (mPlayingTransitions.get(i).isInTransition(wc)) return true;
}
return false;
}
@@ -469,6 +487,7 @@
void collectForDisplayAreaChange(@NonNull DisplayArea<?> wc) {
final Transition transition = mCollectingTransition;
if (transition == null || !transition.mParticipants.contains(wc)) return;
+ transition.collectVisibleChange(wc);
// Collect all visible tasks.
wc.forAllLeafTasks(task -> {
if (task.isVisible()) {
@@ -488,6 +507,16 @@
}
}
+ /**
+ * Records that a particular container is changing visibly (ie. something about it is changing
+ * while it remains visible). This only effects windows that are already in the collecting
+ * transition.
+ */
+ void collectVisibleChange(WindowContainer wc) {
+ if (!isCollecting()) return;
+ mCollectingTransition.collectVisibleChange(wc);
+ }
+
/** @see Transition#mStatusBarTransitionDelay */
void setStatusBarTransitionDelay(long delay) {
if (mCollectingTransition == null) return;
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 6245005..908fdbd 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -19,6 +19,7 @@
import static android.app.WallpaperManager.COMMAND_FREEZE;
import static android.app.WallpaperManager.COMMAND_UNFREEZE;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -35,7 +36,9 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.WALLPAPER_DRAW_PENDING_TIMEOUT;
+import android.annotation.Nullable;
import android.graphics.Bitmap;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Debug;
@@ -45,6 +48,8 @@
import android.util.ArraySet;
import android.util.MathUtils;
import android.util.Slog;
+import android.view.Display;
+import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.animation.Animation;
@@ -56,6 +61,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
import java.util.function.Consumer;
/**
@@ -113,8 +119,12 @@
*/
private WindowState mTmpTopWallpaper;
+ @Nullable private Point mLargestDisplaySize = null;
+
private final FindWallpaperTargetResult mFindResults = new FindWallpaperTargetResult();
+ private boolean mShouldOffsetWallpaperCenter;
+
private final ToBooleanFunction<WindowState> mFindWallpaperTargetFunction = w -> {
if ((w.mAttrs.type == TYPE_WALLPAPER)) {
if (mFindResults.topWallpaper == null || mFindResults.resetTopWallpaper) {
@@ -186,7 +196,7 @@
&& animatingContainer.getAnimation() != null
&& animatingContainer.getAnimation().getShowWallpaper();
final boolean hasWallpaper = w.hasWallpaper() || animationWallpaper;
- if (isRecentsTransitionTarget(w)) {
+ if (isRecentsTransitionTarget(w) || isBackAnimationTarget(w)) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Found recents animation wallpaper target: " + w);
mFindResults.setWallpaperTarget(w);
return true;
@@ -226,6 +236,13 @@
return controller != null && controller.isWallpaperVisible(w);
}
+ private boolean isBackAnimationTarget(WindowState w) {
+ // The window is either the back activity or is in the task animating by the back gesture.
+ final BackNaviAnimationController bthController = mService.getBackNaviAnimationController();
+ return bthController != null && bthController.isWallpaperVisible(w);
+ }
+
+
/**
* @see #computeLastWallpaperZoomOut()
*/
@@ -241,6 +258,38 @@
mDisplayContent = displayContent;
mMaxWallpaperScale = service.mContext.getResources()
.getFloat(com.android.internal.R.dimen.config_wallpaperMaxScale);
+ mShouldOffsetWallpaperCenter = service.mContext.getResources()
+ .getBoolean(
+ com.android.internal.R.bool.config_offsetWallpaperToCenterOfLargestDisplay);
+ }
+
+ void resetLargestDisplay(Display display) {
+ if (display != null && display.getType() == Display.TYPE_INTERNAL) {
+ mLargestDisplaySize = null;
+ }
+ }
+
+ @VisibleForTesting void setShouldOffsetWallpaperCenter(boolean shouldOffset) {
+ mShouldOffsetWallpaperCenter = shouldOffset;
+ }
+
+ @Nullable private Point findLargestDisplaySize() {
+ if (!mShouldOffsetWallpaperCenter) {
+ return null;
+ }
+ Point largestDisplaySize = new Point();
+ List<DisplayInfo> possibleDisplayInfo =
+ mService.getPossibleDisplayInfoLocked(DEFAULT_DISPLAY);
+ for (int i = 0; i < possibleDisplayInfo.size(); i++) {
+ DisplayInfo displayInfo = possibleDisplayInfo.get(i);
+ if (displayInfo.type == Display.TYPE_INTERNAL
+ && Math.max(displayInfo.logicalWidth, displayInfo.logicalHeight)
+ > Math.max(largestDisplaySize.x, largestDisplaySize.y)) {
+ largestDisplaySize.set(displayInfo.logicalWidth,
+ displayInfo.logicalHeight);
+ }
+ }
+ return largestDisplaySize;
}
WindowState getWallpaperTarget() {
@@ -327,24 +376,44 @@
}
boolean updateWallpaperOffset(WindowState wallpaperWin, boolean sync) {
- final Rect bounds = wallpaperWin.getLastReportedBounds();
- final int dw = bounds.width();
- final int dh = bounds.height();
+ // Size of the display the wallpaper is rendered on.
+ final Rect lastWallpaperBounds = wallpaperWin.getLastReportedBounds();
+ // Full size of the wallpaper (usually larger than bounds above to parallax scroll when
+ // swiping through Launcher pages).
+ final Rect wallpaperFrame = wallpaperWin.getFrame();
- int xOffset = 0;
- int yOffset = 0;
+ int newXOffset = 0;
+ int newYOffset = 0;
boolean rawChanged = false;
// Set the default wallpaper x-offset to either edge of the screen (depending on RTL), to
// match the behavior of most Launchers
float defaultWallpaperX = wallpaperWin.isRtl() ? 1f : 0f;
+ // "Wallpaper X" is the previous x-offset of the wallpaper (in a 0 to 1 scale).
+ // The 0 to 1 scale is because the "length" varies depending on how many home screens you
+ // have, so 0 is the left of the first home screen, and 1 is the right of the last one (for
+ // LTR, and the opposite for RTL).
float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : defaultWallpaperX;
+ // "Wallpaper X step size" is how much of that 0-1 is one "page" of the home screen
+ // when scrolling.
float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
- int availw = wallpaperWin.getFrame().right - wallpaperWin.getFrame().left - dw;
+ // Difference between width of wallpaper image, and the last size of the wallpaper.
+ // This is the horizontal surplus from the prior configuration.
+ int availw = wallpaperFrame.width() - lastWallpaperBounds.width();
+
+ int displayOffset = getDisplayWidthOffset(availw, lastWallpaperBounds,
+ wallpaperWin.isRtl());
+ availw -= displayOffset;
int offset = availw > 0 ? -(int)(availw * wpx + .5f) : 0;
if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ // if device is LTR, then offset wallpaper to the left (the wallpaper is drawn
+ // always starting from the left of the screen).
offset += mLastWallpaperDisplayOffsetX;
+ } else if (!wallpaperWin.isRtl()) {
+ // In RTL the offset is calculated so that the wallpaper ends up right aligned (see
+ // offset above).
+ offset -= displayOffset;
}
- xOffset = offset;
+ newXOffset = offset;
if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
wallpaperWin.mWallpaperX = wpx;
@@ -354,12 +423,13 @@
float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
- int availh = wallpaperWin.getFrame().bottom - wallpaperWin.getFrame().top - dh;
+ int availh = wallpaperWin.getFrame().bottom - wallpaperWin.getFrame().top
+ - lastWallpaperBounds.height();
offset = availh > 0 ? -(int)(availh * wpy + .5f) : 0;
if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
offset += mLastWallpaperDisplayOffsetY;
}
- yOffset = offset;
+ newYOffset = offset;
if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
wallpaperWin.mWallpaperY = wpy;
@@ -372,7 +442,7 @@
rawChanged = true;
}
- boolean changed = wallpaperWin.setWallpaperOffset(xOffset, yOffset,
+ boolean changed = wallpaperWin.setWallpaperOffset(newXOffset, newYOffset,
wallpaperWin.mShouldScaleWallpaper
? zoomOutToScale(wallpaperWin.mWallpaperZoomOut) : 1);
@@ -419,6 +489,52 @@
return changed;
}
+ /**
+ * Get an extra offset if needed ({@link #mShouldOffsetWallpaperCenter} = true, typically on
+ * multiple display devices) so that the wallpaper in a smaller display ends up centered at the
+ * same position as in the largest display of the device.
+ *
+ * Note that the wallpaper has already been cropped when set by the user, so these calculations
+ * apply to the image size for the display the wallpaper was set for.
+ *
+ * @param availWidth width available for the wallpaper offset in the current display
+ * @param displayFrame size of the "display" (parent frame)
+ * @param isRtl whether we're in an RTL configuration
+ * @return an offset to apply to the width, or 0 if the current configuration doesn't require
+ * any adjustment (either @link #mShouldOffsetWallpaperCenter} is false or we're on the largest
+ * display).
+ */
+ private int getDisplayWidthOffset(int availWidth, Rect displayFrame, boolean isRtl) {
+ if (!mShouldOffsetWallpaperCenter) {
+ return 0;
+ }
+ if (mLargestDisplaySize == null) {
+ mLargestDisplaySize = findLargestDisplaySize();
+ }
+ if (mLargestDisplaySize == null) {
+ return 0;
+ }
+ // Page width is the width of a Launcher "page", for pagination when swiping right.
+ int pageWidth = displayFrame.width();
+ // Only need offset if the current size is different from the largest display, and we're
+ // in a portrait configuration
+ if (mLargestDisplaySize.x != pageWidth && displayFrame.width() < displayFrame.height()) {
+ // The wallpaper will be scaled to fit the height of the wallpaper, so if the height
+ // of the displays are different, we need to account for that scaling when calculating
+ // the offset to the center
+ float sizeRatio = (float) displayFrame.height() / mLargestDisplaySize.y;
+ // Scale the width of the largest display to match the scale of the wallpaper size in
+ // the current display
+ int adjustedLargestWidth = Math.round(mLargestDisplaySize.x * sizeRatio);
+ // Finally, find the difference between the centers, taking into account that the
+ // size of the wallpaper frame could be smaller than the screen
+ return isRtl
+ ? adjustedLargestWidth - (adjustedLargestWidth + pageWidth) / 2
+ : Math.min(adjustedLargestWidth - pageWidth, availWidth) / 2;
+ }
+ return 0;
+ }
+
void setWindowWallpaperPosition(
WindowState window, float x, float y, float xStep, float yStep) {
if (window.mWallpaperX != x || window.mWallpaperY != y) {
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 6ee30bb..8fdaec6 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -128,12 +128,15 @@
if (visible && wallpaperTarget != null) {
final RecentsAnimationController recentsAnimationController =
mWmService.getRecentsAnimationController();
+ final BackNaviAnimationController bac = mWmService.getBackNaviAnimationController();
if (recentsAnimationController != null
&& recentsAnimationController.isAnimatingTask(wallpaperTarget.getTask())) {
// If the Recents animation is running, and the wallpaper target is the animating
// task we want the wallpaper to be rotated in the same orientation as the
// RecentsAnimation's target (e.g the launcher)
recentsAnimationController.linkFixedRotationTransformIfNeeded(this);
+ } else if (bac != null && bac.isAnimatingTask(wallpaperTarget.getTask())) {
+ bac.linkFixedRotationTransformIfNeeded(this);
} else if ((wallpaperTarget.mActivityRecord == null
// Ignore invisible activity because it may be moving to background.
|| wallpaperTarget.mActivityRecord.mVisibleRequested)
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 7979048..92e52de 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -343,6 +343,7 @@
BLASTSyncEngine.SyncGroup mSyncGroup = null;
final SurfaceControl.Transaction mSyncTransaction;
@SyncState int mSyncState = SYNC_STATE_NONE;
+ int mSyncMethodOverride = BLASTSyncEngine.METHOD_UNDEFINED;
private final List<WindowContainerListener> mListeners = new ArrayList<>();
@@ -2825,6 +2826,7 @@
*/
void initializeChangeTransition(Rect startBounds, @Nullable SurfaceControl freezeTarget) {
if (mDisplayContent.mTransitionController.isShellTransitionsEnabled()) {
+ mDisplayContent.mTransitionController.collectVisibleChange(this);
// TODO(b/207070762): request shell transition for activityEmbedding change.
return;
}
@@ -3666,6 +3668,7 @@
boolean onSyncFinishedDrawing() {
if (mSyncState == SYNC_STATE_NONE) return false;
mSyncState = SYNC_STATE_READY;
+ mSyncMethodOverride = BLASTSyncEngine.METHOD_UNDEFINED;
mWmService.mWindowPlacerLocked.requestTraversal();
ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "onSyncFinishedDrawing %s", this);
return true;
@@ -3684,6 +3687,13 @@
mSyncGroup = group;
}
+ @Nullable
+ BLASTSyncEngine.SyncGroup getSyncGroup() {
+ if (mSyncGroup != null) return mSyncGroup;
+ if (mParent != null) return mParent.getSyncGroup();
+ return null;
+ }
+
/**
* Prepares this container for participation in a sync-group. This includes preparing all its
* children.
@@ -3723,6 +3733,7 @@
}
if (cancel && mSyncGroup != null) mSyncGroup.onCancelSync(this);
mSyncState = SYNC_STATE_NONE;
+ mSyncMethodOverride = BLASTSyncEngine.METHOD_UNDEFINED;
mSyncGroup = null;
}
@@ -3825,6 +3836,7 @@
// disable this when shell transitions is disabled.
if (mTransitionController.isShellTransitionsEnabled()) {
mSyncState = SYNC_STATE_NONE;
+ mSyncMethodOverride = BLASTSyncEngine.METHOD_UNDEFINED;
}
prepareSync();
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index dce0fbe..6819833 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -93,7 +93,6 @@
import static android.view.WindowManagerGlobal.ADD_OKAY;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN;
@@ -105,7 +104,6 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
-import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
@@ -220,7 +218,6 @@
import android.os.SystemService;
import android.os.Trace;
import android.os.UserHandle;
-import android.os.WorkSource;
import android.provider.DeviceConfigInterface;
import android.provider.Settings;
import android.service.vr.IVrManager;
@@ -322,6 +319,7 @@
import com.android.server.policy.WindowManagerPolicy.ScreenOffListener;
import com.android.server.power.ShutdownThread;
import com.android.server.utils.PriorityDump;
+import com.android.server.wm.utils.WmDisplayCutout;
import dalvik.annotation.optimization.NeverCompile;
@@ -643,10 +641,6 @@
boolean mBootAnimationStopped = false;
long mBootWaitForWindowsStartTime = -1;
- // Following variables are for debugging screen wakelock only.
- WindowState mLastWakeLockHoldingWindow = null;
- WindowState mLastWakeLockObscuringWindow = null;
-
/** Dump of the windows and app tokens at the time of the last ANR. Cleared after
* LAST_ANR_LIFETIME_DURATION_MSECS */
String mLastANRState;
@@ -1011,10 +1005,6 @@
private boolean mHasWideColorGamutSupport;
private boolean mHasHdrSupport;
- /** Who is holding the screen on. */
- private Session mHoldingScreenOn;
- private PowerManager.WakeLock mHoldingScreenWakeLock;
-
/** Whether or not a layout can cause a wake up when theater mode is enabled. */
boolean mAllowTheaterModeWakeFromLayout;
@@ -1349,10 +1339,6 @@
mSettingsObserver = new SettingsObserver();
- mHoldingScreenWakeLock = mPowerManager.newWakeLock(
- PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
- mHoldingScreenWakeLock.setReferenceCounted(false);
-
mSurfaceAnimationRunner = new SurfaceAnimationRunner(mTransactionFactory,
mPowerManagerInternal);
@@ -1831,7 +1817,7 @@
prepareNoneTransitionForRelaunching(activity);
}
- if (displayPolicy.areSystemBarsForcedShownLw()) {
+ if (displayPolicy.areSystemBarsForcedConsumedLw()) {
res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS;
}
@@ -1870,7 +1856,8 @@
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addWindow: New client %s"
+ ": window=%s Callers=%s", client.asBinder(), win, Debug.getCallers(5));
- if (win.isVisibleRequestedOrAdding() && displayContent.updateOrientation()) {
+ if ((win.isVisibleRequestedOrAdding() && displayContent.updateOrientation())
+ || win.providesNonDecorInsets()) {
displayContent.sendNewConfiguration();
}
@@ -2556,7 +2543,7 @@
if (win.mActivityRecord != null) {
win.mActivityRecord.updateReportedVisibilityLocked();
}
- if (displayPolicy.areSystemBarsForcedShownLw()) {
+ if (displayPolicy.areSystemBarsForcedConsumedLw()) {
result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
}
if (!win.isGoneForLayout()) {
@@ -2587,7 +2574,7 @@
final int maybeSyncSeqId;
if (mUseBLASTSync && win.useBLASTSync() && viewVisibility != View.GONE
&& win.mSyncSeqId > lastSyncSeqId) {
- maybeSyncSeqId = win.mSyncSeqId;
+ maybeSyncSeqId = win.shouldSyncWithBuffers() ? win.mSyncSeqId : -1;
win.markRedrawForSyncReported();
} else {
maybeSyncSeqId = -1;
@@ -6037,34 +6024,6 @@
});
}
- void setHoldScreenLocked(final Session newHoldScreen) {
- final boolean hold = newHoldScreen != null;
-
- if (hold && mHoldingScreenOn != newHoldScreen) {
- mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
- }
- mHoldingScreenOn = newHoldScreen;
-
- final boolean state = mHoldingScreenWakeLock.isHeld();
- if (hold != state) {
- if (hold) {
- ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to %s",
- mRoot.mHoldScreenWindow);
- mLastWakeLockHoldingWindow = mRoot.mHoldScreenWindow;
- mLastWakeLockObscuringWindow = null;
- mHoldingScreenWakeLock.acquire();
- mPolicy.keepScreenOnStartedLw();
- } else {
- ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by %s",
- mRoot.mObscuringWindow);
- mLastWakeLockHoldingWindow = null;
- mLastWakeLockObscuringWindow = mRoot.mObscuringWindow;
- mPolicy.keepScreenOnStoppedLw();
- mHoldingScreenWakeLock.release();
- }
- }
- }
-
void requestTraversal() {
mWindowPlacerLocked.requestTraversal();
}
@@ -6383,27 +6342,6 @@
}
}
- /**
- * Used by ActivityManager to determine where to position an app with aspect ratio shorter then
- * the screen is.
- * @see DisplayPolicy#getNavBarPosition()
- */
- @Override
- @WindowManagerPolicy.NavigationBarPosition
- public int getNavBarPosition(int displayId) {
- synchronized (mGlobalLock) {
- // Perform layout if it was scheduled before to make sure that we get correct nav bar
- // position when doing rotations.
- final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
- if (displayContent == null) {
- Slog.w(TAG, "getNavBarPosition with invalid displayId=" + displayId
- + " callers=" + Debug.getCallers(3));
- return NAV_BAR_INVALID;
- }
- return displayContent.getDisplayPolicy().getNavBarPosition();
- }
- }
-
@Override
public void createInputConsumer(IBinder token, String name, int displayId,
InputChannel inputChannel) {
@@ -6719,9 +6657,6 @@
pw.print(mLastFinishedFreezeSource);
}
pw.println();
- pw.print(" mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow);
- pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow);
- pw.println();
mInputManagerCallback.dump(pw, " ");
mTaskSnapshotController.dump(pw, " ");
@@ -7242,7 +7177,9 @@
final DisplayContent dc = mRoot.getDisplayContent(displayId);
if (dc != null) {
final DisplayInfo di = dc.getDisplayInfo();
- dc.getDisplayPolicy().getStableInsetsLw(di.rotation, di.displayCutout, outInsets);
+ final WmDisplayCutout cutout = dc.calculateDisplayCutoutForRotation(di.rotation);
+ dc.getDisplayPolicy().getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+ cutout, outInsets);
}
}
@@ -8897,7 +8834,7 @@
: overrideScale;
outInsetsState.scale(1f / compatScale);
}
- return dc.getDisplayPolicy().areSystemBarsForcedShownLw();
+ return dc.getDisplayPolicy().areSystemBarsForcedConsumedLw();
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -8917,13 +8854,19 @@
}
// Retrieve the DisplayInfo across all possible display layouts.
- return List.copyOf(mPossibleDisplayInfoMapper.getPossibleDisplayInfos(displayId));
+ return mPossibleDisplayInfoMapper.getPossibleDisplayInfos(displayId);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
+ List<DisplayInfo> getPossibleDisplayInfoLocked(int displayId) {
+ // Retrieve the DisplayInfo for all possible rotations across all possible display
+ // layouts.
+ return mPossibleDisplayInfoMapper.getPossibleDisplayInfos(displayId);
+ }
+
/**
* Returns {@code true} when the calling package is the recents component.
*/
@@ -9298,4 +9241,9 @@
"Unexpected letterbox background type: " + letterboxBackgroundType);
}
}
+
+ BackNaviAnimationController getBackNaviAnimationController() {
+ return mAtmService.mBackNavigationController != null
+ ? mAtmService.mBackNavigationController.mBackNaviAnimationController : null;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index ff43a96..c22091b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -34,7 +34,6 @@
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
-import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ShellCommand;
import android.os.UserHandle;
@@ -47,8 +46,6 @@
import com.android.internal.os.ByteTransferPipe;
import com.android.internal.protolog.ProtoLogImpl;
-import com.android.server.LocalServices;
-import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType;
import com.android.server.wm.LetterboxConfiguration.LetterboxHorizontalReachabilityPosition;
import com.android.server.wm.LetterboxConfiguration.LetterboxVerticalReachabilityPosition;
@@ -56,7 +53,6 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
@@ -106,19 +102,11 @@
// trace files can be written.
return mInternal.mWindowTracing.onShellCommand(this);
case "logging":
- String[] args = peekRemainingArgs();
int result = ProtoLogImpl.getSingleInstance().onShellCommand(this);
if (result != 0) {
- // Let the shell try and handle this
- try (ParcelFileDescriptor pfd
- = ParcelFileDescriptor.dup(getOutFileDescriptor())){
- pw.println("Not handled, calling status bar with args: "
- + Arrays.toString(args));
- LocalServices.getService(StatusBarManagerInternal.class)
- .handleWindowManagerLoggingCommand(args, pfd);
- } catch (IOException e) {
- pw.println("Failed to handle logging command: " + e.getMessage());
- }
+ pw.println("Not handled, please use "
+ + "`adb shell dumpsys activity service SystemUIService WMShell` "
+ + "if you are looking for ProtoLog in WMShell");
}
return result;
case "user-rotation":
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 68b1d35..d34ad7d 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -29,6 +29,7 @@
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_LAUNCH_TASK;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_PENDING_INTENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_INSETS_PROVIDER;
+import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_TASK;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
@@ -74,6 +75,7 @@
import android.util.Slog;
import android.view.RemoteAnimationAdapter;
import android.view.SurfaceControl;
+import android.view.WindowManager;
import android.window.IDisplayAreaOrganizerController;
import android.window.ITaskFragmentOrganizer;
import android.window.ITaskFragmentOrganizerController;
@@ -99,6 +101,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.function.IntSupplier;
/**
@@ -175,7 +178,7 @@
if (t == null) {
throw new IllegalArgumentException("Null transaction passed to applyTransaction");
}
- enforceTaskPermission("applyTransaction()", t);
+ enforceTaskPermission("applyTransaction()");
final CallerInfo caller = new CallerInfo();
final long ident = Binder.clearCallingIdentity();
try {
@@ -193,7 +196,7 @@
if (t == null) {
throw new IllegalArgumentException("Null transaction passed to applySyncTransaction");
}
- enforceTaskPermission("applySyncTransaction()", t);
+ enforceTaskPermission("applySyncTransaction()");
final CallerInfo caller = new CallerInfo();
final long ident = Binder.clearCallingIdentity();
try {
@@ -372,6 +375,87 @@
}
}
+ /**
+ * Applies the {@link WindowContainerTransaction} as a request from
+ * {@link android.window.TaskFragmentOrganizer}.
+ *
+ * @param wct {@link WindowContainerTransaction} to apply.
+ * @param type {@link WindowManager.TransitionType} if it needs to start a new transition.
+ * @param shouldApplyIndependently If {@code true}, the {@code wct} will request a new
+ * transition, which will be queued until the sync engine is
+ * free if there is any other active sync. If {@code false},
+ * the {@code wct} will be directly applied to the active sync.
+ */
+ void applyTaskFragmentTransactionLocked(@NonNull WindowContainerTransaction wct,
+ @WindowManager.TransitionType int type, boolean shouldApplyIndependently) {
+ if (!isValidTransaction(wct)) {
+ return;
+ }
+ enforceTaskFragmentOrganizerPermission("applyTaskFragmentTransaction()",
+ Objects.requireNonNull(wct.getTaskFragmentOrganizer()),
+ Objects.requireNonNull(wct));
+ final CallerInfo caller = new CallerInfo();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (mTransitionController.getTransitionPlayer() == null) {
+ // No need to worry about transition when Shell transition is not enabled.
+ applyTransaction(wct, -1 /* syncId */, null /* transition */, caller);
+ return;
+ }
+
+ if (!mService.mWindowManager.mSyncEngine.hasActiveSync()) {
+ // Sync is for either transition or applySyncTransaction(). We don't support
+ // multiple sync at the same time because it may cause conflict.
+ // Create a new transition when there is no active sync to collect the changes.
+ final Transition transition = mTransitionController.createTransition(type);
+ applyTransaction(wct, -1 /* syncId */, transition, caller);
+ mTransitionController.requestStartTransition(transition, null /* startTask */,
+ null /* remoteTransition */, null /* displayChange */);
+ return;
+ }
+
+ if (!shouldApplyIndependently) {
+ // Although there is an active sync, we want to apply the transaction now.
+ if (!mTransitionController.isCollecting()) {
+ // This should rarely happen, and we should try to avoid using
+ // {@link #applySyncTransaction} with Shell transition.
+ // We still want to apply and merge the transaction to the active sync
+ // because {@code shouldApplyIndependently} is {@code false}.
+ ProtoLog.w(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
+ "TaskFragmentTransaction changes are not collected in transition"
+ + " because there is an ongoing sync for"
+ + " applySyncTransaction().");
+ }
+ // TODO(b/207070762) make sure changes are all collected.
+ applyTransaction(wct, -1 /* syncId */, null /* transition */, caller);
+ return;
+ }
+
+ // It is ok to queue the WCT until the sync engine is free.
+ final Transition nextTransition = new Transition(type, 0 /* flags */,
+ mTransitionController, mService.mWindowManager.mSyncEngine);
+ ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
+ "Creating Pending Transition for TaskFragment: %s", nextTransition);
+ mService.mWindowManager.mSyncEngine.queueSyncSet(
+ // Make sure to collect immediately to prevent another transition
+ // from sneaking in before it. Note: moveToCollecting internally
+ // calls startSyncSet.
+ () -> mTransitionController.moveToCollecting(nextTransition),
+ () -> {
+ if (isValidTransaction(wct)) {
+ applyTransaction(wct, -1 /*syncId*/, nextTransition, caller);
+ mTransitionController.requestStartTransition(nextTransition,
+ null /* startTask */, null /* remoteTransition */,
+ null /* displayChange */);
+ } else {
+ nextTransition.abort();
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
private void applyTransaction(@NonNull WindowContainerTransaction t, int syncId,
@Nullable Transition transition, @NonNull CallerInfo caller) {
applyTransaction(t, syncId, transition, caller, null /* finishTransition */);
@@ -386,12 +470,6 @@
private void applyTransaction(@NonNull WindowContainerTransaction t, int syncId,
@Nullable Transition transition, @NonNull CallerInfo caller,
@Nullable Transition finishTransition) {
- if (t.getTaskFragmentOrganizer() != null && !mTaskFragmentOrganizerController
- .isOrganizerRegistered(t.getTaskFragmentOrganizer())) {
- Slog.e(TAG, "Caller organizer=" + t.getTaskFragmentOrganizer()
- + " is no longer registered");
- return;
- }
int effects = 0;
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Apply window transaction, syncId=%d", syncId);
mService.deferWindowLayout();
@@ -702,6 +780,12 @@
@Nullable ITaskFragmentOrganizer organizer, @Nullable Transition finishTransition) {
final int type = hop.getType();
switch (type) {
+ case HIERARCHY_OP_TYPE_REMOVE_TASK: {
+ final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
+ final Task task = wc != null ? wc.asTask() : null;
+ task.remove(true, "Applying remove task Hierarchy Op");
+ break;
+ }
case HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT: {
final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
final Task task = wc != null ? wc.asTask() : null;
@@ -1405,7 +1489,7 @@
private BLASTSyncEngine.SyncGroup prepareSyncWithOrganizer(
IWindowContainerTransactionCallback callback) {
final BLASTSyncEngine.SyncGroup s = mService.mWindowManager.mSyncEngine
- .prepareSyncSet(this, "");
+ .prepareSyncSet(this, "", BLASTSyncEngine.METHOD_BLAST);
mTransactionCallbacksByPendingSyncId.put(s.mSyncId, callback);
return s;
}
@@ -1487,25 +1571,24 @@
mService.enforceTaskPermission(func);
}
- private void enforceTaskPermission(String func, @Nullable WindowContainerTransaction t) {
- if (t == null || t.getTaskFragmentOrganizer() == null) {
- enforceTaskPermission(func);
- return;
+ private boolean isValidTransaction(@NonNull WindowContainerTransaction t) {
+ if (t.getTaskFragmentOrganizer() != null && !mTaskFragmentOrganizerController
+ .isOrganizerRegistered(t.getTaskFragmentOrganizer())) {
+ // Transaction from an unregistered organizer should not be applied. This can happen
+ // when the organizer process died before the transaction is applied.
+ Slog.e(TAG, "Caller organizer=" + t.getTaskFragmentOrganizer()
+ + " is no longer registered");
+ return false;
}
-
- // Apps may not have the permission to manage Tasks, but we are allowing apps to manage
- // TaskFragments belonging to their own Task.
- enforceOperationsAllowedForTaskFragmentOrganizer(func, t);
+ return true;
}
/**
* Makes sure that the transaction only contains operations that are allowed for the
* {@link WindowContainerTransaction#getTaskFragmentOrganizer()}.
*/
- private void enforceOperationsAllowedForTaskFragmentOrganizer(
- String func, WindowContainerTransaction t) {
- final ITaskFragmentOrganizer organizer = t.getTaskFragmentOrganizer();
-
+ private void enforceTaskFragmentOrganizerPermission(@NonNull String func,
+ @NonNull ITaskFragmentOrganizer organizer, @NonNull WindowContainerTransaction t) {
// Configuration changes
final Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
t.getChanges().entrySet().iterator();
@@ -1524,7 +1607,6 @@
final int type = hop.getType();
// Check for each type of the operations that are allowed for TaskFragmentOrganizer.
switch (type) {
- case HIERARCHY_OP_TYPE_REORDER:
case HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT:
enforceTaskFragmentOrganized(func,
WindowContainer.fromBinder(hop.getContainer()), organizer);
@@ -1540,14 +1622,19 @@
// We are allowing organizer to create TaskFragment. We will check the
// ownerToken in #createTaskFragment, and trigger error callback if that is not
// valid.
+ break;
case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT:
- case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT:
- case HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS:
case HIERARCHY_OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT:
- // We are allowing organizer to start/reparent activity to a TaskFragment it
- // created, or set two TaskFragments adjacent to each other. Nothing to check
- // here because the TaskFragment may not be created yet, but will be created in
- // the same transaction.
+ enforceTaskFragmentOrganized(func, hop.getContainer(), organizer);
+ break;
+ case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT:
+ enforceTaskFragmentOrganized(func, hop.getNewParent(), organizer);
+ break;
+ case HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS:
+ enforceTaskFragmentOrganized(func, hop.getContainer(), organizer);
+ if (hop.getAdjacentRoot() != null) {
+ enforceTaskFragmentOrganized(func, hop.getAdjacentRoot(), organizer);
+ }
break;
case HIERARCHY_OP_TYPE_REPARENT_CHILDREN:
enforceTaskFragmentOrganized(func,
@@ -1570,8 +1657,12 @@
}
}
- private void enforceTaskFragmentOrganized(String func, @Nullable WindowContainer wc,
- ITaskFragmentOrganizer organizer) {
+ /**
+ * Makes sure that the given {@link WindowContainer} is a {@link TaskFragment} organized by the
+ * given {@link ITaskFragmentOrganizer}.
+ */
+ private void enforceTaskFragmentOrganized(@NonNull String func, @Nullable WindowContainer wc,
+ @NonNull ITaskFragmentOrganizer organizer) {
if (wc == null) {
Slog.e(TAG, "Attempt to operate on window that no longer exists");
return;
@@ -1588,6 +1679,26 @@
}
/**
+ * Makes sure that the {@link TaskFragment} of the given fragment token is created and organized
+ * by the given {@link ITaskFragmentOrganizer}.
+ */
+ private void enforceTaskFragmentOrganized(@NonNull String func,
+ @NonNull IBinder fragmentToken, @NonNull ITaskFragmentOrganizer organizer) {
+ Objects.requireNonNull(fragmentToken);
+ final TaskFragment tf = mLaunchTaskFragments.get(fragmentToken);
+ // When the TaskFragment is {@code null}, it means that the TaskFragment will be created
+ // later in the same transaction, in which case it will always be organized by the given
+ // organizer.
+ if (tf != null && !tf.hasTaskFragmentOrganizer(organizer)) {
+ String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid() + " trying to modify TaskFragment not"
+ + " belonging to the TaskFragmentOrganizer=" + organizer;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ }
+
+ /**
* Makes sure that SurfaceControl transactions and the ability to set bounds outside of the
* parent bounds are not allowed for embedding without full trust between the host and the
* target.
@@ -1669,6 +1780,13 @@
final ITaskFragmentOrganizer organizer = ITaskFragmentOrganizer.Stub.asInterface(
creationParams.getOrganizer().asBinder());
+ if (mLaunchTaskFragments.containsKey(creationParams.getFragmentToken())) {
+ final Throwable exception =
+ new IllegalArgumentException("TaskFragment token must be unique");
+ sendTaskFragmentOperationFailure(organizer, errorCallbackToken, null /* taskFragment */,
+ HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT, exception);
+ return;
+ }
if (ownerActivity == null || ownerActivity.getTask() == null) {
final Throwable exception =
new IllegalArgumentException("Not allowed to operate with invalid ownerToken");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2432afb..b601cc5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -243,6 +243,7 @@
import android.view.ViewDebug;
import android.view.ViewTreeObserver;
import android.view.WindowInfo;
+import android.view.WindowInsets;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowManager;
import android.view.animation.Animation;
@@ -391,7 +392,7 @@
*/
int mSyncSeqId = 0;
- /** The last syncId associated with a prepareSync or 0 when no sync is active. */
+ /** The last syncId associated with a BLAST prepareSync or 0 when no BLAST sync is active. */
int mPrepareSyncSeqId = 0;
/**
@@ -1897,6 +1898,19 @@
return (mPolicyVisibility & POLICY_VISIBILITY_ALL) == POLICY_VISIBILITY_ALL;
}
+ boolean providesNonDecorInsets() {
+ if (mProvidedInsetsSources == null) {
+ return false;
+ }
+ for (int i = mProvidedInsetsSources.size() - 1; i >= 0; i--) {
+ final int type = mProvidedInsetsSources.keyAt(i);
+ if ((InsetsState.toPublicType(type) & WindowInsets.Type.navigationBars()) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
void clearPolicyVisibilityFlag(int policyVisibilityFlag) {
mPolicyVisibility &= ~policyVisibilityFlag;
mWmService.scheduleAnimationLocked();
@@ -2609,14 +2623,19 @@
}
removeImmediately();
- // Removing a visible window will effect the computed orientation
- // So just update orientation if needed.
+ boolean sentNewConfig = false;
if (wasVisible) {
+ // Removing a visible window will effect the computed orientation
+ // So just update orientation if needed.
final DisplayContent displayContent = getDisplayContent();
if (displayContent.updateOrientation()) {
displayContent.sendNewConfiguration();
+ sentNewConfig = true;
}
}
+ if (!sentNewConfig && providesNonDecorInsets()) {
+ getDisplayContent().sendNewConfiguration();
+ }
mWmService.updateFocusedWindowLocked(isFocused()
? UPDATE_FOCUS_REMOVING_FOCUS
: UPDATE_FOCUS_NORMAL,
@@ -3893,12 +3912,13 @@
fillClientWindowFramesAndConfiguration(mClientWindowFrames, mLastReportedConfiguration,
true /* useLatestConfig */, false /* relayoutVisible */);
final boolean syncRedraw = shouldSendRedrawForSync();
+ final boolean syncWithBuffers = syncRedraw && shouldSyncWithBuffers();
final boolean reportDraw = syncRedraw || drawPending;
final boolean isDragResizeChanged = isDragResizeChanged();
- final boolean forceRelayout = syncRedraw || isDragResizeChanged;
+ final boolean forceRelayout = syncWithBuffers || isDragResizeChanged;
final DisplayContent displayContent = getDisplayContent();
final boolean alwaysConsumeSystemBars =
- displayContent.getDisplayPolicy().areSystemBarsForcedShownLw();
+ displayContent.getDisplayPolicy().areSystemBarsForcedConsumedLw();
final int displayId = displayContent.getDisplayId();
if (isDragResizeChanged) {
@@ -3921,7 +3941,7 @@
try {
mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration,
getCompatInsetsState(), forceRelayout, alwaysConsumeSystemBars, displayId,
- mSyncSeqId, resizeMode);
+ syncWithBuffers ? mSyncSeqId : -1, resizeMode);
if (drawPending && prevRotation >= 0 && prevRotation != mLastReportedConfiguration
.getMergedConfiguration().windowConfiguration.getRotation()) {
mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime();
@@ -5936,7 +5956,9 @@
}
mSyncSeqId++;
- mPrepareSyncSeqId = mSyncSeqId;
+ if (getSyncMethod() == BLASTSyncEngine.METHOD_BLAST) {
+ mPrepareSyncSeqId = mSyncSeqId;
+ }
requestRedrawForSync();
return true;
}
@@ -6009,6 +6031,7 @@
postDrawTransaction = null;
skipLayout = true;
} else if (syncActive) {
+ // Currently in a Sync that is using BLAST.
if (!syncStillPending) {
onSyncFinishedDrawing();
}
@@ -6017,6 +6040,9 @@
// Consume the transaction because the sync group will merge it.
postDrawTransaction = null;
}
+ } else if (useBLASTSync()) {
+ // Sync that is not using BLAST
+ onSyncFinishedDrawing();
}
final boolean layoutNeeded =
@@ -6075,6 +6101,18 @@
return useBLASTSync();
}
+ int getSyncMethod() {
+ final BLASTSyncEngine.SyncGroup syncGroup = getSyncGroup();
+ if (syncGroup == null) return BLASTSyncEngine.METHOD_NONE;
+ if (mSyncMethodOverride != BLASTSyncEngine.METHOD_UNDEFINED) return mSyncMethodOverride;
+ return syncGroup.mSyncMethod;
+ }
+
+ boolean shouldSyncWithBuffers() {
+ if (!mDrawHandlers.isEmpty()) return true;
+ return getSyncMethod() == BLASTSyncEngine.METHOD_BLAST;
+ }
+
void requestRedrawForSync() {
mRedrawForSyncReported = false;
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 2ee5fb0..aa58902 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -228,7 +228,5 @@
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "mTraversalScheduled=" + mTraversalScheduled);
- pw.println(prefix + "mHoldScreenWindow=" + mService.mRoot.mHoldScreenWindow);
- pw.println(prefix + "mObscuringWindow=" + mService.mRoot.mObscuringWindow);
}
}
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index dbc1a00..af5718f 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -113,7 +113,7 @@
uint64_t bytesConsumed = 0;
while (bytesConsumed < bytesToConsume) {
- if (CC_UNLIKELY(batch.totalVmas > 0)) {
+ if (CC_UNLIKELY(batch.totalVmas == 0)) {
// No more vmas to consume
break;
}
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index d322290..3c68662 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -205,6 +205,7 @@
.setRequiresDeviceIdle(true)
.setRequiresCharging(true)
.setPeriodic(BG_PROCESS_PERIOD)
+ .setPriority(JobInfo.PRIORITY_MIN)
.build());
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt
new file mode 100644
index 0000000..3c3172b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm
+
+import android.content.pm.PackageManager
+import android.content.pm.UserInfo
+import android.os.Build
+import android.util.Log
+import com.android.server.testutils.any
+import com.android.server.testutils.spy
+import com.android.server.testutils.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mockito.doAnswer
+
+@RunWith(JUnit4::class)
+class DeletePackageHelperTest {
+
+ @Rule
+ @JvmField
+ val rule = MockSystemRule()
+
+ private lateinit var mPms: PackageManagerService
+ private lateinit var mUserManagerInternal: UserManagerInternal
+
+ @Before
+ @Throws(Exception::class)
+ fun setup() {
+ Log.i("system.out", "setup", Exception())
+ rule.system().stageNominalSystemState()
+ rule.system().stageScanExistingPackage(
+ "a.data.package", 1L, rule.system().dataAppDirectory)
+
+ mUserManagerInternal = rule.mocks().injector.userManagerInternal
+ whenever(mUserManagerInternal.getUserIds()).thenReturn(intArrayOf(0, 1))
+
+ mPms = createPackageManagerService()
+ doAnswer { false }.`when`(mPms).isPackageDeviceAdmin(any(), any())
+ doAnswer { null }.`when`(mPms).freezePackageForDelete(any(), any(), any(), any())
+ }
+
+ private fun createPackageManagerService(): PackageManagerService {
+ return spy(PackageManagerService(rule.mocks().injector,
+ false /*coreOnly*/,
+ false /*factoryTest*/,
+ MockSystem.DEFAULT_VERSION_INFO.fingerprint,
+ false /*isEngBuild*/,
+ false /*isUserDebugBuild*/,
+ Build.VERSION_CODES.CUR_DEVELOPMENT,
+ Build.VERSION.INCREMENTAL))
+ }
+
+ @Test
+ fun deleteSystemPackageFailsIfNotAdminAndNotProfile() {
+ val ps = mPms.mSettings.getPackageLPr("a.data.package")
+ whenever(PackageManagerServiceUtils.isSystemApp(ps)).thenReturn(true)
+ whenever(mUserManagerInternal.getUserInfo(1)).thenReturn(UserInfo(1, "test", 0))
+ whenever(mUserManagerInternal.getProfileParentId(1)).thenReturn(1)
+
+ val dph = DeletePackageHelper(mPms)
+ val result = dph.deletePackageX("a.data.package", 1L, 1, 0, false)
+
+ assertThat(result).isEqualTo(PackageManager.DELETE_FAILED_USER_RESTRICTED)
+ }
+
+ @Test
+ fun deleteSystemPackageFailsIfProfileOfNonAdmin() {
+ val userId = 1
+ val parentId = 5
+ val ps = mPms.mSettings.getPackageLPr("a.data.package")
+ whenever(PackageManagerServiceUtils.isSystemApp(ps)).thenReturn(true)
+ whenever(mUserManagerInternal.getUserInfo(userId)).thenReturn(
+ UserInfo(userId, "test", UserInfo.FLAG_PROFILE))
+ whenever(mUserManagerInternal.getProfileParentId(userId)).thenReturn(parentId)
+ whenever(mUserManagerInternal.getUserInfo(parentId)).thenReturn(
+ UserInfo(userId, "testparent", 0))
+
+ val dph = DeletePackageHelper(mPms)
+ val result = dph.deletePackageX("a.data.package", 1L, userId, 0, false)
+
+ assertThat(result).isEqualTo(PackageManager.DELETE_FAILED_USER_RESTRICTED)
+ }
+
+ @Test
+ fun deleteSystemPackageSucceedsIfAdmin() {
+ val ps = mPms.mSettings.getPackageLPr("a.data.package")
+ whenever(PackageManagerServiceUtils.isSystemApp(ps)).thenReturn(true)
+ whenever(mUserManagerInternal.getUserInfo(1)).thenReturn(
+ UserInfo(1, "test", UserInfo.FLAG_ADMIN))
+
+ val dph = DeletePackageHelper(mPms)
+ val result = dph.deletePackageX("a.data.package", 1L, 1,
+ PackageManager.DELETE_SYSTEM_APP, false)
+
+ assertThat(result).isEqualTo(PackageManager.DELETE_SUCCEEDED)
+ }
+
+ @Test
+ fun deleteSystemPackageSucceedsIfProfileOfAdmin() {
+ val userId = 1
+ val parentId = 5
+ val ps = mPms.mSettings.getPackageLPr("a.data.package")
+ whenever(PackageManagerServiceUtils.isSystemApp(ps)).thenReturn(true)
+ whenever(mUserManagerInternal.getUserInfo(userId)).thenReturn(
+ UserInfo(userId, "test", UserInfo.FLAG_PROFILE))
+ whenever(mUserManagerInternal.getProfileParentId(userId)).thenReturn(parentId)
+ whenever(mUserManagerInternal.getUserInfo(parentId)).thenReturn(
+ UserInfo(userId, "testparent", UserInfo.FLAG_ADMIN))
+
+ val dph = DeletePackageHelper(mPms)
+ val result = dph.deletePackageX("a.data.package", 1L, userId,
+ PackageManager.DELETE_SYSTEM_APP, false)
+
+ assertThat(result).isEqualTo(PackageManager.DELETE_SUCCEEDED)
+ }
+
+ @Test
+ fun deleteSystemPackageSucceedsIfNotAdminButDeleteSystemAppSpecified() {
+ val ps = mPms.mSettings.getPackageLPr("a.data.package")
+ whenever(PackageManagerServiceUtils.isSystemApp(ps)).thenReturn(true)
+ whenever(mUserManagerInternal.getUserInfo(1)).thenReturn(UserInfo(1, "test", 0))
+ whenever(mUserManagerInternal.getProfileParentId(1)).thenReturn(1)
+
+ val dph = DeletePackageHelper(mPms)
+ val result = dph.deletePackageX("a.data.package", 1L, 1,
+ PackageManager.DELETE_SYSTEM_APP, false)
+
+ assertThat(result).isEqualTo(PackageManager.DELETE_SUCCEEDED)
+ }
+}
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 0483a60..7ae70eb 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -147,6 +147,19 @@
android:resource="@xml/test_dream_metadata" />
</service>
+ <service
+ android:name="com.android.server.dreams.TestDreamServiceWithInvalidSettings"
+ android:exported="false"
+ android:label="Test Dream" >
+ <intent-filter>
+ <action android:name="android.service.dreams.DreamService" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <meta-data
+ android:name="android.service.dream"
+ android:resource="@xml/test_dream_metadata_invalid" />
+ </service>
+
<receiver android:name="com.android.server.devicepolicy.ApplicationRestrictionsTest$AdminReceiver"
android:permission="android.permission.BIND_DEVICE_ADMIN"
android:exported="true">
diff --git a/services/tests/servicestests/res/xml/test_dream_metadata.xml b/services/tests/servicestests/res/xml/test_dream_metadata.xml
index aa054f1..9905c69 100644
--- a/services/tests/servicestests/res/xml/test_dream_metadata.xml
+++ b/services/tests/servicestests/res/xml/test_dream_metadata.xml
@@ -15,5 +15,5 @@
-->
<dream xmlns:android="http://schemas.android.com/apk/res/android"
- android:settingsActivity="com.android.server.dreams/.TestDreamSettingsActivity"
+ android:settingsActivity="com.android.frameworks.servicestests/.TestDreamSettingsActivity"
android:showClockAndComplications="false" />
diff --git a/services/tests/servicestests/res/xml/test_dream_metadata_invalid.xml b/services/tests/servicestests/res/xml/test_dream_metadata_invalid.xml
new file mode 100644
index 0000000..47864d9
--- /dev/null
+++ b/services/tests/servicestests/res/xml/test_dream_metadata_invalid.xml
@@ -0,0 +1,20 @@
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!-- The settings activity is in a different package, which is invalid -->
+<dream xmlns:android="http://schemas.android.com/apk/res/android"
+ android:settingsActivity="com.android.server.dreams/.TestDreamSettingsActivity"
+ android:showClockAndComplications="false"/>
diff --git a/services/tests/servicestests/src/com/android/server/ambientcontext/AmbientContextManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/ambientcontext/AmbientContextManagerServiceTest.java
new file mode 100644
index 0000000..c75abf8
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/ambientcontext/AmbientContextManagerServiceTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.ambientcontext;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.PendingIntent;
+import android.app.ambientcontext.AmbientContextEvent;
+import android.app.ambientcontext.AmbientContextEventRequest;
+import android.app.ambientcontext.IAmbientContextObserver;
+import android.content.Intent;
+import android.os.UserHandle;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+import java.util.List;
+
+/**
+ * Unit test for {@link AmbientContextManagerService}.
+ * atest FrameworksServicesTests:AmbientContextManagerServiceTest
+ */
+public class AmbientContextManagerServiceTest {
+ public static final String SYSTEM_PACKAGE_NAME = "com.android.frameworks.servicestests";
+ private static final int USER_ID = UserHandle.USER_SYSTEM;
+
+ @SmallTest
+ @Test
+ public void testClientRequest() {
+ AmbientContextEventRequest request = new AmbientContextEventRequest.Builder()
+ .addEventType(AmbientContextEvent.EVENT_COUGH)
+ .build();
+ Intent intent = new Intent();
+ PendingIntent pendingIntent = PendingIntent.getBroadcast(
+ InstrumentationRegistry.getTargetContext(), 0,
+ intent, PendingIntent.FLAG_IMMUTABLE);
+ IAmbientContextObserver observer = new IAmbientContextObserver.Stub() {
+ @Override
+ public void onEvents(List<AmbientContextEvent> events) {
+ }
+
+ @Override
+ public void onRegistrationComplete(int statusCode) {
+ }
+ };
+ AmbientContextManagerService.ClientRequest clientRequest =
+ new AmbientContextManagerService.ClientRequest(USER_ID, request,
+ pendingIntent.getCreatorPackage(), observer);
+
+ assertThat(clientRequest.getRequest()).isEqualTo(request);
+ assertThat(clientRequest.getPackageName()).isEqualTo(SYSTEM_PACKAGE_NAME);
+ assertThat(clientRequest.getObserver()).isEqualTo(observer);
+ assertThat(clientRequest.hasUserId(USER_ID)).isTrue();
+ assertThat(clientRequest.hasUserId(-1)).isFalse();
+ assertThat(clientRequest.hasUserIdAndPackageName(USER_ID, SYSTEM_PACKAGE_NAME)).isTrue();
+ assertThat(clientRequest.hasUserIdAndPackageName(-1, SYSTEM_PACKAGE_NAME)).isFalse();
+ assertThat(clientRequest.hasUserIdAndPackageName(USER_ID, "random.package.name"))
+ .isFalse();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/ambientcontext/OWNERS b/services/tests/servicestests/src/com/android/server/ambientcontext/OWNERS
new file mode 100644
index 0000000..ddfb6e3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/ambientcontext/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/ambientcontext/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
index b17c3a1..428eaff 100644
--- a/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
@@ -55,14 +55,20 @@
mMockAudioService = mock(AudioService.class);
mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
- mSpatHelper = new SpatializerHelper(mMockAudioService, mSpyAudioSystem);
+ mSpatHelper = new SpatializerHelper(mMockAudioService, mSpyAudioSystem,
+ false /*headTrackingEnabledByDefault*/);
}
+ /**
+ * Test that constructing an SADeviceState instance requires a non-null address for a
+ * wireless type, but can take null for a non-wireless type;
+ * @throws Exception
+ */
@Test
public void testSADeviceStateNullAddressCtor() throws Exception {
try {
- SADeviceState devState = new SADeviceState(
- AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, null);
+ SADeviceState devState = new SADeviceState(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, null);
+ devState = new SADeviceState(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, null);
Assert.fail();
} catch (NullPointerException e) { }
}
@@ -88,11 +94,12 @@
final AudioDeviceAttributes dev1 =
new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, "");
final AudioDeviceAttributes dev2 =
- new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "C3:P0:beep");
+ new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "C3:PO:beep");
final AudioDeviceAttributes dev3 =
new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "R2:D2:bloop");
doNothing().when(mMockAudioService).persistSpatialAudioDeviceSettings();
+ mSpatHelper.initForTest(true /*binaural*/, true /*transaural*/);
// test with single device
mSpatHelper.addCompatibleAudioDevice(dev1);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/ALSProbeTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/ALSProbeTest.java
new file mode 100644
index 0000000..10f0a5c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/ALSProbeTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.log;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.input.InputSensorInfo;
+import android.os.Handler;
+import android.platform.test.annotations.Presubmit;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+
+import androidx.test.filters.SmallTest;
+
+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.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class ALSProbeTest {
+
+ private static final long TIMEOUT_MS = 1000;
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private SensorManager mSensorManager;
+ @Captor
+ private ArgumentCaptor<SensorEventListener> mSensorEventListenerCaptor;
+
+ private TestableLooper mLooper;
+ private Sensor mLightSensor = new Sensor(
+ new InputSensorInfo("", "", 0, 0, Sensor.TYPE_LIGHT, 0, 0, 0, 0, 0, 0,
+ "", "", 0, 0, 0));
+
+ private ALSProbe mProbe;
+
+ @Before
+ public void setup() {
+ mLooper = TestableLooper.get(this);
+ when(mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn(mLightSensor);
+ mProbe = new ALSProbe(mSensorManager, new Handler(mLooper.getLooper()), TIMEOUT_MS - 1);
+ reset(mSensorManager);
+ }
+
+ @Test
+ public void testEnable() {
+ final float value = 2.0f;
+ mProbe.enable();
+ verify(mSensorManager).registerListener(
+ mSensorEventListenerCaptor.capture(), any(), anyInt());
+
+ mSensorEventListenerCaptor.getValue().onSensorChanged(
+ new SensorEvent(mLightSensor, 1, 1, new float[]{4.0f}));
+ mSensorEventListenerCaptor.getValue().onSensorChanged(
+ new SensorEvent(mLightSensor, 1, 2, new float[]{value}));
+
+ assertThat(mProbe.getCurrentLux()).isEqualTo(value);
+ }
+
+ @Test
+ public void testEnableOnlyOnce() {
+ mProbe.enable();
+ mProbe.enable();
+
+ verify(mSensorManager).registerListener(any(), any(), anyInt());
+ verifyNoMoreInteractions(mSensorManager);
+ }
+
+ @Test
+ public void testDisable() {
+ mProbe.enable();
+ verify(mSensorManager).registerListener(
+ mSensorEventListenerCaptor.capture(), any(), anyInt());
+ mProbe.disable();
+
+ verify(mSensorManager).unregisterListener(eq(mSensorEventListenerCaptor.getValue()));
+ verifyNoMoreInteractions(mSensorManager);
+ }
+
+ @Test
+ public void testDestroy() {
+ mProbe.destroy();
+ mProbe.enable();
+
+ verify(mSensorManager, never()).registerListener(any(), any(), anyInt());
+ verifyNoMoreInteractions(mSensorManager);
+ }
+
+ @Test
+ public void testDisabledReportsNegativeValue() {
+ assertThat(mProbe.getCurrentLux()).isLessThan(0f);
+
+ mProbe.enable();
+ verify(mSensorManager).registerListener(
+ mSensorEventListenerCaptor.capture(), any(), anyInt());
+ mSensorEventListenerCaptor.getValue().onSensorChanged(
+ new SensorEvent(mLightSensor, 1, 1, new float[]{4.0f}));
+ mProbe.disable();
+
+ assertThat(mProbe.getCurrentLux()).isLessThan(0f);
+ }
+
+ @Test
+ public void testWatchDog() {
+ mProbe.enable();
+ verify(mSensorManager).registerListener(
+ mSensorEventListenerCaptor.capture(), any(), anyInt());
+ mSensorEventListenerCaptor.getValue().onSensorChanged(
+ new SensorEvent(mLightSensor, 1, 1, new float[]{4.0f}));
+ moveTimeBy(TIMEOUT_MS);
+
+ verify(mSensorManager).unregisterListener(eq(mSensorEventListenerCaptor.getValue()));
+ verifyNoMoreInteractions(mSensorManager);
+ assertThat(mProbe.getCurrentLux()).isLessThan(0f);
+ }
+
+ @Test
+ public void testEnableExtendsWatchDog() {
+ mProbe.enable();
+ verify(mSensorManager).registerListener(any(), any(), anyInt());
+
+ moveTimeBy(TIMEOUT_MS / 2);
+ verify(mSensorManager, never()).unregisterListener(any(SensorEventListener.class));
+
+ mProbe.enable();
+ moveTimeBy(TIMEOUT_MS);
+
+ verify(mSensorManager).unregisterListener(any(SensorEventListener.class));
+ verifyNoMoreInteractions(mSensorManager);
+ assertThat(mProbe.getCurrentLux()).isLessThan(0f);
+ }
+
+ private void moveTimeBy(long millis) {
+ mLooper.moveTimeForward(millis);
+ mLooper.processAllMessages();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
index e6acc90..dd7aeb7 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
@@ -40,8 +40,6 @@
import com.android.internal.statusbar.ISessionListener;
import com.android.internal.statusbar.IStatusBarService;
-import com.google.common.collect.ImmutableList;
-
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -89,33 +87,64 @@
@Test
public void testIsAod() throws RemoteException {
- mListener.onDozeChanged(true);
+ mListener.onDozeChanged(true /* isDozing */, false /* isAwake */);
assertThat(mProvider.isAod()).isTrue();
- mListener.onDozeChanged(false);
+ mListener.onDozeChanged(false /* isDozing */, false /* isAwake */);
assertThat(mProvider.isAod()).isFalse();
when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(false);
- mListener.onDozeChanged(true);
+ mListener.onDozeChanged(true /* isDozing */, false /* isAwake */);
assertThat(mProvider.isAod()).isFalse();
- mListener.onDozeChanged(false);
+ mListener.onDozeChanged(false /* isDozing */, false /* isAwake */);
assertThat(mProvider.isAod()).isFalse();
}
@Test
+ public void testIsAwake() throws RemoteException {
+ mListener.onDozeChanged(false /* isDozing */, true /* isAwake */);
+ assertThat(mProvider.isAwake()).isTrue();
+ mListener.onDozeChanged(false /* isDozing */, false /* isAwake */);
+ assertThat(mProvider.isAwake()).isFalse();
+ mListener.onDozeChanged(true /* isDozing */, true /* isAwake */);
+ assertThat(mProvider.isAwake()).isTrue();
+ mListener.onDozeChanged(true /* isDozing */, false /* isAwake */);
+ assertThat(mProvider.isAwake()).isFalse();
+ }
+
+ @Test
public void testSubscribesToAod() throws RemoteException {
- final List<Boolean> expected = ImmutableList.of(true, false, true, true, false);
final List<Boolean> actual = new ArrayList<>();
mProvider.subscribe(mOpContext, ctx -> {
assertThat(ctx).isSameInstanceAs(mOpContext);
+ assertThat(mProvider.isAod()).isEqualTo(ctx.isAod);
+ assertThat(mProvider.isAwake()).isFalse();
actual.add(ctx.isAod);
});
- for (boolean v : expected) {
- mListener.onDozeChanged(v);
+ for (boolean v : List.of(true, false, true, true, false, false)) {
+ mListener.onDozeChanged(v /* isDozing */, false /* isAwake */);
}
- assertThat(actual).containsExactlyElementsIn(expected).inOrder();
+ assertThat(actual).containsExactly(true, false, true, false).inOrder();
+ }
+
+ @Test
+ public void testSubscribesToAwake() throws RemoteException {
+ final List<Boolean> actual = new ArrayList<>();
+
+ mProvider.subscribe(mOpContext, ctx -> {
+ assertThat(ctx).isSameInstanceAs(mOpContext);
+ assertThat(ctx.isAod).isFalse();
+ assertThat(mProvider.isAod()).isFalse();
+ actual.add(mProvider.isAwake());
+ });
+
+ for (boolean v : List.of(true, false, true, true, false, false)) {
+ mListener.onDozeChanged(false /* isDozing */, v /* isAwake */);
+ }
+
+ assertThat(actual).containsExactly(true, false, true, false).inOrder();
}
@Test
@@ -124,13 +153,13 @@
mProvider.subscribe(mOpContext, emptyConsumer);
mProvider.unsubscribe(mOpContext);
- mListener.onDozeChanged(true);
+ mListener.onDozeChanged(true /* isDozing */, false /* isAwake */);
final Consumer<OperationContext> nonEmptyConsumer = mock(Consumer.class);
mProvider.subscribe(mOpContext, nonEmptyConsumer);
- mListener.onDozeChanged(false);
+ mListener.onDozeChanged(false /* isDozing */, false /* isAwake */);
mProvider.unsubscribe(mOpContext);
- mListener.onDozeChanged(true);
+ mListener.onDozeChanged(true /* isDozing */, false /* isAwake */);
verify(emptyConsumer, never()).accept(any());
verify(nonEmptyConsumer).accept(same(mOpContext));
@@ -171,7 +200,7 @@
@Test
public void testUpdate() throws RemoteException {
- mListener.onDozeChanged(false);
+ mListener.onDozeChanged(false /* isDozing */, false /* isAwake */);
OperationContext context = mProvider.updateContext(mOpContext, false /* crypto */);
// default state when nothing has been set
@@ -186,7 +215,7 @@
final int id = 40 + type;
final boolean aod = (type & 1) == 0;
- mListener.onDozeChanged(aod);
+ mListener.onDozeChanged(aod /* isDozing */, false /* isAwake */);
mSessionListener.onSessionStarted(type, InstanceId.fakeInstanceId(id));
context = mProvider.updateContext(mOpContext, false /* crypto */);
assertThat(context).isSameInstanceAs(mOpContext);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
index 0b8e8ad..60dc2eb 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
@@ -232,7 +232,7 @@
public void testALSCallback() {
mLogger = createLogger();
final CallbackWithProbe<Probe> callback =
- mLogger.createALSCallback(true /* startWithClient */);
+ mLogger.getAmbientLightProbe(true /* startWithClient */);
callback.onClientStarted(mClient);
verify(mSensorManager).registerListener(any(), any(), anyInt());
@@ -242,10 +242,37 @@
}
@Test
+ public void testALSCallbackWhenLogsDisabled() {
+ mLogger = createLogger();
+ mLogger.disableMetrics();
+ final CallbackWithProbe<Probe> callback =
+ mLogger.getAmbientLightProbe(true /* startWithClient */);
+
+ callback.onClientStarted(mClient);
+ verify(mSensorManager, never()).registerListener(any(), any(), anyInt());
+
+ callback.onClientFinished(mClient, true /* success */);
+ verify(mSensorManager, never()).unregisterListener(any(SensorEventListener.class));
+ }
+
+ @Test
+ public void testALSCallbackWhenDisabledAfterStarting() {
+ mLogger = createLogger();
+ final CallbackWithProbe<Probe> callback =
+ mLogger.getAmbientLightProbe(true /* startWithClient */);
+
+ callback.onClientStarted(mClient);
+ verify(mSensorManager).registerListener(any(), any(), anyInt());
+
+ mLogger.disableMetrics();
+ verify(mSensorManager).unregisterListener(any(SensorEventListener.class));
+ }
+
+ @Test
public void testALSCallbackDoesNotStart() {
mLogger = createLogger();
final CallbackWithProbe<Probe> callback =
- mLogger.createALSCallback(false /* startWithClient */);
+ mLogger.getAmbientLightProbe(false /* startWithClient */);
callback.onClientStarted(mClient);
callback.onClientFinished(mClient, true /* success */);
@@ -256,7 +283,7 @@
public void testALSCallbackDestroyed() {
mLogger = createLogger();
final CallbackWithProbe<Probe> callback =
- mLogger.createALSCallback(true /* startWithClient */);
+ mLogger.getAmbientLightProbe(true /* startWithClient */);
callback.onClientStarted(mClient);
callback.onClientFinished(mClient, false /* success */);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java
index 5f88c99..5076915 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java
@@ -24,7 +24,8 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.hardware.biometrics.BiometricStateListener;
+import android.hardware.biometrics.IBiometricStateListener;
+import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
@@ -45,36 +46,46 @@
private BiometricStateCallback mCallback;
@Mock
- BiometricStateListener mBiometricStateListener;
+ private IBiometricStateListener.Stub mBiometricStateListener;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ when(mBiometricStateListener.asBinder()).thenReturn(mBiometricStateListener);
+
mCallback = new BiometricStateCallback();
mCallback.registerBiometricStateListener(mBiometricStateListener);
}
@Test
- public void testNoEnrollmentsToEnrollments_callbackNotified() {
+ public void testNoEnrollmentsToEnrollments_callbackNotified() throws RemoteException {
testEnrollmentCallback(true /* changed */, true /* isNowEnrolled */,
true /* expectCallback */, true /* expectedCallbackValue */);
}
@Test
- public void testEnrollmentsToNoEnrollments_callbackNotified() {
+ public void testEnrollmentsToNoEnrollments_callbackNotified() throws RemoteException {
testEnrollmentCallback(true /* changed */, false /* isNowEnrolled */,
true /* expectCallback */, false /* expectedCallbackValue */);
}
@Test
- public void testEnrollmentsToEnrollments_callbackNotNotified() {
+ public void testEnrollmentsToEnrollments_callbackNotNotified() throws RemoteException {
testEnrollmentCallback(false /* changed */, true /* isNowEnrolled */,
false /* expectCallback */, false /* expectedCallbackValue */);
}
+ @Test
+ public void testBinderDeath() throws RemoteException {
+ mCallback.binderDied(mBiometricStateListener.asBinder());
+
+ testEnrollmentCallback(true /* changed */, false /* isNowEnrolled */,
+ false /* expectCallback */, false /* expectedCallbackValue */);
+ }
+
private void testEnrollmentCallback(boolean changed, boolean isNowEnrolled,
- boolean expectCallback, boolean expectedCallbackValue) {
+ boolean expectCallback, boolean expectedCallbackValue) throws RemoteException {
EnrollClient<?> client = mock(EnrollClient.class);
final int userId = 10;
@@ -96,7 +107,7 @@
}
@Test
- public void testAuthentication_enrollmentCallbackNeverNotified() {
+ public void testAuthentication_enrollmentCallbackNeverNotified() throws RemoteException {
AuthenticationClient<?> client = mock(AuthenticationClient.class);
mCallback.onClientFinished(client, true /* success */);
verify(mBiometricStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
index ea1e49d..dea4d4f 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
@@ -26,8 +26,8 @@
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.same;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -53,6 +53,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.internal.R;
import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.log.CallbackWithProbe;
@@ -88,10 +89,13 @@
private static final int TOUCH_Y = 20;
private static final float TOUCH_MAJOR = 4.4f;
private static final float TOUCH_MINOR = 5.5f;
+ private static final int FINGER_UP = 111;
@Rule
public final TestableContext mContext = new TestableContext(
InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
@Mock
private ISession mHal;
@@ -129,16 +133,12 @@
private ArgumentCaptor<PointerContext> mPointerContextCaptor;
@Captor
private ArgumentCaptor<Consumer<OperationContext>> mContextInjector;
-
- private TestLooper mLooper = new TestLooper();
-
- @Rule
- public final MockitoRule mockito = MockitoJUnit.rule();
+ private final TestLooper mLooper = new TestLooper();
@Before
public void setup() {
mContext.addMockSystemService(BiometricManager.class, mBiometricManager);
- when(mBiometricLogger.createALSCallback(anyBoolean())).thenAnswer(i ->
+ when(mBiometricLogger.getAmbientLightProbe(anyBoolean())).thenAnswer(i ->
new CallbackWithProbe<>(mLuxProbe, i.getArgument(0)));
when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer(
i -> i.getArgument(0));
@@ -214,21 +214,41 @@
}
@Test
- public void luxProbeWhenFingerDown() throws RemoteException {
+ public void luxProbeWhenAwake() throws RemoteException {
+ when(mBiometricContext.isAwake()).thenReturn(false, true, false);
+ when(mBiometricContext.isAod()).thenReturn(false);
final FingerprintAuthenticationClient client = createClient();
client.start(mCallback);
- client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
- verify(mLuxProbe).enable();
+ verify(mHal).authenticateWithContext(eq(OP_ID), mOperationContextCaptor.capture());
+ OperationContext opContext = mOperationContextCaptor.getValue();
+ verify(mBiometricContext).subscribe(eq(opContext), mContextInjector.capture());
- client.onAcquired(2, 0);
+ mContextInjector.getValue().accept(opContext);
+ verify(mLuxProbe, never()).enable();
+
+ reset(mLuxProbe);
+ mContextInjector.getValue().accept(opContext);
+ verify(mLuxProbe).enable();
verify(mLuxProbe, never()).disable();
- client.onPointerUp();
+ mContextInjector.getValue().accept(opContext);
verify(mLuxProbe).disable();
+ }
- client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
- verify(mLuxProbe, times(2)).enable();
+ @Test
+ public void luxProbeDisabledOnAod() throws RemoteException {
+ when(mBiometricContext.isAwake()).thenReturn(false);
+ when(mBiometricContext.isAod()).thenReturn(true);
+ final FingerprintAuthenticationClient client = createClient();
+ client.start(mCallback);
+
+ verify(mHal).authenticateWithContext(eq(OP_ID), mOperationContextCaptor.capture());
+ OperationContext opContext = mOperationContextCaptor.getValue();
+ verify(mBiometricContext).subscribe(eq(opContext), mContextInjector.capture());
+
+ mContextInjector.getValue().accept(opContext);
+ verify(mLuxProbe, never()).enable();
}
@Test
@@ -358,16 +378,97 @@
final FingerprintAuthenticationClient client = createClient(1);
client.start(mCallback);
client.onPowerPressed();
+ mLooper.dispatchAll();
mLooper.moveTimeForward(1000);
mLooper.dispatchAll();
client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */),
true /* authenticated */, new ArrayList<>());
+ mLooper.dispatchAll();
mLooper.moveTimeForward(1000);
mLooper.dispatchAll();
verify(mCallback).onClientFinished(any(), eq(true));
}
+ @Test
+ public void sideFingerprintDoesntSendAuthImmediately() throws Exception {
+ when(mSensorProps.isAnySidefpsType()).thenReturn(true);
+
+ final FingerprintAuthenticationClient client = createClient(1);
+ client.start(mCallback);
+ mLooper.dispatchAll();
+ client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */),
+ true /* authenticated */, new ArrayList<>());
+ mLooper.dispatchAll();
+
+ verify(mCallback, never()).onClientFinished(any(), anyBoolean());
+ }
+
+ @Test
+ public void sideFingerprintSkipsWindowIfFingerUp() throws Exception {
+ when(mSensorProps.isAnySidefpsType()).thenReturn(true);
+
+ mContext.getOrCreateTestableResources().addOverride(
+ R.integer.config_sidefpsSkipWaitForPowerAcquireMessage, FINGER_UP);
+
+ final FingerprintAuthenticationClient client = createClient(1);
+ client.start(mCallback);
+ mLooper.dispatchAll();
+ client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */),
+ true /* authenticated */, new ArrayList<>());
+ client.onAcquired(FINGER_UP, 0);
+ mLooper.dispatchAll();
+
+ verify(mCallback).onClientFinished(any(), eq(true));
+ }
+
+ @Test
+ public void sideFingerprintSendsAuthIfFingerUp() throws Exception {
+ when(mSensorProps.isAnySidefpsType()).thenReturn(true);
+
+ mContext.getOrCreateTestableResources().addOverride(
+ R.integer.config_sidefpsSkipWaitForPowerAcquireMessage, FINGER_UP);
+
+ final FingerprintAuthenticationClient client = createClient(1);
+ client.start(mCallback);
+ mLooper.dispatchAll();
+ client.onAcquired(FINGER_UP, 0);
+ client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */),
+ true /* authenticated */, new ArrayList<>());
+ mLooper.dispatchAll();
+
+ verify(mCallback).onClientFinished(any(), eq(true));
+ }
+
+ @Test
+ public void sideFingerprintShortCircuitExpires() throws Exception {
+ when(mSensorProps.isAnySidefpsType()).thenReturn(true);
+
+ final int timeBeforeAuthSent = 500;
+
+ mContext.getOrCreateTestableResources().addOverride(
+ R.integer.config_sidefpsKeyguardPowerPressWindow, timeBeforeAuthSent);
+ mContext.getOrCreateTestableResources().addOverride(
+ R.integer.config_sidefpsSkipWaitForPowerAcquireMessage, FINGER_UP);
+
+ final FingerprintAuthenticationClient client = createClient(1);
+ client.start(mCallback);
+ mLooper.dispatchAll();
+ client.onAcquired(FINGER_UP, 0);
+ mLooper.dispatchAll();
+
+ mLooper.moveTimeForward(500);
+ mLooper.dispatchAll();
+ client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */),
+ true /* authenticated */, new ArrayList<>());
+ mLooper.dispatchAll();
+ verify(mCallback, never()).onClientFinished(any(), anyBoolean());
+
+ mLooper.moveTimeForward(500);
+ mLooper.dispatchAll();
+ verify(mCallback).onClientFinished(any(), eq(true));
+ }
+
private FingerprintAuthenticationClient createClient() throws RemoteException {
return createClient(100 /* version */, true /* allowBackgroundAuthentication */);
}
@@ -388,11 +489,13 @@
final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
return new FingerprintAuthenticationClient(mContext, () -> aidl, mToken,
REQUEST_ID, mClientMonitorCallbackConverter, 5 /* targetUserId */, OP_ID,
- false /* restricted */, "test-owner", 4 /* cookie */, false /* requireConfirmation */,
- 9 /* sensorId */, mBiometricLogger, mBiometricContext,
- true /* isStrongBiometric */,
- null /* taskStackListener */, mLockoutCache,
- mUdfpsOverlayController, mSideFpsController, allowBackgroundAuthentication, mSensorProps,
+ false /* restricted */, "test-owner", 4 /* cookie */,
+ false /* requireConfirmation */,
+ 9 /* sensorId */, mBiometricLogger, mBiometricContext,
+ true /* isStrongBiometric */,
+ null /* taskStackListener */, mLockoutCache,
+ mUdfpsOverlayController, mSideFpsController, allowBackgroundAuthentication,
+ mSensorProps,
new Handler(mLooper.getLooper())) {
@Override
protected ActivityTaskManager getActivityTaskManager() {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
index f77eb0b..92e1f27a 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
@@ -64,6 +64,7 @@
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.util.ArrayList;
import java.util.function.Consumer;
@Presubmit
@@ -119,7 +120,7 @@
@Before
public void setup() {
- when(mBiometricLogger.createALSCallback(anyBoolean())).thenAnswer(i ->
+ when(mBiometricLogger.getAmbientLightProbe(anyBoolean())).thenAnswer(i ->
new CallbackWithProbe<>(mLuxProbe, i.getArgument(0)));
when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer(
i -> i.getArgument(0));
@@ -196,21 +197,22 @@
}
@Test
- public void luxProbeWhenFingerDown() throws RemoteException {
+ public void luxProbeWhenStarted() throws RemoteException {
final FingerprintEnrollClient client = createClient();
client.start(mCallback);
- client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
verify(mLuxProbe).enable();
client.onAcquired(2, 0);
- verify(mLuxProbe, never()).disable();
-
client.onPointerUp();
- verify(mLuxProbe).disable();
-
client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
- verify(mLuxProbe, times(2)).enable();
+ verify(mLuxProbe, never()).disable();
+ verify(mLuxProbe, never()).destroy();
+
+ client.onEnrollResult(new Fingerprint("f", 30 /* fingerId */, 14 /* deviceId */),
+ 0 /* remaining */);
+
+ verify(mLuxProbe).destroy();
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index c80547c..cc2cdba 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -35,6 +35,7 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
@@ -110,6 +111,12 @@
private static final String GOOGLE_MAPS_PACKAGE_NAME = "com.google.android.apps.maps";
private static final String DEVICE_NAME = "device name";
private static final int DISPLAY_ID = 2;
+ private static final int UID_1 = 0;
+ private static final int UID_2 = 10;
+ private static final int UID_3 = 10000;
+ private static final int UID_4 = 10001;
+ private static final int ASSOCIATION_ID_1 = 1;
+ private static final int ASSOCIATION_ID_2 = 2;
private static final int PRODUCT_ID = 10;
private static final int VENDOR_ID = 5;
private static final String UNIQUE_ID = "uniqueid";
@@ -124,6 +131,8 @@
private VirtualDeviceImpl mDeviceImpl;
private InputController mInputController;
private AssociationInfo mAssociationInfo;
+ private VirtualDeviceManagerService mVdms;
+ private VirtualDeviceManagerInternal mLocalService;
@Mock
private InputController.NativeWrapper mNativeWrapperMock;
@Mock
@@ -139,6 +148,10 @@
@Mock
private Consumer<ArraySet<Integer>> mRunningAppsChangedCallback;
@Mock
+ private VirtualDeviceManagerInternal.VirtualDisplayListener mDisplayListener;
+ @Mock
+ private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener mAppsOnVirtualDeviceListener;
+ @Mock
IPowerManager mIPowerManagerMock;
@Mock
IThermalService mIThermalServiceMock;
@@ -215,6 +228,9 @@
mAssociationInfo = new AssociationInfo(1, 0, null,
MacAddress.BROADCAST_ADDRESS, "", null, true, false, false, 0, 0);
+ mVdms = new VirtualDeviceManagerService(mContext);
+ mLocalService = mVdms.getLocalServiceInstance();
+
VirtualDeviceParams params = new VirtualDeviceParams
.Builder()
.setBlockedActivities(getBlockedActivities())
@@ -235,13 +251,83 @@
}
@Test
+ public void onVirtualDisplayCreatedLocked_listenersNotified() {
+ mLocalService.registerVirtualDisplayListener(mDisplayListener);
+
+ mLocalService.onVirtualDisplayCreated(DISPLAY_ID);
+ TestableLooper.get(this).processAllMessages();
+
+ verify(mDisplayListener).onVirtualDisplayCreated(DISPLAY_ID);
+ }
+
+ @Test
+ public void onVirtualDisplayRemovedLocked_listenersNotified() {
+ mLocalService.registerVirtualDisplayListener(mDisplayListener);
+ mDeviceImpl.onVirtualDisplayCreatedLocked(
+ mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
+
+ mLocalService.onVirtualDisplayRemoved(mDeviceImpl, DISPLAY_ID);
+ TestableLooper.get(this).processAllMessages();
+
+ verify(mDisplayListener).onVirtualDisplayRemoved(DISPLAY_ID);
+ }
+
+ @Test
+ public void onAppsOnVirtualDeviceChanged_singleVirtualDevice_listenersNotified() {
+ ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2));
+ mLocalService.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener);
+
+ mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_1, uids);
+ TestableLooper.get(this).processAllMessages();
+
+ verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged(uids);
+ }
+
+ @Test
+ public void onAppsOnVirtualDeviceChanged_multipleVirtualDevices_listenersNotified() {
+ ArraySet<Integer> uidsOnDevice1 = new ArraySet<>(Arrays.asList(UID_1, UID_2));
+ ArraySet<Integer> uidsOnDevice2 = new ArraySet<>(Arrays.asList(UID_3, UID_4));
+ mLocalService.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener);
+
+ // Notifies that the running apps on the first virtual device has changed.
+ mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_1, uidsOnDevice1);
+ TestableLooper.get(this).processAllMessages();
+ verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged(
+ new ArraySet<>(Arrays.asList(UID_1, UID_2)));
+
+ // Notifies that the running apps on the second virtual device has changed.
+ mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_2, uidsOnDevice2);
+ TestableLooper.get(this).processAllMessages();
+ // The union of the apps running on both virtual devices are sent to the listeners.
+ verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged(
+ new ArraySet<>(Arrays.asList(UID_1, UID_2, UID_3, UID_4)));
+
+ // Notifies that the running apps on the first virtual device has changed again.
+ uidsOnDevice1.remove(UID_2);
+ mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_1, uidsOnDevice1);
+ mLocalService.onAppsOnVirtualDeviceChanged();
+ TestableLooper.get(this).processAllMessages();
+ // The union of the apps running on both virtual devices are sent to the listeners.
+ verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged(
+ new ArraySet<>(Arrays.asList(UID_1, UID_3, UID_4)));
+
+ // Notifies that the running apps on the first virtual device has changed but with the same
+ // set of UIDs.
+ mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_1, uidsOnDevice1);
+ mLocalService.onAppsOnVirtualDeviceChanged();
+ TestableLooper.get(this).processAllMessages();
+ // Listeners should not be notified.
+ verifyNoMoreInteractions(mAppsOnVirtualDeviceListener);
+ }
+
+ @Test
public void onVirtualDisplayCreatedLocked_wakeLockIsAcquired() throws RemoteException {
verify(mIPowerManagerMock, never()).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
nullable(String.class), anyInt(), eq(null));
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
- verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(),
+ verify(mIPowerManagerMock).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
nullable(String.class), eq(DISPLAY_ID), eq(null));
}
@@ -255,7 +341,7 @@
assertThrows(IllegalStateException.class,
() -> mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID));
TestableLooper.get(this).processAllMessages();
- verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(),
+ verify(mIPowerManagerMock).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
nullable(String.class), eq(DISPLAY_ID), eq(null));
}
@@ -273,14 +359,14 @@
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class);
TestableLooper.get(this).processAllMessages();
- verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(),
+ verify(mIPowerManagerMock).acquireWakeLock(wakeLockCaptor.capture(),
anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
nullable(String.class), eq(DISPLAY_ID), eq(null));
IBinder wakeLock = wakeLockCaptor.getValue();
mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID);
- verify(mIPowerManagerMock, Mockito.times(1)).releaseWakeLock(eq(wakeLock), anyInt());
+ verify(mIPowerManagerMock).releaseWakeLock(eq(wakeLock), anyInt());
}
@Test
@@ -289,7 +375,7 @@
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class);
TestableLooper.get(this).processAllMessages();
- verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(),
+ verify(mIPowerManagerMock).acquireWakeLock(wakeLockCaptor.capture(),
anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
nullable(String.class), eq(DISPLAY_ID), eq(null));
@@ -297,7 +383,7 @@
// Close the VirtualDevice without first notifying it of the VirtualDisplay removal.
mDeviceImpl.close();
- verify(mIPowerManagerMock, Mockito.times(1)).releaseWakeLock(eq(wakeLock), anyInt());
+ verify(mIPowerManagerMock).releaseWakeLock(eq(wakeLock), anyInt());
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/dreams/DreamServiceTest.java b/services/tests/servicestests/src/com/android/server/dreams/DreamServiceTest.java
index 74d2e0f..0efd296 100644
--- a/services/tests/servicestests/src/com/android/server/dreams/DreamServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/dreams/DreamServiceTest.java
@@ -16,7 +16,8 @@
package com.android.server.dreams;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertFalse;
import android.content.ComponentName;
@@ -35,21 +36,36 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class DreamServiceTest {
+ private static final String TEST_PACKAGE_NAME = "com.android.frameworks.servicestests";
+
@Test
public void testMetadataParsing() throws PackageManager.NameNotFoundException {
- final String testPackageName = "com.android.frameworks.servicestests";
final String testDreamClassName = "com.android.server.dreams.TestDreamService";
- final String testSettingsActivity = "com.android.server.dreams/.TestDreamSettingsActivity";
+ final String testSettingsActivity =
+ "com.android.frameworks.servicestests/.TestDreamSettingsActivity";
+ final DreamService.DreamMetadata metadata = getDreamMetadata(testDreamClassName);
- final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
-
- final ServiceInfo si = context.getPackageManager().getServiceInfo(
- new ComponentName(testPackageName, testDreamClassName),
- PackageManager.ComponentInfoFlags.of(PackageManager.GET_META_DATA));
- final DreamService.DreamMetadata metadata = DreamService.getDreamMetadata(context, si);
-
- assertEquals(0, metadata.settingsActivity.compareTo(
- ComponentName.unflattenFromString(testSettingsActivity)));
+ assertThat(metadata.settingsActivity).isEqualTo(
+ ComponentName.unflattenFromString(testSettingsActivity));
assertFalse(metadata.showComplications);
}
+
+ @Test
+ public void testMetadataParsing_invalidSettingsActivity()
+ throws PackageManager.NameNotFoundException {
+ final String testDreamClassName =
+ "com.android.server.dreams.TestDreamServiceWithInvalidSettings";
+ final DreamService.DreamMetadata metadata = getDreamMetadata(testDreamClassName);
+
+ assertThat(metadata.settingsActivity).isNull();
+ }
+
+ private DreamService.DreamMetadata getDreamMetadata(String dreamClassName)
+ throws PackageManager.NameNotFoundException {
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ final ServiceInfo si = context.getPackageManager().getServiceInfo(
+ new ComponentName(TEST_PACKAGE_NAME, dreamClassName),
+ PackageManager.ComponentInfoFlags.of(PackageManager.GET_META_DATA));
+ return DreamService.getDreamMetadata(context, si);
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java b/services/tests/servicestests/src/com/android/server/dreams/TestDreamServiceWithInvalidSettings.java
similarity index 62%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
rename to services/tests/servicestests/src/com/android/server/dreams/TestDreamServiceWithInvalidSettings.java
index e62a63a..5c7d02f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeConstants.java
+++ b/services/tests/servicestests/src/com/android/server/dreams/TestDreamServiceWithInvalidSettings.java
@@ -14,18 +14,12 @@
* limitations under the License.
*/
-package com.android.wm.shell.desktopmode;
+package com.android.server.dreams;
-import android.os.SystemProperties;
+import android.service.dreams.DreamService;
/**
- * Constants for desktop mode feature
+ * Dream service implementation for unit testing, where the settings activity is invalid.
*/
-public class DesktopModeConstants {
-
- /**
- * Flag to indicate whether desktop mode is available on the device
- */
- public static final boolean IS_FEATURE_ENABLED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode", false);
+public class TestDreamServiceWithInvalidSettings extends DreamService {
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 34b40c7..b1ad8ec 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -16,53 +16,79 @@
package com.android.server.pm;
+import static android.os.UserManager.DISALLOW_USER_SWITCH;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.ActivityManager;
+import android.app.PropertyInvalidatedCache;
+import android.content.Context;
import android.content.pm.UserInfo;
import android.os.Bundle;
import android.os.FileUtils;
+import android.os.Looper;
import android.os.Parcelable;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.Postsubmit;
import android.support.test.uiautomator.UiDevice;
-import android.test.AndroidTestCase;
-import android.text.TextUtils;
import android.util.AtomicFile;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.LocalServices;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
+/** Test {@link UserManagerService} functionality. */
@Postsubmit
-@SmallTest
-public class UserManagerServiceTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class UserManagerServiceTest {
private static String[] STRING_ARRAY = new String[] {"<tag", "<![CDATA["};
private File restrictionsFile;
private int tempUserId = UserHandle.USER_NULL;
+ private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ private UserManagerService mUserManagerService;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setup() throws Exception {
+ // Currently UserManagerService cannot be instantiated twice inside a VM without a cleanup
+ // TODO: Remove once UMS supports proper dependency injection
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+ // Disable binder caches in this process.
+ PropertyInvalidatedCache.disableForTestMode();
+
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ mUserManagerService = new UserManagerService(InstrumentationRegistry.getContext());
+
restrictionsFile = new File(mContext.getCacheDir(), "restrictions.xml");
restrictionsFile.delete();
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void teardown() throws Exception {
restrictionsFile.delete();
if (tempUserId != UserHandle.USER_NULL) {
UserManager.get(mContext).removeUser(tempUserId);
}
- super.tearDown();
}
+ @Test
public void testWriteReadApplicationRestrictions() throws IOException {
AtomicFile atomicFile = new AtomicFile(restrictionsFile);
Bundle bundle = createBundle();
UserManagerService.writeApplicationRestrictionsLAr(bundle, atomicFile);
- assertTrue(atomicFile.getBaseFile().exists());
+ assertThat(atomicFile.getBaseFile().exists()).isTrue();
String s = FileUtils.readTextFile(restrictionsFile, 10000, "");
System.out.println("restrictionsFile: " + s);
bundle = UserManagerService.readApplicationRestrictionsLAr(atomicFile);
@@ -70,22 +96,22 @@
assertBundle(bundle);
}
+ @Test
public void testAddUserWithAccount() {
UserManager um = UserManager.get(mContext);
UserInfo user = um.createUser("Test User", 0);
- assertNotNull(user);
+ assertThat(user).isNotNull();
tempUserId = user.id;
String accountName = "Test Account";
um.setUserAccount(tempUserId, accountName);
- assertEquals(accountName, um.getUserAccount(tempUserId));
+ assertThat(um.getUserAccount(tempUserId)).isEqualTo(accountName);
}
+ @Test
public void testUserSystemPackageWhitelist() throws Exception {
String cmd = "cmd user report-system-user-package-whitelist-problems --critical-only";
final String result = runShellCommand(cmd);
- if (!TextUtils.isEmpty(result)) {
- fail("Command '" + cmd + " reported errors:\n" + result);
- }
+ assertThat(result).isEmpty();
}
private Bundle createBundle() {
@@ -114,26 +140,141 @@
}
private void assertBundle(Bundle bundle) {
- assertFalse(bundle.getBoolean("boolean_0"));
- assertTrue(bundle.getBoolean("boolean_1"));
- assertEquals(100, bundle.getInt("integer"));
- assertEquals("", bundle.getString("empty"));
- assertEquals("text", bundle.getString("string"));
- assertEquals(Arrays.asList(STRING_ARRAY), Arrays.asList(bundle.getStringArray("string[]")));
+ assertThat(bundle.getBoolean("boolean_0")).isFalse();
+ assertThat(bundle.getBoolean("boolean_1")).isTrue();
+ assertThat(bundle.getInt("integer")).isEqualTo(100);
+ assertThat(bundle.getString("empty")).isEqualTo("");
+ assertThat(bundle.getString("string")).isEqualTo("text");
+ assertThat(Arrays.asList(bundle.getStringArray("string[]")))
+ .isEqualTo(Arrays.asList(STRING_ARRAY));
Parcelable[] bundle_array = bundle.getParcelableArray("bundle_array");
- assertEquals(2, bundle_array.length);
+ assertThat(bundle_array.length).isEqualTo(2);
Bundle bundle1 = (Bundle) bundle_array[0];
- assertEquals("bundle_array_string", bundle1.getString("bundle_array_string"));
- assertNotNull(bundle1.getBundle("bundle_array_bundle"));
+ assertThat(bundle1.getString("bundle_array_string"))
+ .isEqualTo("bundle_array_string");
+ assertThat(bundle1.getBundle("bundle_array_bundle")).isNotNull();
Bundle bundle2 = (Bundle) bundle_array[1];
- assertEquals("bundle_array_string2", bundle2.getString("bundle_array_string2"));
+ assertThat(bundle2.getString("bundle_array_string2"))
+ .isEqualTo("bundle_array_string2");
Bundle childBundle = bundle.getBundle("bundle");
- assertEquals("bundle_string", childBundle.getString("bundle_string"));
- assertEquals(1, childBundle.getInt("bundle_int"));
+ assertThat(childBundle.getString("bundle_string"))
+ .isEqualTo("bundle_string");
+ assertThat(childBundle.getInt("bundle_int")).isEqualTo(1);
}
+ @Test
+ public void assertHasUserRestriction() throws Exception {
+ int userId = ActivityManager.getCurrentUser();
+
+ mUserManagerService.setUserRestriction(DISALLOW_USER_SWITCH, true, userId);
+ assertThat(mUserManagerService.hasUserRestriction(DISALLOW_USER_SWITCH, userId)).isTrue();
+
+ mUserManagerService.setUserRestriction(DISALLOW_USER_SWITCH, false, userId);
+ assertThat(mUserManagerService.hasUserRestriction(DISALLOW_USER_SWITCH, userId)).isFalse();
+ }
+
+ @Test
+ public void assertIsUserSwitcherEnabledOnMultiUserSettings() throws Exception {
+ int userId = ActivityManager.getCurrentUser();
+ resetUserSwitcherEnabled();
+
+ setUserSwitch(false);
+ assertThat(mUserManagerService.isUserSwitcherEnabled(userId)).isFalse();
+
+ setUserSwitch(true);
+ assertThat(mUserManagerService.isUserSwitcherEnabled(userId)).isTrue();
+ }
+
+ @Test
+ public void assertIsUserSwitcherEnabledOnMaxSupportedUsers() throws Exception {
+ int userId = ActivityManager.getCurrentUser();
+ setMaxSupportedUsers(1);
+
+ assertThat(UserManager.supportsMultipleUsers()).isFalse();
+ assertThat(mUserManagerService.isUserSwitcherEnabled(userId)).isFalse();
+
+ setMaxSupportedUsers(8);
+
+ assertThat(UserManager.supportsMultipleUsers()).isTrue();
+ assertThat(mUserManagerService.isUserSwitcherEnabled(userId)).isTrue();
+ }
+
+
+ @Test
+ public void assertIsUserSwitcherEnabledOnShowMultiuserUI() throws Exception {
+ int userId = ActivityManager.getCurrentUser();
+ setShowMultiuserUI(false);
+
+ assertThat(UserManager.supportsMultipleUsers()).isFalse();
+ assertThat(mUserManagerService.isUserSwitcherEnabled(userId)).isFalse();
+
+ setShowMultiuserUI(true);
+
+ assertThat(UserManager.supportsMultipleUsers()).isTrue();
+ assertThat(mUserManagerService.isUserSwitcherEnabled(userId)).isTrue();
+ }
+
+ @Test
+ public void assertIsUserSwitcherEnabledOnUserRestrictions() throws Exception {
+ int userId = ActivityManager.getCurrentUser();
+ resetUserSwitcherEnabled();
+
+ mUserManagerService.setUserRestriction(DISALLOW_USER_SWITCH, true, userId);
+ assertThat(mUserManagerService.isUserSwitcherEnabled(userId)).isFalse();
+
+ mUserManagerService.setUserRestriction(DISALLOW_USER_SWITCH, false, userId);
+ assertThat(mUserManagerService.isUserSwitcherEnabled(userId)).isTrue();
+ }
+
+ @Test
+ public void assertIsUserSwitcherEnabledOnDemoMode() throws Exception {
+ int userId = ActivityManager.getCurrentUser();
+ resetUserSwitcherEnabled();
+
+ setDeviceDemoMode(true);
+ assertThat(mUserManagerService.isUserSwitcherEnabled(userId)).isFalse();
+
+ setDeviceDemoMode(false);
+ assertThat(mUserManagerService.isUserSwitcherEnabled(userId)).isTrue();
+ }
+
+ private void resetUserSwitcherEnabled() throws Exception {
+ int userId = ActivityManager.getCurrentUser();
+ setUserSwitch(true);
+ setShowMultiuserUI(true);
+ setDeviceDemoMode(false);
+ setMaxSupportedUsers(8);
+ mUserManagerService.setUserRestriction(DISALLOW_USER_SWITCH, false, userId);
+ }
+
+ private void setUserSwitch(boolean enabled) {
+ android.provider.Settings.Global.putInt(mContext.getContentResolver(),
+ android.provider.Settings.Global.USER_SWITCHER_ENABLED, enabled ? 1 : 0);
+ }
+
+ private void setDeviceDemoMode(boolean enabled) {
+ android.provider.Settings.Global.putInt(mContext.getContentResolver(),
+ android.provider.Settings.Global.DEVICE_DEMO_MODE, enabled ? 1 : 0);
+ }
+
+
private static String runShellCommand(String cmd) throws Exception {
return UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
.executeShellCommand(cmd);
}
+
+ private static String setSystemProperty(String name, String value) throws Exception {
+ final String oldValue = runShellCommand("getprop " + name);
+ assertThat(runShellCommand("setprop " + name + " " + value))
+ .isEqualTo("");
+ return oldValue;
+ }
+
+ private static void setMaxSupportedUsers(int max) throws Exception {
+ setSystemProperty("fw.max_users", String.valueOf(max));
+ }
+
+ public static void setShowMultiuserUI(boolean show) throws Exception {
+ setSystemProperty("fw.show_multiuserui", String.valueOf(show));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
index 4ef6530..aafbb11 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -66,12 +66,15 @@
import android.os.vibrator.VibrationConfig;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
+import android.util.ArraySet;
+import android.view.Display;
import androidx.test.InstrumentationRegistry;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
import com.android.server.LocalServices;
+import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
import org.junit.After;
import org.junit.Before;
@@ -95,6 +98,7 @@
public class VibrationSettingsTest {
private static final int UID = 1;
+ private static final int VIRTUAL_DISPLAY_ID = 1;
private static final String SYSUI_PACKAGE_NAME = "sysui";
private static final PowerSaveState NORMAL_POWER_STATE = new PowerSaveState.Builder().build();
private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder()
@@ -117,15 +121,23 @@
@Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
@Mock private VibrationSettings.OnVibratorSettingsChanged mListenerMock;
- @Mock private PowerManagerInternal mPowerManagerInternalMock;
- @Mock private PackageManagerInternal mPackageManagerInternalMock;
- @Mock private VibrationConfig mVibrationConfigMock;
+ @Mock
+ private PowerManagerInternal mPowerManagerInternalMock;
+ @Mock
+ private VirtualDeviceManagerInternal mVirtualDeviceManagerInternalMock;
+ @Mock
+ private PackageManagerInternal mPackageManagerInternalMock;
+ @Mock
+ private VibrationConfig mVibrationConfigMock;
private TestLooper mTestLooper;
private ContextWrapper mContextSpy;
private AudioManager mAudioManager;
private VibrationSettings mVibrationSettings;
private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener;
+ private VirtualDeviceManagerInternal.VirtualDisplayListener mRegisteredVirtualDisplayListener;
+ private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener
+ mRegisteredAppsOnVirtualDeviceListener;
@Before
public void setUp() throws Exception {
@@ -140,11 +152,17 @@
}).when(mPowerManagerInternalMock).registerLowPowerModeObserver(any());
when(mPackageManagerInternalMock.getSystemUiServiceComponent())
.thenReturn(new ComponentName(SYSUI_PACKAGE_NAME, ""));
+ doAnswer(invocation -> {
+ mRegisteredVirtualDisplayListener = invocation.getArgument(0);
+ return null;
+ }).when(mVirtualDeviceManagerInternalMock).registerVirtualDisplayListener(any());
+ doAnswer(invocation -> {
+ mRegisteredAppsOnVirtualDeviceListener = invocation.getArgument(0);
+ return null;
+ }).when(mVirtualDeviceManagerInternalMock).registerAppsOnVirtualDeviceListener(any());
- LocalServices.removeServiceForTest(PowerManagerInternal.class);
- LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock);
- LocalServices.removeServiceForTest(PackageManagerInternal.class);
- LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock);
+ removeServicesForTest();
+ addServicesForTest();
setDefaultIntensity(VIBRATION_INTENSITY_MEDIUM);
mAudioManager = mContextSpy.getSystemService(AudioManager.class);
@@ -168,6 +186,18 @@
}
@Test
+ public void create_withOnlyRequiredSystemServices() {
+ // The only core services that we depend on are PowerManager and PackageManager
+ removeServicesForTest();
+ LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock);
+ LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock);
+
+ VibrationSettings minimalVibrationSettings = new VibrationSettings(mContextSpy,
+ new Handler(mTestLooper.getLooper()), mVibrationConfigMock);
+ minimalVibrationSettings.onSystemReady();
+ }
+
+ @Test
public void addListener_settingsChangeTriggerListener() {
mVibrationSettings.addListener(mListenerMock);
@@ -447,6 +477,65 @@
}
@Test
+ public void shouldIgnoreVibrationFromVirtualDisplays_displayNonVirtual_neverIgnored() {
+ // Vibrations from the primary display is never ignored regardless of the creation and
+ // removal of virtual displays and of the changes of apps running on virtual displays.
+ mRegisteredVirtualDisplayListener.onVirtualDisplayCreated(VIRTUAL_DISPLAY_ID);
+ mRegisteredAppsOnVirtualDeviceListener.onAppsOnAnyVirtualDeviceChanged(
+ new ArraySet<>(Arrays.asList(UID)));
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsageAndDisplay(usage, Display.DEFAULT_DISPLAY);
+ }
+
+ mRegisteredVirtualDisplayListener.onVirtualDisplayRemoved(VIRTUAL_DISPLAY_ID);
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsageAndDisplay(usage, Display.DEFAULT_DISPLAY);
+ }
+
+ mRegisteredAppsOnVirtualDeviceListener.onAppsOnAnyVirtualDeviceChanged(new ArraySet<>());
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsageAndDisplay(usage, Display.DEFAULT_DISPLAY);
+ }
+ }
+
+ @Test
+ public void shouldIgnoreVibrationFromVirtualDisplays_displayVirtual() {
+ // Ignore the vibration when the coming display id represents a virtual display.
+ mRegisteredVirtualDisplayListener.onVirtualDisplayCreated(VIRTUAL_DISPLAY_ID);
+
+ for (int usage : ALL_USAGES) {
+ assertVibrationIgnoredForUsageAndDisplay(usage, VIRTUAL_DISPLAY_ID,
+ Vibration.Status.IGNORED_FROM_VIRTUAL_DEVICE);
+ }
+
+ // Stop ignoring when the virtual display is removed.
+ mRegisteredVirtualDisplayListener.onVirtualDisplayRemoved(VIRTUAL_DISPLAY_ID);
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsageAndDisplay(usage, VIRTUAL_DISPLAY_ID);
+ }
+ }
+
+
+ @Test
+ public void shouldIgnoreVibrationFromVirtualDisplays_appsOnVirtualDisplay() {
+ // Ignore when the passed-in display id is invalid and the calling uid is on a virtual
+ // display.
+ mRegisteredAppsOnVirtualDeviceListener.onAppsOnAnyVirtualDeviceChanged(
+ new ArraySet<>(Arrays.asList(UID)));
+ for (int usage : ALL_USAGES) {
+ assertVibrationIgnoredForUsageAndDisplay(usage, Display.INVALID_DISPLAY,
+ Vibration.Status.IGNORED_FROM_VIRTUAL_DEVICE);
+ }
+
+ // Stop ignoring when the app is no longer on virtual display.
+ mRegisteredAppsOnVirtualDeviceListener.onAppsOnAnyVirtualDeviceChanged(new ArraySet<>());
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsageAndDisplay(usage, Display.INVALID_DISPLAY);
+ }
+
+ }
+
+ @Test
public void shouldVibrateInputDevices_returnsSettingsValue() {
setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 1);
assertTrue(mVibrationSettings.shouldVibrateInputDevices());
@@ -479,7 +568,7 @@
@Test
public void shouldCancelVibrationOnScreenOff_withSleepReasonInAllowlist_returnsAlwaysFalse() {
long vibrateStartTime = 100;
- int[] allowedSleepReasons = new int[] {
+ int[] allowedSleepReasons = new int[]{
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE,
};
@@ -646,11 +735,29 @@
assertNotNull(mVibrationSettings.getFallbackEffect(VibrationEffect.EFFECT_DOUBLE_CLICK));
}
+ private void removeServicesForTest() {
+ LocalServices.removeServiceForTest(PowerManagerInternal.class);
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
+ }
+
+ private void addServicesForTest() {
+ LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock);
+ LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock);
+ LocalServices.addService(VirtualDeviceManagerInternal.class,
+ mVirtualDeviceManagerInternalMock);
+ }
+
private void assertVibrationIgnoredForUsage(@VibrationAttributes.Usage int usage,
Vibration.Status expectedStatus) {
+ assertVibrationIgnoredForUsageAndDisplay(usage, Display.DEFAULT_DISPLAY, expectedStatus);
+ }
+
+ private void assertVibrationIgnoredForUsageAndDisplay(@VibrationAttributes.Usage int usage,
+ int displayId, Vibration.Status expectedStatus) {
assertEquals(errorMessageForUsage(usage),
expectedStatus,
- mVibrationSettings.shouldIgnoreVibration(UID,
+ mVibrationSettings.shouldIgnoreVibration(UID, displayId,
VibrationAttributes.createForUsage(usage)));
}
@@ -660,8 +767,20 @@
private void assertVibrationNotIgnoredForUsageAndFlags(@VibrationAttributes.Usage int usage,
@VibrationAttributes.Flag int flags) {
+ assertVibrationNotIgnoredForUsageAndFlagsAndDidsplay(usage, Display.DEFAULT_DISPLAY, flags);
+ }
+
+ private void assertVibrationNotIgnoredForUsageAndDisplay(@VibrationAttributes.Usage int usage,
+ int displayId) {
+ assertVibrationNotIgnoredForUsageAndFlagsAndDidsplay(usage, displayId, /* flags= */ 0);
+ }
+
+ private void assertVibrationNotIgnoredForUsageAndFlagsAndDidsplay(
+ @VibrationAttributes.Usage int usage, int displayId,
+ @VibrationAttributes.Flag int flags) {
assertNull(errorMessageForUsage(usage),
mVibrationSettings.shouldIgnoreVibration(UID,
+ displayId,
new VibrationAttributes.Builder()
.setUsage(usage)
.setFlags(flags)
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 ca162ef..0551bfc 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -94,6 +94,7 @@
private static final int TEST_TIMEOUT_MILLIS = 900;
private static final int UID = Process.ROOT_UID;
+ private static final int DISPLAY_ID = 10;
private static final int VIBRATOR_ID = 1;
private static final String PACKAGE_NAME = "package";
private static final VibrationAttributes ATTRS = new VibrationAttributes.Builder().build();
@@ -1584,7 +1585,8 @@
}
private Vibration createVibration(long id, CombinedVibration effect) {
- return new Vibration(mVibrationToken, (int) id, effect, ATTRS, UID, PACKAGE_NAME, "reason");
+ return new Vibration(mVibrationToken, (int) id, effect, ATTRS, UID, DISPLAY_ID,
+ PACKAGE_NAME, "reason");
}
private SparseArray<VibratorController> createVibratorControllers() {
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 36bec75..fe0a79c 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -76,7 +76,9 @@
import android.os.vibrator.VibrationEffectSegment;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
+import android.util.ArraySet;
import android.util.SparseBooleanArray;
+import android.view.Display;
import android.view.InputDevice;
import androidx.test.InstrumentationRegistry;
@@ -86,6 +88,7 @@
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
import com.android.server.LocalServices;
+import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
import org.junit.After;
import org.junit.Before;
@@ -115,6 +118,7 @@
private static final int TEST_TIMEOUT_MILLIS = 1_000;
private static final int UID = Process.ROOT_UID;
+ private static final int VIRTUAL_DISPLAY_ID = 1;
private static final String PACKAGE_NAME = "package";
private static final PowerSaveState NORMAL_POWER_STATE = new PowerSaveState.Builder().build();
private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder()
@@ -153,6 +157,8 @@
private IBatteryStats mBatteryStatsMock;
@Mock
private VibratorFrameworkStatsLogger mVibratorFrameworkStatsLoggerMock;
+ @Mock
+ private VirtualDeviceManagerInternal mVirtualDeviceManagerInternalMock;
private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>();
@@ -162,6 +168,9 @@
private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener;
private VibratorManagerService.ExternalVibratorService mExternalVibratorService;
private VibrationConfig mVibrationConfig;
+ private VirtualDeviceManagerInternal.VirtualDisplayListener mRegisteredVirtualDisplayListener;
+ private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener
+ mRegisteredAppsOnVirtualDeviceListener;
@Before
public void setUp() throws Exception {
@@ -186,6 +195,14 @@
mRegisteredPowerModeListener = invocation.getArgument(0);
return null;
}).when(mPowerManagerInternalMock).registerLowPowerModeObserver(any());
+ doAnswer(invocation -> {
+ mRegisteredVirtualDisplayListener = invocation.getArgument(0);
+ return null;
+ }).when(mVirtualDeviceManagerInternalMock).registerVirtualDisplayListener(any());
+ doAnswer(invocation -> {
+ mRegisteredAppsOnVirtualDeviceListener = invocation.getArgument(0);
+ return null;
+ }).when(mVirtualDeviceManagerInternalMock).registerAppsOnVirtualDeviceListener(any());
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 1);
@@ -202,6 +219,7 @@
addLocalServiceMock(PackageManagerInternal.class, mPackageManagerInternalMock);
addLocalServiceMock(PowerManagerInternal.class, mPowerManagerInternalMock);
+ addLocalServiceMock(VirtualDeviceManagerInternal.class, mVirtualDeviceManagerInternalMock);
mTestLooper.startAutoDispatch();
}
@@ -1167,6 +1185,64 @@
}
@Test
+ public void vibrate_withVitualDisplayChange_ignoreVibrationFromVirtualDisplay()
+ throws Exception {
+ mockVibrators(1);
+ VibratorManagerService service = createSystemReadyService();
+ mRegisteredVirtualDisplayListener.onVirtualDisplayCreated(VIRTUAL_DISPLAY_ID);
+
+ vibrateWithDisplay(service,
+ VIRTUAL_DISPLAY_ID,
+ CombinedVibration.startParallel()
+ .addVibrator(1, VibrationEffect.createOneShot(1000, 100))
+ .combine(),
+ HAPTIC_FEEDBACK_ATTRS);
+
+ // Haptic feedback ignored when it's from a virtual display.
+ assertFalse(waitUntil(s -> s.isVibrating(1), service, /* timeout= */ 50));
+
+ mRegisteredVirtualDisplayListener.onVirtualDisplayRemoved(VIRTUAL_DISPLAY_ID);
+ vibrateWithDisplay(service,
+ VIRTUAL_DISPLAY_ID,
+ CombinedVibration.startParallel()
+ .addVibrator(1, VibrationEffect.createOneShot(1000, 100))
+ .combine(),
+ HAPTIC_FEEDBACK_ATTRS);
+ // Haptic feedback played normally when the virtual display is removed.
+ assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+
+ }
+
+ @Test
+ public void vibrate_withAppsOnVitualDisplayChange_ignoreVibrationFromVirtualDisplay()
+ throws Exception {
+ mockVibrators(1);
+ VibratorManagerService service = createSystemReadyService();
+ mRegisteredAppsOnVirtualDeviceListener.onAppsOnAnyVirtualDeviceChanged(
+ new ArraySet<>(Arrays.asList(UID)));
+ vibrateWithDisplay(service,
+ Display.INVALID_DISPLAY,
+ CombinedVibration.startParallel()
+ .addVibrator(1, VibrationEffect.createOneShot(1000, 100))
+ .combine(),
+ HAPTIC_FEEDBACK_ATTRS);
+
+ // Haptic feedback ignored when it's from an app running virtual display.
+ assertFalse(waitUntil(s -> s.isVibrating(1), service, /* timeout= */ 50));
+
+ mRegisteredAppsOnVirtualDeviceListener.onAppsOnAnyVirtualDeviceChanged(new ArraySet<>());
+ vibrateWithDisplay(service,
+ Display.INVALID_DISPLAY,
+ CombinedVibration.startParallel()
+ .addVibrator(1, VibrationEffect.createOneShot(1000, 100))
+ .combine(),
+ HAPTIC_FEEDBACK_ATTRS);
+ // Haptic feedback played normally when the same app no long runs on a virtual display.
+ assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+
+ }
+
+ @Test
public void cancelVibrate_withoutUsageFilter_stopsVibrating() throws Exception {
mockVibrators(1);
VibratorManagerService service = createSystemReadyService();
@@ -1240,6 +1316,24 @@
}
@Test
+ public void onExternalVibration_ignoreVibrationFromVirtualDevices() throws Exception {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
+ createSystemReadyService();
+
+ IBinder binderToken = mock(IBinder.class);
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ATTRS,
+ mock(IExternalVibrationController.class), binderToken);
+ int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
+ assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
+
+ mRegisteredAppsOnVirtualDeviceListener.onAppsOnAnyVirtualDeviceChanged(
+ new ArraySet<>(Arrays.asList(UID)));
+ scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
+ assertEquals(IExternalVibratorService.SCALE_MUTE, scale);
+ }
+
+ @Test
public void onExternalVibration_setsExternalControl() throws Exception {
mockVibrators(1);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
@@ -1820,7 +1914,8 @@
private void vibrateAndWaitUntilFinished(VibratorManagerService service,
CombinedVibration effect, VibrationAttributes attrs) throws InterruptedException {
Vibration vib =
- service.vibrateInternal(UID, PACKAGE_NAME, effect, attrs, "some reason", service);
+ service.vibrateInternal(UID, Display.DEFAULT_DISPLAY, PACKAGE_NAME, effect, attrs,
+ "some reason", service);
if (vib != null) {
vib.waitForEnd();
}
@@ -1833,7 +1928,12 @@
private void vibrate(VibratorManagerService service, CombinedVibration effect,
VibrationAttributes attrs) {
- service.vibrate(UID, PACKAGE_NAME, effect, attrs, "some reason", service);
+ vibrateWithDisplay(service, Display.DEFAULT_DISPLAY, effect, attrs);
+ }
+
+ private void vibrateWithDisplay(VibratorManagerService service, int displayId,
+ CombinedVibration effect, VibrationAttributes attrs) {
+ service.vibrate(UID, displayId, PACKAGE_NAME, effect, attrs, "some reason", service);
}
private boolean waitUntil(Predicate<VibratorManagerService> predicate,
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 2128a08..3d6736e 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -20,6 +20,7 @@
],
static_libs: [
+ "frameworks-base-testutils",
"services.accessibility",
"services.core",
"services.devicepolicy",
@@ -32,6 +33,7 @@
"platformprotosnano",
"statsdprotolite",
"hamcrest-library",
+ "servicestests-utils",
"testables",
"truth-prebuilt",
// TODO: remove once Android migrates to JUnit 4.12,
diff --git a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
index aee2755..617a34f 100644
--- a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
@@ -45,6 +45,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.notNull;
+import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
@@ -58,31 +59,36 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.initMocks;
import static org.testng.Assert.assertThrows;
import android.Manifest;
+import android.app.Activity;
import android.app.AlarmManager;
import android.app.IOnProjectionStateChangedListener;
import android.app.IUiModeManager;
import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Process;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
+import android.os.Process;
import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.dreams.DreamManagerInternal;
+import android.test.mock.MockContentResolver;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
@@ -93,6 +99,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import java.time.LocalDateTime;
@@ -107,8 +114,7 @@
private static final String PACKAGE_NAME = "Diane Coffee";
private UiModeManagerService mUiManagerService;
private IUiModeManager mService;
- @Mock
- private ContentResolver mContentResolver;
+ private MockContentResolver mContentResolver;
@Mock
private WindowManagerInternal mWindowManager;
@Mock
@@ -131,16 +137,22 @@
private PackageManager mPackageManager;
@Mock
private IBinder mBinder;
+ @Mock
+ private DreamManagerInternal mDreamManager;
+ @Captor
+ private ArgumentCaptor<Intent> mOrderedBroadcastIntent;
+ @Captor
+ private ArgumentCaptor<BroadcastReceiver> mOrderedBroadcastReceiver;
private BroadcastReceiver mScreenOffCallback;
private BroadcastReceiver mTimeChangedCallback;
+ private BroadcastReceiver mDockStateChangedCallback;
private AlarmManager.OnAlarmListener mCustomListener;
private Consumer<PowerSaveState> mPowerSaveConsumer;
private TwilightListener mTwilightListener;
@Before
public void setUp() {
- initMocks(this);
when(mContext.checkCallingOrSelfPermission(anyString()))
.thenReturn(PackageManager.PERMISSION_GRANTED);
doAnswer(inv -> {
@@ -154,6 +166,10 @@
when(mLocalPowerManager.getLowPowerState(anyInt()))
.thenReturn(new PowerSaveState.Builder().setBatterySaverEnabled(false).build());
when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getString(com.android.internal.R.string.config_somnambulatorComponent))
+ .thenReturn("somnambulator");
+ mContentResolver = new MockContentResolver();
+ mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPowerManager.isInteractive()).thenReturn(true);
@@ -168,6 +184,9 @@
if (filter.hasAction(Intent.ACTION_SCREEN_OFF)) {
mScreenOffCallback = inv.getArgument(0);
}
+ if (filter.hasAction(Intent.ACTION_DOCK_EVENT)) {
+ mDockStateChangedCallback = inv.getArgument(0);
+ }
return null;
});
doAnswer(inv -> {
@@ -182,11 +201,13 @@
}).when(mAlarmManager).cancel(eq(mCustomListener));
when(mContext.getSystemService(eq(Context.POWER_SERVICE)))
.thenReturn(mPowerManager);
+ when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
when(mContext.getSystemService(eq(Context.ALARM_SERVICE)))
.thenReturn(mAlarmManager);
addLocalService(WindowManagerInternal.class, mWindowManager);
addLocalService(PowerManagerInternal.class, mLocalPowerManager);
addLocalService(TwilightManager.class, mTwilightManager);
+ addLocalService(DreamManagerInternal.class, mDreamManager);
mUiManagerService = new UiModeManagerService(mContext, /* setupWizardComplete= */ true,
mTwilightManager, new TestInjector());
@@ -1298,6 +1319,138 @@
assertThat(mService.getCurrentModeType()).isNotEqualTo(Configuration.UI_MODE_TYPE_CAR);
}
+ @Test
+ public void dreamWhenDocked() {
+ setScreensaverActivateOnDock(true);
+ setScreensaverEnabled(true);
+
+ triggerDockIntent();
+ verifyAndSendResultBroadcast();
+ verify(mDreamManager).requestDream();
+ }
+
+ @Test
+ public void noDreamWhenDocked_dreamsDisabled() {
+ setScreensaverActivateOnDock(true);
+ setScreensaverEnabled(false);
+
+ triggerDockIntent();
+ verifyAndSendResultBroadcast();
+ verify(mDreamManager, never()).requestDream();
+ }
+
+ @Test
+ public void noDreamWhenDocked_dreamsWhenDockedDisabled() {
+ setScreensaverActivateOnDock(false);
+ setScreensaverEnabled(true);
+
+ triggerDockIntent();
+ verifyAndSendResultBroadcast();
+ verify(mDreamManager, never()).requestDream();
+ }
+
+ @Test
+ public void noDreamWhenDocked_keyguardNotShowing_interactive() {
+ setScreensaverActivateOnDock(true);
+ setScreensaverEnabled(true);
+ mUiManagerService.setStartDreamImmediatelyOnDock(false);
+ when(mWindowManager.isKeyguardShowingAndNotOccluded()).thenReturn(false);
+ when(mPowerManager.isInteractive()).thenReturn(true);
+
+ triggerDockIntent();
+ verifyAndSendResultBroadcast();
+ verify(mDreamManager, never()).requestDream();
+ }
+
+ @Test
+ public void dreamWhenDocked_keyguardShowing_interactive() {
+ setScreensaverActivateOnDock(true);
+ setScreensaverEnabled(true);
+ mUiManagerService.setStartDreamImmediatelyOnDock(false);
+ when(mWindowManager.isKeyguardShowingAndNotOccluded()).thenReturn(true);
+ when(mPowerManager.isInteractive()).thenReturn(false);
+
+ triggerDockIntent();
+ verifyAndSendResultBroadcast();
+ verify(mDreamManager).requestDream();
+ }
+
+ @Test
+ public void dreamWhenDocked_keyguardNotShowing_notInteractive() {
+ setScreensaverActivateOnDock(true);
+ setScreensaverEnabled(true);
+ mUiManagerService.setStartDreamImmediatelyOnDock(false);
+ when(mWindowManager.isKeyguardShowingAndNotOccluded()).thenReturn(false);
+ when(mPowerManager.isInteractive()).thenReturn(false);
+
+ triggerDockIntent();
+ verifyAndSendResultBroadcast();
+ verify(mDreamManager).requestDream();
+ }
+
+ @Test
+ public void dreamWhenDocked_keyguardShowing_notInteractive() {
+ setScreensaverActivateOnDock(true);
+ setScreensaverEnabled(true);
+ mUiManagerService.setStartDreamImmediatelyOnDock(false);
+ when(mWindowManager.isKeyguardShowingAndNotOccluded()).thenReturn(true);
+ when(mPowerManager.isInteractive()).thenReturn(false);
+
+ triggerDockIntent();
+ verifyAndSendResultBroadcast();
+ verify(mDreamManager).requestDream();
+ }
+
+ private void triggerDockIntent() {
+ final Intent dockedIntent =
+ new Intent(Intent.ACTION_DOCK_EVENT)
+ .putExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_DESK);
+ mDockStateChangedCallback.onReceive(mContext, dockedIntent);
+ }
+
+ private void verifyAndSendResultBroadcast() {
+ verify(mContext).sendOrderedBroadcastAsUser(
+ mOrderedBroadcastIntent.capture(),
+ any(UserHandle.class),
+ nullable(String.class),
+ mOrderedBroadcastReceiver.capture(),
+ nullable(Handler.class),
+ anyInt(),
+ nullable(String.class),
+ nullable(Bundle.class));
+
+ mOrderedBroadcastReceiver.getValue().setPendingResult(
+ new BroadcastReceiver.PendingResult(
+ Activity.RESULT_OK,
+ /* resultData= */ "",
+ /* resultExtras= */ null,
+ /* type= */ 0,
+ /* ordered= */ true,
+ /* sticky= */ false,
+ /* token= */ null,
+ /* userId= */ 0,
+ /* flags= */ 0));
+ mOrderedBroadcastReceiver.getValue().onReceive(
+ mContext,
+ mOrderedBroadcastIntent.getValue());
+ }
+
+ private void setScreensaverEnabled(boolean enable) {
+ Settings.Secure.putIntForUser(
+ mContentResolver,
+ Settings.Secure.SCREENSAVER_ENABLED,
+ enable ? 1 : 0,
+ UserHandle.USER_CURRENT);
+ }
+
+ private void setScreensaverActivateOnDock(boolean enable) {
+ Settings.Secure.putIntForUser(
+ mContentResolver,
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+ enable ? 1 : 0,
+ UserHandle.USER_CURRENT);
+ }
+
private void requestAllPossibleProjectionTypes() throws RemoteException {
for (int i = 0; i < Integer.SIZE; ++i) {
mService.requestProjection(mBinder, 1 << i, PACKAGE_NAME);
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 8ba9af0..49879efe 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -15,6 +15,11 @@
*/
package com.android.server.notification;
+import static android.content.Context.DEVICE_POLICY_SERVICE;
+import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
+import static android.os.UserManager.USER_TYPE_PROFILE_CLONE;
+import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
+
import static com.android.server.notification.ManagedServices.APPROVAL_BY_COMPONENT;
import static com.android.server.notification.ManagedServices.APPROVAL_BY_PACKAGE;
@@ -34,6 +39,8 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -94,6 +101,7 @@
private UserManager mUm;
@Mock
private ManagedServices.UserProfiles mUserProfiles;
+ @Mock private DevicePolicyManager mDpm;
Object mLock = new Object();
UserInfo mZero = new UserInfo(0, "zero", 0);
@@ -122,6 +130,7 @@
getContext().setMockPackageManager(mPm);
getContext().addMockSystemService(Context.USER_SERVICE, mUm);
+ getContext().addMockSystemService(DEVICE_POLICY_SERVICE, mDpm);
List<UserInfo> users = new ArrayList<>();
users.add(mZero);
@@ -1694,6 +1703,58 @@
assertEquals(new ArrayMap(), mService.mIsUserChanged);
}
+ @Test
+ public void testInfoIsPermittedForProfile_notAllowed() {
+ when(mUserProfiles.canProfileUseBoundServices(anyInt())).thenReturn(false);
+
+ IInterface service = mock(IInterface.class);
+ when(service.asBinder()).thenReturn(mock(IBinder.class));
+ ManagedServices services = new TestManagedServices(getContext(), mLock, mUserProfiles,
+ mIpm, APPROVAL_BY_PACKAGE);
+ services.registerSystemService(service, null, 10, 1000);
+ ManagedServices.ManagedServiceInfo info = services.checkServiceTokenLocked(service);
+
+ assertFalse(info.isPermittedForProfile(0));
+ }
+
+ @Test
+ public void testInfoIsPermittedForProfile_allows() {
+ when(mUserProfiles.canProfileUseBoundServices(anyInt())).thenReturn(true);
+ when(mDpm.isNotificationListenerServicePermitted(anyString(), anyInt())).thenReturn(true);
+
+ IInterface service = mock(IInterface.class);
+ when(service.asBinder()).thenReturn(mock(IBinder.class));
+ ManagedServices services = new TestManagedServices(getContext(), mLock, mUserProfiles,
+ mIpm, APPROVAL_BY_PACKAGE);
+ services.registerSystemService(service, null, 10, 1000);
+ ManagedServices.ManagedServiceInfo info = services.checkServiceTokenLocked(service);
+ info.component = new ComponentName("a","b");
+
+ assertTrue(info.isPermittedForProfile(0));
+ }
+
+ @Test
+ public void testUserProfiles_canProfileUseBoundServices_managedProfile() {
+ List<UserInfo> users = new ArrayList<>();
+ UserInfo profile = new UserInfo(ActivityManager.getCurrentUser(), "current", 0);
+ profile.userType = USER_TYPE_FULL_SECONDARY;
+ users.add(profile);
+ UserInfo managed = new UserInfo(12, "12", 0);
+ managed.userType = USER_TYPE_PROFILE_MANAGED;
+ users.add(managed);
+ UserInfo clone = new UserInfo(13, "13", 0);
+ clone.userType = USER_TYPE_PROFILE_CLONE;
+ users.add(clone);
+ when(mUm.getProfiles(ActivityManager.getCurrentUser())).thenReturn(users);
+
+ ManagedServices.UserProfiles profiles = new ManagedServices.UserProfiles();
+ profiles.updateCache(mContext);
+
+ assertTrue(profiles.canProfileUseBoundServices(ActivityManager.getCurrentUser()));
+ assertFalse(profiles.canProfileUseBoundServices(12));
+ assertFalse(profiles.canProfileUseBoundServices(13));
+ }
+
private void resetComponentsAndPackages() {
ArrayMap<Integer, ArrayMap<Integer, String>> empty = new ArrayMap(1);
ArrayMap<Integer, String> emptyPkgs = new ArrayMap(0);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index d78ca1b..e85d7db 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -58,6 +58,9 @@
import static android.os.Build.VERSION_CODES.O_MR1;
import static android.os.Build.VERSION_CODES.P;
import static android.os.UserHandle.USER_SYSTEM;
+import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
+import static android.os.UserManager.USER_TYPE_PROFILE_CLONE;
+import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
import static android.service.notification.Adjustment.KEY_IMPORTANCE;
import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
@@ -212,6 +215,7 @@
import com.android.server.notification.NotificationManagerService.NotificationAssistants;
import com.android.server.notification.NotificationManagerService.NotificationListeners;
import com.android.server.pm.PackageManagerService;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;
@@ -353,6 +357,8 @@
@Mock
UserManager mUm;
@Mock
+ UserManagerInternal mUmInternal;
+ @Mock
NotificationHistoryManager mHistoryManager;
@Mock
StatsManager mStatsManager;
@@ -394,6 +400,8 @@
DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class);
when(deviceIdleInternal.getNotificationAllowlistDuration()).thenReturn(3000L);
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ LocalServices.addService(UserManagerInternal.class, mUmInternal);
LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
LocalServices.removeServiceForTest(WindowManagerInternal.class);
@@ -4464,6 +4472,33 @@
}
@Test
+ public void testReadPolicyXml_doesNotRestoreManagedServicesForCloneUser() throws Exception {
+ final String policyXml = "<notification-policy version=\"1\">"
+ + "<ranking></ranking>"
+ + "<enabled_listeners>"
+ + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
+ + "</enabled_listeners>"
+ + "<enabled_assistants>"
+ + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
+ + "</enabled_assistants>"
+ + "<dnd_apps>"
+ + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
+ + "</dnd_apps>"
+ + "</notification-policy>";
+ UserInfo ui = new UserInfo();
+ ui.id = 10;
+ ui.userType = USER_TYPE_PROFILE_CLONE;
+ when(mUmInternal.getUserInfo(10)).thenReturn(ui);
+ mService.readPolicyXml(
+ new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
+ true,
+ 10);
+ verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
+ verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
+ verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
+ }
+
+ @Test
public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
final String policyXml = "<notification-policy version=\"1\">"
+ "<ranking></ranking>"
@@ -4477,7 +4512,10 @@
+ "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
+ "</dnd_apps>"
+ "</notification-policy>";
- when(mUm.isManagedProfile(10)).thenReturn(true);
+ UserInfo ui = new UserInfo();
+ ui.id = 10;
+ ui.userType = USER_TYPE_PROFILE_MANAGED;
+ when(mUmInternal.getUserInfo(10)).thenReturn(ui);
mService.readPolicyXml(
new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
true,
@@ -4501,7 +4539,10 @@
+ "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
+ "</dnd_apps>"
+ "</notification-policy>";
- when(mUm.isManagedProfile(10)).thenReturn(false);
+ UserInfo ui = new UserInfo();
+ ui.id = 10;
+ ui.userType = USER_TYPE_FULL_SECONDARY;
+ when(mUmInternal.getUserInfo(10)).thenReturn(ui);
mService.readPolicyXml(
new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
true,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index d62ac99..598a22b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -93,7 +93,6 @@
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
-import android.os.Parcel;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -2448,35 +2447,6 @@
}
@Test
- public void testGetNotificationChannelGroup() throws Exception {
- NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted");
- NotificationChannel base =
- new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT);
- base.setGroup("not");
- NotificationChannel convo =
- new NotificationChannel("convo", "belongs to notDeleted", IMPORTANCE_DEFAULT);
- convo.setGroup("not");
- convo.setConversationId("not deleted", "banana");
-
- mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, notDeleted, true);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, base, true, false);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, convo, true, false);
- mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, notDeleted, true);
-
- NotificationChannelGroup g
- = mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG_N_MR1, UID_N_MR1);
- Parcel parcel = Parcel.obtain();
- g.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
-
- NotificationChannelGroup g2
- = mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG_N_MR1, UID_N_MR1);
- Parcel parcel2 = Parcel.obtain();
- g2.writeToParcel(parcel2, 0);
- parcel2.setDataPosition(0);
- }
-
- @Test
public void testOnUserRemoved() throws Exception {
int[] user0Uids = {98, 235, 16, 3782};
int[] user1Uids = new int[user0Uids.length];
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 4550b56..2ccdcaa 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -1672,6 +1672,36 @@
}
@Test
+ public void testAddAutomaticZenRule_claimedSystemOwner() {
+ // Make sure anything that claims to have a "system" owner but not actually part of the
+ // system package still gets limited on number of rules
+ for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) {
+ ScheduleInfo si = new ScheduleInfo();
+ si.startHour = i;
+ AutomaticZenRule zenRule = new AutomaticZenRule("name" + i,
+ new ComponentName("android", "ScheduleConditionProvider" + i),
+ null, // configuration activity
+ ZenModeConfig.toScheduleConditionId(si),
+ new ZenPolicy.Builder().build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+ assertNotNull(id);
+ }
+ try {
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ new ComponentName("android", "ScheduleConditionProviderFinal"),
+ null, // configuration activity
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ new ZenPolicy.Builder().build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+ fail("allowed too many rules to be created");
+ } catch (IllegalArgumentException e) {
+ // yay
+ }
+ }
+
+ @Test
public void testAddAutomaticZenRule_CA() {
AutomaticZenRule zenRule = new AutomaticZenRule("name",
null,
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 8b350f4..eb61a9c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -158,6 +158,7 @@
import com.android.internal.R;
import com.android.server.wm.ActivityRecord.State;
+import com.android.server.wm.utils.WmDisplayCutout;
import org.junit.Assert;
import org.junit.Before;
@@ -551,7 +552,8 @@
final Rect insets = new Rect();
final DisplayInfo displayInfo = task.mDisplayContent.getDisplayInfo();
final DisplayPolicy policy = task.mDisplayContent.getDisplayPolicy();
- policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.displayCutout, insets);
+ policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
+ displayInfo.logicalHeight, WmDisplayCutout.NO_CUTOUT, insets);
policy.convertNonDecorInsetsToStableInsets(insets, displayInfo.rotation);
Task.intersectWithInsetsIfFits(stableRect, stableRect, insets);
@@ -592,7 +594,8 @@
final Rect insets = new Rect();
final DisplayInfo displayInfo = rootTask.mDisplayContent.getDisplayInfo();
final DisplayPolicy policy = rootTask.mDisplayContent.getDisplayPolicy();
- policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.displayCutout, insets);
+ policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
+ displayInfo.logicalHeight, WmDisplayCutout.NO_CUTOUT, insets);
policy.convertNonDecorInsetsToStableInsets(insets, displayInfo.rotation);
Task.intersectWithInsetsIfFits(stableRect, stableRect, insets);
@@ -2868,6 +2871,7 @@
mAtm, null /* fragmentToken */, false /* createdByOrganizer */);
fragmentSetup.accept(taskFragment1, new Rect(0, 0, width / 2, height));
task.addChild(taskFragment1, POSITION_TOP);
+ assertEquals(task, activity1.mStartingData.mAssociatedTask);
final TaskFragment taskFragment2 = new TaskFragment(
mAtm, null /* fragmentToken */, false /* createdByOrganizer */);
@@ -2889,7 +2893,6 @@
eq(task.mSurfaceControl));
assertEquals(activity1.mStartingData, startingWindow.mStartingData);
assertEquals(task.mSurfaceControl, startingWindow.getAnimationLeashParent());
- assertEquals(task, activity1.mStartingData.mAssociatedTask);
assertEquals(taskFragment1.getBounds(), activity1.getBounds());
// The activity was resized by task fragment, but starting window must still cover the task.
assertEquals(taskBounds, activity1.mStartingWindow.getBounds());
@@ -2897,7 +2900,6 @@
// The starting window is only removed when all embedded activities are drawn.
final WindowState activityWindow = mock(WindowState.class);
activity1.onFirstWindowDrawn(activityWindow);
- assertNotNull(activity1.mStartingWindow);
activity2.onFirstWindowDrawn(activityWindow);
assertNull(activity1.mStartingWindow);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index c2ca0a2..1cd0b19 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -80,10 +80,12 @@
IOnBackInvokedCallback callback = withSystemCallback(task);
BackNavigationInfo backNavigationInfo =
- mBackNavigationController.startBackNavigation(true, null);
+ mBackNavigationController.startBackNavigation(true, null, null);
assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull();
- assertThat(backNavigationInfo.getDepartingAnimationTarget()).isNotNull();
- assertThat(backNavigationInfo.getTaskWindowConfiguration()).isNotNull();
+ if (!BackNavigationController.USE_TRANSITION) {
+ assertThat(backNavigationInfo.getDepartingAnimationTarget()).isNotNull();
+ assertThat(backNavigationInfo.getTaskWindowConfiguration()).isNotNull();
+ }
assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(callback);
assertThat(typeToString(backNavigationInfo.getType()))
.isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME));
@@ -233,7 +235,7 @@
@Nullable
private BackNavigationInfo startBackNavigation() {
- return mBackNavigationController.startBackNavigation(true, null);
+ return mBackNavigationController.startBackNavigation(true, null, null);
}
@NonNull
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index be266c9..fd97d91 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1251,7 +1251,15 @@
public void testComputeImeControlTarget() throws Exception {
final DisplayContent dc = createNewDisplay();
dc.setRemoteInsetsController(createDisplayWindowInsetsController());
- dc.setImeInputTarget(createWindow(null, TYPE_BASE_APPLICATION, "app"));
+ dc.mCurrentFocus = createWindow(null, TYPE_BASE_APPLICATION, "app");
+
+ // Expect returning null IME control target when the focus window has not yet been the
+ // IME input target (e.g. IME is restarting) in fullscreen windowing mode.
+ dc.setImeInputTarget(null);
+ assertFalse(dc.mCurrentFocus.inMultiWindowMode());
+ assertNull(dc.computeImeControlTarget());
+
+ dc.setImeInputTarget(dc.mCurrentFocus);
dc.setImeLayeringTarget(dc.getImeInputTarget().getWindowState());
assertEquals(dc.getImeInputTarget().getWindowState(), dc.computeImeControlTarget());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java
index f41fee7..a001eda 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java
@@ -25,10 +25,13 @@
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
+import android.util.Pair;
import android.view.DisplayInfo;
import androidx.test.filters.SmallTest;
+import com.android.server.wm.utils.WmDisplayCutout;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
@@ -46,7 +49,8 @@
@Test
public void portrait() {
- final DisplayInfo di = displayInfoForRotation(ROTATION_0, false /* withCutout */);
+ final Pair<DisplayInfo, WmDisplayCutout> di =
+ displayInfoForRotation(ROTATION_0, false /* withCutout */);
verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT);
verifyNonDecorInsets(di, 0, 0, 0, NAV_BAR_HEIGHT);
@@ -55,7 +59,8 @@
@Test
public void portrait_withCutout() {
- final DisplayInfo di = displayInfoForRotation(ROTATION_0, true /* withCutout */);
+ final Pair<DisplayInfo, WmDisplayCutout> di =
+ displayInfoForRotation(ROTATION_0, true /* withCutout */);
verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT);
verifyNonDecorInsets(di, 0, DISPLAY_CUTOUT_HEIGHT, 0, NAV_BAR_HEIGHT);
@@ -64,7 +69,8 @@
@Test
public void landscape() {
- final DisplayInfo di = displayInfoForRotation(ROTATION_90, false /* withCutout */);
+ final Pair<DisplayInfo, WmDisplayCutout> di =
+ displayInfoForRotation(ROTATION_90, false /* withCutout */);
if (mDisplayPolicy.navigationBarCanMove()) {
verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
@@ -79,7 +85,8 @@
@Test
public void landscape_withCutout() {
- final DisplayInfo di = displayInfoForRotation(ROTATION_90, true /* withCutout */);
+ final Pair<DisplayInfo, WmDisplayCutout> di =
+ displayInfoForRotation(ROTATION_90, true /* withCutout */);
if (mDisplayPolicy.navigationBarCanMove()) {
verifyStableInsets(di, DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
@@ -94,7 +101,8 @@
@Test
public void seascape() {
- final DisplayInfo di = displayInfoForRotation(ROTATION_270, false /* withCutout */);
+ final Pair<DisplayInfo, WmDisplayCutout> di =
+ displayInfoForRotation(ROTATION_270, false /* withCutout */);
if (mDisplayPolicy.navigationBarCanMove()) {
verifyStableInsets(di, NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, 0, 0);
@@ -109,7 +117,8 @@
@Test
public void seascape_withCutout() {
- final DisplayInfo di = displayInfoForRotation(ROTATION_270, true /* withCutout */);
+ final Pair<DisplayInfo, WmDisplayCutout> di =
+ displayInfoForRotation(ROTATION_270, true /* withCutout */);
if (mDisplayPolicy.navigationBarCanMove()) {
verifyStableInsets(di, NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, DISPLAY_CUTOUT_HEIGHT, 0);
@@ -124,7 +133,8 @@
@Test
public void upsideDown() {
- final DisplayInfo di = displayInfoForRotation(ROTATION_180, false /* withCutout */);
+ final Pair<DisplayInfo, WmDisplayCutout> di =
+ displayInfoForRotation(ROTATION_180, false /* withCutout */);
verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT);
verifyNonDecorInsets(di, 0, 0, 0, NAV_BAR_HEIGHT);
@@ -133,28 +143,34 @@
@Test
public void upsideDown_withCutout() {
- final DisplayInfo di = displayInfoForRotation(ROTATION_180, true /* withCutout */);
+ final Pair<DisplayInfo, WmDisplayCutout> di =
+ displayInfoForRotation(ROTATION_180, true /* withCutout */);
verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT + DISPLAY_CUTOUT_HEIGHT);
verifyNonDecorInsets(di, 0, 0, 0, NAV_BAR_HEIGHT + DISPLAY_CUTOUT_HEIGHT);
verifyConsistency(di);
}
- private void verifyStableInsets(DisplayInfo di, int left, int top, int right, int bottom) {
- mErrorCollector.checkThat("stableInsets", getStableInsetsLw(di), equalTo(new Rect(
+ private void verifyStableInsets(Pair<DisplayInfo, WmDisplayCutout> diPair, int left, int top,
+ int right, int bottom) {
+ mErrorCollector.checkThat("stableInsets", getStableInsetsLw(diPair.first, diPair.second),
+ equalTo(new Rect(left, top, right, bottom)));
+ }
+
+ private void verifyNonDecorInsets(Pair<DisplayInfo, WmDisplayCutout> diPair, int left, int top,
+ int right, int bottom) {
+ mErrorCollector.checkThat("nonDecorInsets",
+ getNonDecorInsetsLw(diPair.first, diPair.second), equalTo(new Rect(
left, top, right, bottom)));
}
- private void verifyNonDecorInsets(DisplayInfo di, int left, int top, int right, int bottom) {
- mErrorCollector.checkThat("nonDecorInsets", getNonDecorInsetsLw(di), equalTo(new Rect(
- left, top, right, bottom)));
- }
-
- private void verifyConsistency(DisplayInfo di) {
- verifyConsistency("configDisplay", di, getStableInsetsLw(di),
- getConfigDisplayWidth(di), getConfigDisplayHeight(di));
- verifyConsistency("nonDecorDisplay", di, getNonDecorInsetsLw(di),
- getNonDecorDisplayWidth(di), getNonDecorDisplayHeight(di));
+ private void verifyConsistency(Pair<DisplayInfo, WmDisplayCutout> diPair) {
+ final DisplayInfo di = diPair.first;
+ final WmDisplayCutout cutout = diPair.second;
+ verifyConsistency("configDisplay", di, getStableInsetsLw(di, cutout),
+ getConfigDisplayWidth(di, cutout), getConfigDisplayHeight(di, cutout));
+ verifyConsistency("nonDecorDisplay", di, getNonDecorInsetsLw(di, cutout),
+ getNonDecorDisplayWidth(di, cutout), getNonDecorDisplayHeight(di, cutout));
}
private void verifyConsistency(String what, DisplayInfo di, Rect insets, int width,
@@ -165,39 +181,42 @@
equalTo(di.logicalHeight - insets.top - insets.bottom));
}
- private Rect getStableInsetsLw(DisplayInfo di) {
+ private Rect getStableInsetsLw(DisplayInfo di, WmDisplayCutout cutout) {
Rect result = new Rect();
- mDisplayPolicy.getStableInsetsLw(di.rotation, di.displayCutout, result);
+ mDisplayPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+ cutout, result);
return result;
}
- private Rect getNonDecorInsetsLw(DisplayInfo di) {
+ private Rect getNonDecorInsetsLw(DisplayInfo di, WmDisplayCutout cutout) {
Rect result = new Rect();
- mDisplayPolicy.getNonDecorInsetsLw(di.rotation, di.displayCutout, result);
+ mDisplayPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+ cutout, result);
return result;
}
- private int getNonDecorDisplayWidth(DisplayInfo di) {
- return mDisplayPolicy.getNonDecorDisplayWidth(di.logicalWidth, di.logicalHeight,
- di.rotation, 0 /* ui */, di.displayCutout);
+ private int getNonDecorDisplayWidth(DisplayInfo di, WmDisplayCutout cutout) {
+ return mDisplayPolicy.getNonDecorDisplayFrame(di.logicalWidth, di.logicalHeight,
+ di.rotation, cutout).width();
}
- private int getNonDecorDisplayHeight(DisplayInfo di) {
- return mDisplayPolicy.getNonDecorDisplayHeight(di.logicalHeight, di.rotation,
- di.displayCutout);
+ private int getNonDecorDisplayHeight(DisplayInfo di, WmDisplayCutout cutout) {
+ return mDisplayPolicy.getNonDecorDisplayFrame(di.logicalWidth, di.logicalHeight,
+ di.rotation, cutout).height();
}
- private int getConfigDisplayWidth(DisplayInfo di) {
- return mDisplayPolicy.getConfigDisplayWidth(di.logicalWidth, di.logicalHeight,
- di.rotation, 0 /* ui */, di.displayCutout);
+ private int getConfigDisplayWidth(DisplayInfo di, WmDisplayCutout cutout) {
+ return mDisplayPolicy.getConfigDisplaySize(di.logicalWidth, di.logicalHeight,
+ di.rotation, cutout).x;
}
- private int getConfigDisplayHeight(DisplayInfo di) {
- return mDisplayPolicy.getConfigDisplayHeight(di.logicalWidth, di.logicalHeight,
- di.rotation, 0 /* ui */, di.displayCutout);
+ private int getConfigDisplayHeight(DisplayInfo di, WmDisplayCutout cutout) {
+ return mDisplayPolicy.getConfigDisplaySize(di.logicalWidth, di.logicalHeight,
+ di.rotation, cutout).y;
}
- private static DisplayInfo displayInfoForRotation(int rotation, boolean withDisplayCutout) {
- return displayInfoAndCutoutForRotation(rotation, withDisplayCutout, false).first;
+ private static Pair<DisplayInfo, WmDisplayCutout> displayInfoForRotation(int rotation,
+ boolean withDisplayCutout) {
+ return displayInfoAndCutoutForRotation(rotation, withDisplayCutout, false);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/PossibleDisplayInfoMapperTests.java b/services/tests/wmtests/src/com/android/server/wm/PossibleDisplayInfoMapperTests.java
index 8b0a540..58b0e16 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PossibleDisplayInfoMapperTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PossibleDisplayInfoMapperTests.java
@@ -36,6 +36,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
@@ -88,7 +90,8 @@
mPossibleDisplayInfo.add(mDefaultDisplayInfo);
mDisplayInfoMapper.updatePossibleDisplayInfos(DEFAULT_DISPLAY);
- Set<DisplayInfo> displayInfos = mDisplayInfoMapper.getPossibleDisplayInfos(DEFAULT_DISPLAY);
+ List<DisplayInfo> displayInfos = mDisplayInfoMapper.getPossibleDisplayInfos(
+ DEFAULT_DISPLAY);
// An entry for rotation 0, for a display that can be in a single state.
assertThat(displayInfos.size()).isEqualTo(1);
assertPossibleDisplayInfoEntries(displayInfos, mDefaultDisplayInfo);
@@ -105,9 +108,10 @@
mPossibleDisplayInfo.add(mSecondDisplayInfo);
mDisplayInfoMapper.updatePossibleDisplayInfos(DEFAULT_DISPLAY);
- Set<DisplayInfo> displayInfos = mDisplayInfoMapper.getPossibleDisplayInfos(DEFAULT_DISPLAY);
- Set<DisplayInfo> defaultDisplayInfos = new ArraySet<>();
- Set<DisplayInfo> secondDisplayInfos = new ArraySet<>();
+ List<DisplayInfo> displayInfos = mDisplayInfoMapper.getPossibleDisplayInfos(
+ DEFAULT_DISPLAY);
+ List<DisplayInfo> defaultDisplayInfos = new ArrayList<>();
+ List<DisplayInfo> secondDisplayInfos = new ArrayList<>();
for (DisplayInfo di : displayInfos) {
if ((di.flags & FLAG_PRESENTATION) != 0) {
secondDisplayInfos.add(di);
@@ -137,12 +141,13 @@
mPossibleDisplayInfo.add(mSecondDisplayInfo);
mDisplayInfoMapper.updatePossibleDisplayInfos(mSecondDisplayInfo.displayId);
- Set<DisplayInfo> displayInfos = mDisplayInfoMapper.getPossibleDisplayInfos(DEFAULT_DISPLAY);
+ List<DisplayInfo> displayInfos = mDisplayInfoMapper.getPossibleDisplayInfos(
+ DEFAULT_DISPLAY);
// An entry for rotation 0, for the default display.
assertThat(displayInfos).hasSize(1);
assertPossibleDisplayInfoEntries(displayInfos, mDefaultDisplayInfo);
- Set<DisplayInfo> secondStateEntries =
+ List<DisplayInfo> secondStateEntries =
mDisplayInfoMapper.getPossibleDisplayInfos(mSecondDisplayInfo.displayId);
// An entry for rotation 0, for the second display.
assertThat(secondStateEntries).hasSize(1);
@@ -157,7 +162,7 @@
outDisplayInfo.logicalHeight = logicalBounds.height();
}
- private static void assertPossibleDisplayInfoEntries(Set<DisplayInfo> displayInfos,
+ private static void assertPossibleDisplayInfoEntries(List<DisplayInfo> displayInfos,
DisplayInfo expectedDisplayInfo) {
for (DisplayInfo displayInfo : displayInfos) {
assertThat(displayInfo.displayId).isEqualTo(expectedDisplayInfo.displayId);
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 85f85f1..f6ffa91 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -1640,6 +1640,75 @@
}
@Test
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN})
+ public void testOverrideMinAspectRatioExcludePortraitFullscreen() {
+ setUpDisplaySizeWithApp(2600, 1600);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.33f);
+
+ // Create a size compat activity on the same task.
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(mTask)
+ .setComponent(ComponentName.createRelative(mContext,
+ SizeCompatTests.class.getName()))
+ .setUid(android.os.Process.myUid())
+ .build();
+
+ // Non-resizable portrait activity
+ prepareUnresizable(activity, 0f, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+
+ // At first, OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_FULLSCREEN does not apply, because the
+ // display is in landscape
+ assertEquals(1600, activity.getBounds().height());
+ assertEquals(1600 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
+ activity.getBounds().width(), 0.5);
+
+ rotateDisplay(activity.mDisplayContent, ROTATION_90);
+ prepareUnresizable(activity, /* maxAspect */ 0, SCREEN_ORIENTATION_PORTRAIT);
+
+ // Now the display is in portrait fullscreen, so the override is applied making the content
+ // fullscreen
+ assertEquals(activity.getBounds(), activity.mDisplayContent.getBounds());
+ }
+
+ @Test
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN})
+ public void testOverrideMinAspectRatioExcludePortraitFullscreenNotApplied() {
+ // In this test, the activity is not in fullscreen, so the override is not applied
+ setUpDisplaySizeWithApp(2600, 1600);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.33f);
+
+ // Create a size compat activity on the same task.
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(mTask)
+ .setComponent(ComponentName.createRelative(mContext,
+ SizeCompatTests.class.getName()))
+ .setUid(android.os.Process.myUid())
+ .build();
+
+ final TestSplitOrganizer organizer =
+ new TestSplitOrganizer(mAtm, activity.getDisplayContent());
+
+ // Move first activity to split screen which takes half of the screen.
+ organizer.mPrimary.setBounds(0, 0, 1300, 1600);
+ organizer.putTaskToPrimary(mTask, true);
+
+ // Non-resizable portrait activity
+ prepareUnresizable(activity, /* maxAspect */ 0, SCREEN_ORIENTATION_PORTRAIT);
+
+ // OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_FULLSCREEN does not apply here because the
+ // display is not in fullscreen, so OVERRIDE_MIN_ASPECT_RATIO_LARGE applies instead
+ assertEquals(1600, activity.getBounds().height());
+ assertEquals(1600 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
+ activity.getBounds().width(), 0.5);
+ }
+
+ @Test
public void testSplitAspectRatioForUnresizableLandscapeApps() {
// Set up a display in portrait and ignoring orientation request.
int screenWidth = 1400;
diff --git a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
index 420ea8e..d3aa073 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
@@ -16,13 +16,18 @@
package com.android.server.wm;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.BLASTSyncEngine.METHOD_BLAST;
+import static com.android.server.wm.BLASTSyncEngine.METHOD_NONE;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowContainer.SYNC_STATE_NONE;
+import static com.android.server.wm.WindowState.BLAST_TIMEOUT_DURATION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -67,7 +72,7 @@
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
- int id = bse.startSyncSet(listener);
+ int id = startSyncSet(bse, listener);
bse.addToSyncSet(id, mockWC);
// Make sure a traversal is requested
verify(mWm.mWindowPlacerLocked, times(1)).requestTraversal();
@@ -95,7 +100,7 @@
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
- int id = bse.startSyncSet(listener);
+ int id = startSyncSet(bse, listener);
bse.addToSyncSet(id, mockWC);
bse.setReady(id);
// Make sure traversals requested (one for add and another for setReady)
@@ -119,7 +124,7 @@
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
- int id = bse.startSyncSet(listener);
+ int id = startSyncSet(bse, listener);
bse.addToSyncSet(id, mockWC);
bse.setReady(id);
// Make sure traversals requested (one for add and another for setReady)
@@ -147,7 +152,7 @@
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
- int id = bse.startSyncSet(listener);
+ int id = startSyncSet(bse, listener);
bse.addToSyncSet(id, parentWC);
bse.setReady(id);
bse.onSurfacePlacement();
@@ -180,7 +185,7 @@
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
- int id = bse.startSyncSet(listener);
+ int id = startSyncSet(bse, listener);
bse.addToSyncSet(id, parentWC);
bse.setReady(id);
bse.onSurfacePlacement();
@@ -211,7 +216,7 @@
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
- int id = bse.startSyncSet(listener);
+ int id = startSyncSet(bse, listener);
bse.addToSyncSet(id, parentWC);
bse.setReady(id);
bse.onSurfacePlacement();
@@ -243,7 +248,7 @@
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
- int id = bse.startSyncSet(listener);
+ int id = startSyncSet(bse, listener);
bse.addToSyncSet(id, parentWC);
bse.setReady(id);
bse.onSurfacePlacement();
@@ -278,7 +283,7 @@
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
- int id = bse.startSyncSet(listener);
+ int id = startSyncSet(bse, listener);
bse.addToSyncSet(id, parentWC);
bse.setReady(id);
bse.onSurfacePlacement();
@@ -317,7 +322,7 @@
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
- int id = bse.startSyncSet(listener);
+ int id = startSyncSet(bse, listener);
bse.addToSyncSet(id, parentWC);
final BLASTSyncEngine.SyncGroup syncGroup = parentWC.mSyncGroup;
bse.setReady(id);
@@ -350,6 +355,33 @@
assertEquals(SYNC_STATE_NONE, botChildWC.mSyncState);
}
+ @Test
+ public void testNonBlastMethod() {
+ mAppWindow = createWindow(null, TYPE_BASE_APPLICATION, "mAppWindow");
+
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ int id = startSyncSet(bse, listener, METHOD_NONE);
+ bse.addToSyncSet(id, mAppWindow.mToken);
+ mAppWindow.prepareSync();
+ assertFalse(mAppWindow.shouldSyncWithBuffers());
+
+ mAppWindow.removeImmediately();
+ }
+
+ static int startSyncSet(BLASTSyncEngine engine,
+ BLASTSyncEngine.TransactionReadyListener listener) {
+ return startSyncSet(engine, listener, METHOD_BLAST);
+ }
+
+ static int startSyncSet(BLASTSyncEngine engine,
+ BLASTSyncEngine.TransactionReadyListener listener, int method) {
+ return engine.startSyncSet(listener, BLAST_TIMEOUT_DURATION, "", method);
+ }
+
static class TestWindowContainer extends WindowContainer {
final boolean mWaiter;
boolean mVisibleRequested = true;
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 6c100d7..6d514b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -235,6 +235,7 @@
doReturn(pm).when(mContext).getSystemService(eq(Context.POWER_SERVICE));
mStubbedWakeLock = createStubbedWakeLock(false /* needVerification */);
doReturn(mStubbedWakeLock).when(pm).newWakeLock(anyInt(), anyString());
+ doReturn(mStubbedWakeLock).when(pm).newWakeLock(anyInt(), anyString(), anyInt());
// DisplayManagerInternal
final DisplayManagerInternal dmi = mock(DisplayManagerInternal.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index 9274eb3..9bdf750 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -18,10 +18,20 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_OP_TYPE;
+import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_THROWABLE;
+import static android.window.TaskFragmentOrganizer.getTransitionType;
+import static android.window.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENTED_TO_TASK;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_ERROR;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_INFO_CHANGED;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED;
+import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_VANISHED;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_CHILDREN;
+import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT;
@@ -40,21 +50,22 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
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.annotation.NonNull;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
@@ -68,7 +79,6 @@
import android.window.TaskFragmentTransaction;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
-import android.window.WindowContainerTransactionCallback;
import androidx.test.filters.SmallTest;
@@ -76,9 +86,12 @@
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;
+import java.util.List;
+
/**
* Build/Install/Run:
* atest WmTests:TaskFragmentOrganizerControllerTest
@@ -107,6 +120,8 @@
private TaskFragmentInfo mTaskFragmentInfo;
@Mock
private Task mTask;
+ @Captor
+ private ArgumentCaptor<TaskFragmentTransaction> mTransactionCaptor;
@Before
public void setup() throws RemoteException {
@@ -121,6 +136,7 @@
mTaskFragment =
new TaskFragment(mAtm, mFragmentToken, true /* createdByOrganizer */);
mTransaction = new WindowContainerTransaction();
+ mTransaction.setTaskFragmentOrganizer(mIOrganizer);
mFragmentWindowToken = mTaskFragment.mRemoteToken.toWindowContainerToken();
mDefinition = new RemoteAnimationDefinition();
mErrorToken = new Binder();
@@ -140,11 +156,16 @@
doReturn(new Configuration()).when(mTaskFragmentInfo).getConfiguration();
// To prevent it from calling the real server.
- doNothing().when(mOrganizer).onTransactionHandled(any(), any());
+ doNothing().when(mOrganizer).applyTransaction(any(), anyInt(), anyBoolean());
+ doNothing().when(mOrganizer).onTransactionHandled(any(), any(), anyInt(), anyBoolean());
+
+ mController.registerOrganizer(mIOrganizer);
}
@Test
public void testCallTaskFragmentCallbackWithoutRegister_throwsException() {
+ mController.unregisterOrganizer(mIOrganizer);
+
doReturn(mTask).when(mTaskFragment).getTask();
assertThrows(IllegalArgumentException.class, () -> mController
@@ -160,13 +181,11 @@
@Test
public void testOnTaskFragmentAppeared() {
- mController.registerOrganizer(mIOrganizer);
-
// No-op when the TaskFragment is not attached.
mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer, never()).onTaskFragmentAppeared(any(), any());
+ verify(mOrganizer, never()).onTransactionReady(any());
// Send callback when the TaskFragment is attached.
setupMockParent(mTaskFragment, mTask);
@@ -174,12 +193,11 @@
mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentAppeared(any(), any());
+ assertTaskFragmentAppearedTransaction();
}
@Test
public void testOnTaskFragmentInfoChanged() {
- mController.registerOrganizer(mIOrganizer);
setupMockParent(mTaskFragment, mTask);
// No-op if onTaskFragmentAppeared is not called yet.
@@ -187,15 +205,16 @@
mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer, never()).onTaskFragmentInfoChanged(any(), any());
+ verify(mOrganizer, never()).onTransactionReady(any());
// Call onTaskFragmentAppeared first.
mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentAppeared(any(), any());
+ verify(mOrganizer).onTransactionReady(any());
// No callback if the info is not changed.
+ clearInvocations(mOrganizer);
doReturn(true).when(mTaskFragmentInfo).equalsForTaskFragmentOrganizer(any());
doReturn(new Configuration()).when(mTaskFragmentInfo).getConfiguration();
@@ -203,7 +222,7 @@
mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer, never()).onTaskFragmentInfoChanged(any(), any());
+ verify(mOrganizer, never()).onTransactionReady(any());
// Trigger callback if the info is changed.
doReturn(false).when(mTaskFragmentInfo).equalsForTaskFragmentOrganizer(any());
@@ -212,23 +231,20 @@
mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentInfoChanged(any(), eq(mTaskFragmentInfo));
+ assertTaskFragmentInfoChangedTransaction();
}
@Test
public void testOnTaskFragmentVanished() {
- mController.registerOrganizer(mIOrganizer);
-
mTaskFragment.mTaskFragmentAppearedSent = true;
mController.onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentVanished(any(), any());
+ assertTaskFragmentVanishedTransaction();
}
@Test
public void testOnTaskFragmentVanished_clearUpRemaining() {
- mController.registerOrganizer(mIOrganizer);
setupMockParent(mTaskFragment, mTask);
// Not trigger onTaskFragmentAppeared.
@@ -236,10 +252,7 @@
mController.onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer, never()).onTaskFragmentAppeared(any(), any());
- verify(mOrganizer, never()).onTaskFragmentInfoChanged(any(), any());
- verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(any(), anyInt(), any());
- verify(mOrganizer).onTaskFragmentVanished(any(), eq(mTaskFragmentInfo));
+ assertTaskFragmentVanishedTransaction();
// Not trigger onTaskFragmentInfoChanged.
// Call onTaskFragmentAppeared before calling onTaskFragmentInfoChanged.
@@ -252,15 +265,11 @@
mController.onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer, never()).onTaskFragmentAppeared(any(), any());
- verify(mOrganizer, never()).onTaskFragmentInfoChanged(any(), any());
- verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(any(), anyInt(), any());
- verify(mOrganizer).onTaskFragmentVanished(any(), eq(mTaskFragmentInfo));
+ assertTaskFragmentVanishedTransaction();
}
@Test
public void testOnTaskFragmentParentInfoChanged() {
- mController.registerOrganizer(mIOrganizer);
setupMockParent(mTaskFragment, mTask);
mTask.getConfiguration().smallestScreenWidthDp = 10;
@@ -268,24 +277,30 @@
mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentParentInfoChanged(any(), eq(mTask.mTaskId), any());
+ assertTaskFragmentParentInfoChangedTransaction(mTask);
- // No extra callback if the info is not changed.
+ // No extra parent info changed callback if the info is not changed.
clearInvocations(mOrganizer);
mController.onTaskFragmentInfoChanged(
mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(any(), anyInt(), any());
+ verify(mOrganizer).onTransactionReady(mTransactionCaptor.capture());
+ final TaskFragmentTransaction transaction = mTransactionCaptor.getValue();
+ final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
+ assertEquals(1, changes.size());
+ final TaskFragmentTransaction.Change change = changes.get(0);
+ assertEquals(TYPE_TASK_FRAGMENT_INFO_CHANGED, change.getType());
// Trigger callback if the size is changed.
+ clearInvocations(mOrganizer);
mTask.getConfiguration().smallestScreenWidthDp = 100;
mController.onTaskFragmentInfoChanged(
mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentParentInfoChanged(any(), eq(mTask.mTaskId), any());
+ assertTaskFragmentParentInfoChangedTransaction(mTask);
// Trigger callback if the windowing mode is changed.
clearInvocations(mOrganizer);
@@ -294,20 +309,20 @@
mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentParentInfoChanged(any(), eq(mTask.mTaskId), any());
+ assertTaskFragmentParentInfoChangedTransaction(mTask);
}
@Test
public void testOnTaskFragmentError() {
final Throwable exception = new IllegalArgumentException("Test exception");
- mController.registerOrganizer(mIOrganizer);
mController.onTaskFragmentError(mTaskFragment.getTaskFragmentOrganizer(),
- mErrorToken, null /* taskFragment */, -1 /* opType */, exception);
+ mErrorToken, null /* taskFragment */, HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS,
+ exception);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentError(any(), eq(mErrorToken), eq(null), eq(-1),
- eq(exception));
+ assertTaskFragmentErrorTransaction(HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS,
+ exception.getClass());
}
@Test
@@ -315,7 +330,6 @@
// Make sure the activity pid/uid is the same as the organizer caller.
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
- mController.registerOrganizer(mIOrganizer);
final ActivityRecord activity = createActivityRecord(mDisplayContent);
final Task task = activity.getTask();
activity.info.applicationInfo.uid = uid;
@@ -326,17 +340,17 @@
mController.onActivityReparentedToTask(activity);
mController.dispatchPendingEvents();
- verify(mOrganizer, never()).onActivityReparentedToTask(any(), anyInt(), any(), any());
+ verify(mOrganizer, never()).onTransactionReady(any());
// Notify organizer if it was embedded before entered Pip.
activity.mLastTaskFragmentOrganizerBeforePip = mIOrganizer;
mController.onActivityReparentedToTask(activity);
mController.dispatchPendingEvents();
- verify(mOrganizer).onActivityReparentedToTask(any(), eq(task.mTaskId), eq(activity.intent),
- eq(activity.token));
+ assertActivityReparentedToTaskTransaction(task.mTaskId, activity.intent, activity.token);
// Notify organizer if there is any embedded in the Task.
+ clearInvocations(mOrganizer);
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
.setParentTask(task)
.setOrganizer(mOrganizer)
@@ -348,9 +362,7 @@
mController.onActivityReparentedToTask(activity);
mController.dispatchPendingEvents();
- verify(mOrganizer, times(2))
- .onActivityReparentedToTask(any(), eq(task.mTaskId), eq(activity.intent),
- eq(activity.token));
+ assertActivityReparentedToTaskTransaction(task.mTaskId, activity.intent, activity.token);
}
@Test
@@ -360,8 +372,6 @@
mTaskFragment.setTaskFragmentOrganizer(mOrganizer.getOrganizerToken(), uid,
DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME);
mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
- mController.registerOrganizer(mIOrganizer);
- mOrganizer.applyTransaction(mTransaction);
final Task task = createTask(mDisplayContent);
task.addChild(mTaskFragment, POSITION_TOP);
final ActivityRecord activity = createActivityRecord(task);
@@ -370,30 +380,35 @@
activity.info.applicationInfo.uid = uid;
doReturn(pid + 1).when(activity).getPid();
task.effectiveUid = uid;
- final ArgumentCaptor<IBinder> token = ArgumentCaptor.forClass(IBinder.class);
// Notify organizer if it was embedded before entered Pip.
// Create a temporary token since the activity doesn't belong to the same process.
+ clearInvocations(mOrganizer);
activity.mLastTaskFragmentOrganizerBeforePip = mIOrganizer;
mController.onActivityReparentedToTask(activity);
mController.dispatchPendingEvents();
// Allow organizer to reparent activity in other process using the temporary token.
- verify(mOrganizer).onActivityReparentedToTask(any(), eq(task.mTaskId), eq(activity.intent),
- token.capture());
- final IBinder temporaryToken = token.getValue();
- assertNotEquals(activity.token, temporaryToken);
- mTransaction.reparentActivityToTaskFragment(mFragmentToken, temporaryToken);
- mWindowOrganizerController.applyTransaction(mTransaction);
+ verify(mOrganizer).onTransactionReady(mTransactionCaptor.capture());
+ final TaskFragmentTransaction transaction = mTransactionCaptor.getValue();
+ final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
+ assertFalse(changes.isEmpty());
+ final TaskFragmentTransaction.Change change = changes.get(0);
+ assertEquals(TYPE_ACTIVITY_REPARENTED_TO_TASK, change.getType());
+ assertEquals(task.mTaskId, change.getTaskId());
+ assertEquals(activity.intent, change.getActivityIntent());
+ assertNotEquals(activity.token, change.getActivityToken());
+ mTransaction.reparentActivityToTaskFragment(mFragmentToken, change.getActivityToken());
+ assertApplyTransactionAllowed(mTransaction);
assertEquals(mTaskFragment, activity.getTaskFragment());
// The temporary token can only be used once.
- assertNull(mController.getReparentActivityFromTemporaryToken(mIOrganizer, temporaryToken));
+ assertNull(mController.getReparentActivityFromTemporaryToken(mIOrganizer,
+ change.getActivityToken()));
}
@Test
public void testRegisterRemoteAnimations() {
- mController.registerOrganizer(mIOrganizer);
mController.registerRemoteAnimations(mIOrganizer, TASK_ID, mDefinition);
assertEquals(mDefinition, mController.getRemoteAnimationDefinition(mIOrganizer, TASK_ID));
@@ -404,23 +419,7 @@
}
@Test
- public void testWindowContainerTransaction_setTaskFragmentOrganizer() {
- mOrganizer.applyTransaction(mTransaction);
-
- assertEquals(mIOrganizer, mTransaction.getTaskFragmentOrganizer());
-
- mTransaction = new WindowContainerTransaction();
- mOrganizer.applySyncTransaction(
- mTransaction, mock(WindowContainerTransactionCallback.class));
-
- assertEquals(mIOrganizer, mTransaction.getTaskFragmentOrganizer());
- }
-
- @Test
- public void testApplyTransaction_enforceConfigurationChangeOnOrganizedTaskFragment()
- throws RemoteException {
- mOrganizer.applyTransaction(mTransaction);
-
+ public void testApplyTransaction_enforceConfigurationChangeOnOrganizedTaskFragment() {
// Throw exception if the transaction is trying to change a window that is not organized by
// the organizer.
mTransaction.setBounds(mFragmentWindowToken, new Rect(0, 0, 100, 100));
@@ -434,28 +433,9 @@
assertApplyTransactionAllowed(mTransaction);
}
- @Test
- public void testApplyTransaction_enforceHierarchyChange_reorder() throws RemoteException {
- mOrganizer.applyTransaction(mTransaction);
-
- // Throw exception if the transaction is trying to change a window that is not organized by
- // the organizer.
- mTransaction.reorder(mFragmentWindowToken, true /* onTop */);
-
- assertApplyTransactionDisallowed(mTransaction);
-
- // Allow transaction to change a TaskFragment created by the organizer.
- mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
- "Test:TaskFragmentOrganizer" /* processName */);
-
- assertApplyTransactionAllowed(mTransaction);
- }
@Test
- public void testApplyTransaction_enforceHierarchyChange_deleteTaskFragment()
- throws RemoteException {
- mController.registerOrganizer(mIOrganizer);
- mOrganizer.applyTransaction(mTransaction);
+ public void testApplyTransaction_enforceHierarchyChange_deleteTaskFragment() {
doReturn(true).when(mTaskFragment).isAttached();
// Throw exception if the transaction is trying to change a window that is not organized by
@@ -481,13 +461,10 @@
}
@Test
- public void testApplyTransaction_enforceHierarchyChange_setAdjacentRoots()
- throws RemoteException {
- mAtm.mTaskFragmentOrganizerController.registerOrganizer(mIOrganizer);
+ public void testApplyTransaction_enforceHierarchyChange_setAdjacentRoots() {
final TaskFragment taskFragment2 =
new TaskFragment(mAtm, new Binder(), true /* createdByOrganizer */);
final WindowContainerToken token2 = taskFragment2.mRemoteToken.toWindowContainerToken();
- mOrganizer.applyTransaction(mTransaction);
// Throw exception if the transaction is trying to change a window that is not organized by
// the organizer.
@@ -508,9 +485,7 @@
}
@Test
- public void testApplyTransaction_enforceHierarchyChange_createTaskFragment()
- throws RemoteException {
- mController.registerOrganizer(mIOrganizer);
+ public void testApplyTransaction_enforceHierarchyChange_createTaskFragment() {
final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent);
final IBinder fragmentToken = new Binder();
@@ -521,54 +496,149 @@
mTransaction.reparentActivityToTaskFragment(mFragmentToken, mock(IBinder.class));
mTransaction.setAdjacentTaskFragments(mFragmentToken, mock(IBinder.class),
null /* options */);
- mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
// Successfully created a TaskFragment.
- final TaskFragment taskFragment = mAtm.mWindowOrganizerController
- .getTaskFragment(fragmentToken);
+ final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(fragmentToken);
assertNotNull(taskFragment);
assertEquals(ownerActivity.getTask(), taskFragment.getTask());
}
@Test
- public void testApplyTransaction_createTaskFragment_failForDifferentUid()
- throws RemoteException {
- mController.registerOrganizer(mIOrganizer);
+ public void testApplyTransaction_enforceTaskFragmentOrganized_startActivityInTaskFragment() {
+ final Task task = createTask(mDisplayContent);
+ final ActivityRecord ownerActivity = createActivityRecord(task);
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(mFragmentToken)
+ .build();
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ mTransaction.startActivityInTaskFragment(
+ mFragmentToken, ownerActivity.token, new Intent(), null /* activityOptions */);
+ mOrganizer.applyTransaction(mTransaction);
+
+ // Not allowed because TaskFragment is not organized by the caller organizer.
+ assertApplyTransactionDisallowed(mTransaction);
+
+ mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
+ "Test:TaskFragmentOrganizer" /* processName */);
+
+ assertApplyTransactionAllowed(mTransaction);
+ }
+
+ @Test
+ public void testApplyTransaction_enforceTaskFragmentOrganized_reparentActivityInTaskFragment() {
+ final Task task = createTask(mDisplayContent);
+ final ActivityRecord activity = createActivityRecord(task);
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(mFragmentToken)
+ .build();
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token);
+ mOrganizer.applyTransaction(mTransaction);
+
+ // Not allowed because TaskFragment is not organized by the caller organizer.
+ assertApplyTransactionDisallowed(mTransaction);
+
+ mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
+ "Test:TaskFragmentOrganizer" /* processName */);
+
+ assertApplyTransactionAllowed(mTransaction);
+ }
+
+ @Test
+ public void testApplyTransaction_enforceTaskFragmentOrganized_setAdjacentTaskFragments() {
+ final Task task = createTask(mDisplayContent);
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(mFragmentToken)
+ .build();
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ final IBinder fragmentToken2 = new Binder();
+ final TaskFragment taskFragment2 = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(fragmentToken2)
+ .build();
+ mWindowOrganizerController.mLaunchTaskFragments.put(fragmentToken2, taskFragment2);
+ mTransaction.setAdjacentTaskFragments(mFragmentToken, fragmentToken2, null /* params */);
+ mOrganizer.applyTransaction(mTransaction);
+
+ // Not allowed because TaskFragments are not organized by the caller organizer.
+ assertApplyTransactionDisallowed(mTransaction);
+
+ mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
+ "Test:TaskFragmentOrganizer" /* processName */);
+
+ // Not allowed because TaskFragment2 is not organized by the caller organizer.
+ assertApplyTransactionDisallowed(mTransaction);
+
+ mTaskFragment.onTaskFragmentOrganizerRemoved();
+ taskFragment2.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
+ "Test:TaskFragmentOrganizer" /* processName */);
+
+ // Not allowed because mTaskFragment is not organized by the caller organizer.
+ assertApplyTransactionDisallowed(mTransaction);
+
+ mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
+ "Test:TaskFragmentOrganizer" /* processName */);
+
+ assertApplyTransactionAllowed(mTransaction);
+ }
+
+ @Test
+ public void testApplyTransaction_enforceTaskFragmentOrganized_requestFocusOnTaskFragment() {
+ final Task task = createTask(mDisplayContent);
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(mFragmentToken)
+ .build();
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ mTransaction.requestFocusOnTaskFragment(mFragmentToken);
+ mOrganizer.applyTransaction(mTransaction);
+
+ // Not allowed because TaskFragment is not organized by the caller organizer.
+ assertApplyTransactionDisallowed(mTransaction);
+
+ mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
+ "Test:TaskFragmentOrganizer" /* processName */);
+
+ assertApplyTransactionAllowed(mTransaction);
+ }
+
+ @Test
+ public void testApplyTransaction_createTaskFragment_failForDifferentUid() {
final ActivityRecord activity = createActivityRecord(mDisplayContent);
final int uid = Binder.getCallingUid();
final IBinder fragmentToken = new Binder();
final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
mOrganizerToken, fragmentToken, activity.token).build();
- mOrganizer.applyTransaction(mTransaction);
mTransaction.createTaskFragment(params);
// Fail to create TaskFragment when the task uid is different from caller.
activity.info.applicationInfo.uid = uid;
activity.getTask().effectiveUid = uid + 1;
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
// Fail to create TaskFragment when the task uid is different from owner activity.
activity.info.applicationInfo.uid = uid + 1;
activity.getTask().effectiveUid = uid;
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
// Successfully created a TaskFragment for same uid.
activity.info.applicationInfo.uid = uid;
activity.getTask().effectiveUid = uid;
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
assertNotNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
}
@Test
- public void testApplyTransaction_enforceHierarchyChange_reparentChildren()
- throws RemoteException {
- mOrganizer.applyTransaction(mTransaction);
- mController.registerOrganizer(mIOrganizer);
+ public void testApplyTransaction_enforceHierarchyChange_reparentChildren() {
doReturn(true).when(mTaskFragment).isAttached();
// Throw exception if the transaction is trying to change a window that is not organized by
@@ -588,31 +658,29 @@
}
@Test
- public void testApplyTransaction_reparentActivityToTaskFragment_triggerLifecycleUpdate()
- throws RemoteException {
+ public void testApplyTransaction_reparentActivityToTaskFragment_triggerLifecycleUpdate() {
final Task task = createTask(mDisplayContent);
final ActivityRecord activity = createActivityRecord(task);
+ // Skip manipulate the SurfaceControl.
+ doNothing().when(activity).setDropInputMode(anyInt());
mOrganizer.applyTransaction(mTransaction);
- mController.registerOrganizer(mIOrganizer);
mTaskFragment = new TaskFragmentBuilder(mAtm)
.setParentTask(task)
.setFragmentToken(mFragmentToken)
+ .setOrganizer(mOrganizer)
.build();
- mWindowOrganizerController.mLaunchTaskFragments
- .put(mFragmentToken, mTaskFragment);
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token);
doReturn(EMBEDDING_ALLOWED).when(mTaskFragment).isAllowedToEmbedActivity(activity);
clearInvocations(mAtm.mRootWindowContainer);
- mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities();
}
@Test
public void testApplyTransaction_requestFocusOnTaskFragment() {
- mOrganizer.applyTransaction(mTransaction);
- mController.registerOrganizer(mIOrganizer);
final Task task = createTask(mDisplayContent);
final IBinder token0 = new Binder();
final TaskFragment tf0 = new TaskFragmentBuilder(mAtm)
@@ -637,7 +705,7 @@
final ActivityRecord activityInOtherTask = createActivityRecord(mDefaultDisplay);
mDisplayContent.setFocusedApp(activityInOtherTask);
mTransaction.requestFocusOnTaskFragment(token0);
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
assertEquals(activityInOtherTask, mDisplayContent.mFocusedApp);
@@ -645,7 +713,7 @@
activity0.setState(ActivityRecord.State.PAUSED, "test");
activity1.setState(ActivityRecord.State.RESUMED, "test");
mDisplayContent.setFocusedApp(activity1);
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
assertEquals(activity1, mDisplayContent.mFocusedApp);
@@ -653,28 +721,29 @@
// has a resumed activity.
activity0.setState(ActivityRecord.State.RESUMED, "test");
mDisplayContent.setFocusedApp(activity1);
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
assertEquals(activity0, mDisplayContent.mFocusedApp);
}
@Test
public void testApplyTransaction_skipTransactionForUnregisterOrganizer() {
+ mController.unregisterOrganizer(mIOrganizer);
final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent);
final IBinder fragmentToken = new Binder();
// Allow organizer to create TaskFragment and start/reparent activity to TaskFragment.
createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
// Nothing should happen as the organizer is not registered.
- assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+ assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
mController.registerOrganizer(mIOrganizer);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
// Successfully created when the organizer is registered.
- assertNotNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+ assertNotNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
}
@Test
@@ -686,13 +755,13 @@
// Not allow to start activity in a TaskFragment that is in a PIP Task.
mTransaction.startActivityInTaskFragment(
- mFragmentToken, activity.token, new Intent(), null /* activityOptions */)
+ mFragmentToken, activity.token, new Intent(), null /* activityOptions */)
.setErrorCallbackToken(mErrorToken);
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
verify(mAtm.getActivityStartController(), never()).startActivityInTaskFragment(any(), any(),
any(), any(), anyInt(), anyInt(), any());
- verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
+ verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
eq(mErrorToken), eq(mTaskFragment),
eq(HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT),
any(IllegalArgumentException.class));
@@ -707,7 +776,7 @@
// Not allow to reparent activity to a TaskFragment that is in a PIP Task.
mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token)
.setErrorCallbackToken(mErrorToken);
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
eq(mErrorToken), eq(mTaskFragment),
@@ -723,9 +792,9 @@
// Not allow to set adjacent on a TaskFragment that is in a PIP Task.
mTransaction.setAdjacentTaskFragments(mFragmentToken, null /* fragmentToken2 */,
- null /* options */)
+ null /* options */)
.setErrorCallbackToken(mErrorToken);
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
eq(mErrorToken), eq(mTaskFragment),
@@ -736,7 +805,6 @@
@Test
public void testTaskFragmentInPip_createTaskFragment() {
- mController.registerOrganizer(mIOrganizer);
final Task pipTask = createTask(mDisplayContent, WINDOWING_MODE_PINNED,
ACTIVITY_TYPE_STANDARD);
final ActivityRecord activity = createActivityRecord(pipTask);
@@ -746,7 +814,7 @@
// Not allow to create TaskFragment in a PIP Task.
createTaskFragmentFromOrganizer(mTransaction, activity, fragmentToken);
mTransaction.setErrorCallbackToken(mErrorToken);
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
eq(mErrorToken), eq(null), eq(HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT),
@@ -762,7 +830,7 @@
// Not allow to delete a TaskFragment that is in a PIP Task.
mTransaction.deleteTaskFragment(mFragmentWindowToken)
.setErrorCallbackToken(mErrorToken);
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
eq(mErrorToken), eq(mTaskFragment), eq(HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT),
@@ -772,7 +840,7 @@
// Allow organizer to delete empty TaskFragment for cleanup.
final Task task = mTaskFragment.getTask();
mTaskFragment.removeChild(mTaskFragment.getTopMostActivity());
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
assertNull(mWindowOrganizerController.getTaskFragment(mFragmentToken));
assertNull(task.getTopChild());
@@ -803,13 +871,12 @@
doReturn(false).when(task).shouldBeVisible(any());
// Sending events
- mController.registerOrganizer(mIOrganizer);
taskFragment.mTaskFragmentAppearedSent = true;
mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
mController.dispatchPendingEvents();
// Verifies that event was not sent
- verify(mOrganizer, never()).onTaskFragmentInfoChanged(any(), any());
+ verify(mOrganizer, never()).onTransactionReady(any());
}
@Test
@@ -829,13 +896,12 @@
taskFragment.setResumedActivity(null, "test");
// Sending events
- mController.registerOrganizer(mIOrganizer);
taskFragment.mTaskFragmentAppearedSent = true;
mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
mController.dispatchPendingEvents();
// Verifies that event was not sent
- verify(mOrganizer, never()).onTaskFragmentInfoChanged(any(), any());
+ verify(mOrganizer, never()).onTransactionReady(any());
// Mock the task becomes visible, and activity resumed
doReturn(true).when(task).shouldBeVisible(any());
@@ -843,7 +909,7 @@
// Verifies that event is sent.
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentInfoChanged(any(), any());
+ verify(mOrganizer).onTransactionReady(any());
}
/**
@@ -864,7 +930,6 @@
assertTrue(parentTask.shouldBeVisible(null));
// Dispatch pending info changed event from creating the activity
- mController.registerOrganizer(mIOrganizer);
taskFragment.mTaskFragmentAppearedSent = true;
mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
mController.dispatchPendingEvents();
@@ -877,7 +942,7 @@
clearInvocations(mOrganizer);
mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentInfoChanged(any(), any());
+ verify(mOrganizer).onTransactionReady(any());
}
/**
@@ -900,25 +965,24 @@
assertTrue(task.shouldBeVisible(null));
// Dispatch pending info changed event from creating the activity
- mController.registerOrganizer(mIOrganizer);
taskFragment.mTaskFragmentAppearedSent = true;
mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentInfoChanged(any(), any());
+ verify(mOrganizer).onTransactionReady(any());
// Verify the info changed callback is not called when the task is invisible
clearInvocations(mOrganizer);
doReturn(false).when(task).shouldBeVisible(any());
mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer, never()).onTaskFragmentInfoChanged(any(), any());
+ verify(mOrganizer, never()).onTransactionReady(any());
// Finish the embedded activity, and verify the info changed callback is called because the
// TaskFragment is becoming empty.
embeddedActivity.finishing = true;
mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentInfoChanged(any(), any());
+ verify(mOrganizer).onTransactionReady(any());
}
/**
@@ -926,13 +990,11 @@
* {@link WindowOrganizerController}.
*/
@Test
- public void testTaskFragmentRemoved_cleanUpEmbeddedTaskFragment()
- throws RemoteException {
- mController.registerOrganizer(mIOrganizer);
+ public void testTaskFragmentRemoved_cleanUpEmbeddedTaskFragment() {
final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent);
final IBinder fragmentToken = new Binder();
createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken);
- mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(fragmentToken);
assertNotNull(taskFragment);
@@ -947,9 +1009,7 @@
* its parent bounds.
*/
@Test
- public void testUntrustedEmbedding_configChange() throws RemoteException {
- mController.registerOrganizer(mIOrganizer);
- mOrganizer.applyTransaction(mTransaction);
+ public void testUntrustedEmbedding_configChange() {
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
"Test:TaskFragmentOrganizer" /* processName */);
doReturn(false).when(mTaskFragment).isAllowedToBeEmbeddedInTrustedMode();
@@ -1010,8 +1070,6 @@
// Make minWidth/minHeight exceeds the TaskFragment bounds.
activity.info.windowLayout = new ActivityInfo.WindowLayout(
0, 0, 0, 0, 0, mTaskFragBounds.width() + 10, mTaskFragBounds.height() + 10);
- mOrganizer.applyTransaction(mTransaction);
- mController.registerOrganizer(mIOrganizer);
mTaskFragment = new TaskFragmentBuilder(mAtm)
.setParentTask(task)
.setFragmentToken(mFragmentToken)
@@ -1024,20 +1082,17 @@
// minimum dimensions.
mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token)
.setErrorCallbackToken(mErrorToken);
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
// The pending event will be dispatched on the handler (from requestTraversal).
waitHandlerIdle(mWm.mAnimationHandler);
- verify(mOrganizer).onTaskFragmentError(any(), eq(mErrorToken), any(),
- eq(HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT),
- any(SecurityException.class));
+ assertTaskFragmentErrorTransaction(HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT,
+ SecurityException.class);
}
@Test
public void testMinDimensionViolation_ReparentChildren() {
final Task task = createTask(mDisplayContent);
- mOrganizer.applyTransaction(mTransaction);
- mController.registerOrganizer(mIOrganizer);
final IBinder oldFragToken = new Binder();
final TaskFragment oldTaskFrag = new TaskFragmentBuilder(mAtm)
.setParentTask(task)
@@ -1063,19 +1118,17 @@
mTransaction.reparentChildren(oldTaskFrag.mRemoteToken.toWindowContainerToken(),
mTaskFragment.mRemoteToken.toWindowContainerToken())
.setErrorCallbackToken(mErrorToken);
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
// The pending event will be dispatched on the handler (from requestTraversal).
waitHandlerIdle(mWm.mAnimationHandler);
- verify(mOrganizer).onTaskFragmentError(any(), eq(mErrorToken), any(),
- eq(HIERARCHY_OP_TYPE_REPARENT_CHILDREN), any(SecurityException.class));
+ assertTaskFragmentErrorTransaction(HIERARCHY_OP_TYPE_REPARENT_CHILDREN,
+ SecurityException.class);
}
@Test
public void testMinDimensionViolation_SetBounds() {
final Task task = createTask(mDisplayContent);
- mOrganizer.applyTransaction(mTransaction);
- mController.registerOrganizer(mIOrganizer);
mTaskFragment = new TaskFragmentBuilder(mAtm)
.setParentTask(task)
.createActivityCount(1)
@@ -1094,7 +1147,7 @@
// minimum dimensions.
mTransaction.setBounds(mTaskFragment.mRemoteToken.toWindowContainerToken(), mTaskFragBounds)
.setErrorCallbackToken(mErrorToken);
- mWindowOrganizerController.applyTransaction(mTransaction);
+ assertApplyTransactionAllowed(mTransaction);
assertWithMessage("setBounds must not be performed.")
.that(mTaskFragment.getBounds()).isEqualTo(task.getBounds());
@@ -1102,35 +1155,38 @@
@Test
public void testOnTransactionReady_invokeOnTransactionHandled() {
- mController.registerOrganizer(mIOrganizer);
final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
mOrganizer.onTransactionReady(transaction);
// Organizer should always trigger #onTransactionHandled when receives #onTransactionReady
- verify(mOrganizer).onTransactionHandled(eq(transaction.getTransactionToken()), any());
- verify(mOrganizer, never()).applyTransaction(any());
+ verify(mOrganizer).onTransactionHandled(eq(transaction.getTransactionToken()), any(),
+ anyInt(), anyBoolean());
+ verify(mOrganizer, never()).applyTransaction(any(), anyInt(), anyBoolean());
}
@Test
public void testDispatchTransaction_deferTransitionReady() {
- mController.registerOrganizer(mIOrganizer);
setupMockParent(mTaskFragment, mTask);
final ArgumentCaptor<IBinder> tokenCaptor = ArgumentCaptor.forClass(IBinder.class);
final ArgumentCaptor<WindowContainerTransaction> wctCaptor =
ArgumentCaptor.forClass(WindowContainerTransaction.class);
doReturn(true).when(mTransitionController).isCollecting();
+ doReturn(10).when(mTransitionController).getCollectingTransitionId();
mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
// Defer transition when send TaskFragment transaction during transition collection.
verify(mTransitionController).deferTransitionReady();
- verify(mOrganizer).onTransactionHandled(tokenCaptor.capture(), wctCaptor.capture());
+ verify(mOrganizer).onTransactionHandled(tokenCaptor.capture(), wctCaptor.capture(),
+ anyInt(), anyBoolean());
- mController.onTransactionHandled(mIOrganizer, tokenCaptor.getValue(), wctCaptor.getValue());
+ final IBinder transactionToken = tokenCaptor.getValue();
+ final WindowContainerTransaction wct = wctCaptor.getValue();
+ wct.setTaskFragmentOrganizer(mIOrganizer);
+ mController.onTransactionHandled(transactionToken, wct, getTransitionType(wct),
+ false /* shouldApplyIndependently */);
- // Apply the organizer change and continue transition.
- verify(mWindowOrganizerController).applyTransaction(wctCaptor.getValue());
verify(mTransitionController).continueTransitionReady();
}
@@ -1145,7 +1201,7 @@
ownerActivity.getTask().effectiveUid = uid;
final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
mOrganizerToken, fragmentToken, ownerActivity.token).build();
- mOrganizer.applyTransaction(wct);
+ wct.setTaskFragmentOrganizer(mIOrganizer);
// Allow organizer to create TaskFragment and start/reparent activity to TaskFragment.
wct.createTaskFragment(params);
@@ -1153,28 +1209,99 @@
/** Asserts that applying the given transaction will throw a {@link SecurityException}. */
private void assertApplyTransactionDisallowed(WindowContainerTransaction t) {
- assertThrows(SecurityException.class, () -> {
- try {
- mAtm.getWindowOrganizerController().applyTransaction(t);
- } catch (RemoteException e) {
- fail();
- }
- });
+ assertThrows(SecurityException.class, () ->
+ mController.applyTransaction(t, getTransitionType(t),
+ false /* shouldApplyIndependently */));
}
/** Asserts that applying the given transaction will not throw any exception. */
private void assertApplyTransactionAllowed(WindowContainerTransaction t) {
- try {
- mAtm.getWindowOrganizerController().applyTransaction(t);
- } catch (RemoteException e) {
- fail();
- }
+ mController.applyTransaction(t, getTransitionType(t), false /* shouldApplyIndependently */);
+ }
+
+ /** Asserts that there will be a transaction for TaskFragment appeared. */
+ private void assertTaskFragmentAppearedTransaction() {
+ verify(mOrganizer).onTransactionReady(mTransactionCaptor.capture());
+ final TaskFragmentTransaction transaction = mTransactionCaptor.getValue();
+ final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
+ assertFalse(changes.isEmpty());
+
+ // Appeared will come with parent info changed.
+ final TaskFragmentTransaction.Change change = changes.get(changes.size() - 1);
+ assertEquals(TYPE_TASK_FRAGMENT_APPEARED, change.getType());
+ assertEquals(mTaskFragmentInfo, change.getTaskFragmentInfo());
+ assertEquals(mFragmentToken, change.getTaskFragmentToken());
+ }
+
+ /** Asserts that there will be a transaction for TaskFragment info changed. */
+ private void assertTaskFragmentInfoChangedTransaction() {
+ verify(mOrganizer).onTransactionReady(mTransactionCaptor.capture());
+ final TaskFragmentTransaction transaction = mTransactionCaptor.getValue();
+ final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
+ assertFalse(changes.isEmpty());
+
+ // InfoChanged may come with parent info changed.
+ final TaskFragmentTransaction.Change change = changes.get(changes.size() - 1);
+ assertEquals(TYPE_TASK_FRAGMENT_INFO_CHANGED, change.getType());
+ assertEquals(mTaskFragmentInfo, change.getTaskFragmentInfo());
+ assertEquals(mFragmentToken, change.getTaskFragmentToken());
+ }
+
+ /** Asserts that there will be a transaction for TaskFragment vanished. */
+ private void assertTaskFragmentVanishedTransaction() {
+ verify(mOrganizer).onTransactionReady(mTransactionCaptor.capture());
+ final TaskFragmentTransaction transaction = mTransactionCaptor.getValue();
+ final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
+ assertFalse(changes.isEmpty());
+ final TaskFragmentTransaction.Change change = changes.get(0);
+ assertEquals(TYPE_TASK_FRAGMENT_VANISHED, change.getType());
+ assertEquals(mTaskFragmentInfo, change.getTaskFragmentInfo());
+ assertEquals(mFragmentToken, change.getTaskFragmentToken());
+ }
+
+ /** Asserts that there will be a transaction for TaskFragment vanished. */
+ private void assertTaskFragmentParentInfoChangedTransaction(@NonNull Task task) {
+ verify(mOrganizer).onTransactionReady(mTransactionCaptor.capture());
+ final TaskFragmentTransaction transaction = mTransactionCaptor.getValue();
+ final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
+ assertFalse(changes.isEmpty());
+ final TaskFragmentTransaction.Change change = changes.get(0);
+ assertEquals(TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED, change.getType());
+ assertEquals(task.mTaskId, change.getTaskId());
+ assertEquals(task.getConfiguration(), change.getTaskConfiguration());
+ }
+
+ /** Asserts that there will be a transaction for TaskFragment error. */
+ private void assertTaskFragmentErrorTransaction(int opType, @NonNull Class<?> exceptionClass) {
+ verify(mOrganizer).onTransactionReady(mTransactionCaptor.capture());
+ final TaskFragmentTransaction transaction = mTransactionCaptor.getValue();
+ final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
+ assertFalse(changes.isEmpty());
+ final TaskFragmentTransaction.Change change = changes.get(0);
+ assertEquals(TYPE_TASK_FRAGMENT_ERROR, change.getType());
+ assertEquals(mErrorToken, change.getErrorCallbackToken());
+ final Bundle errorBundle = change.getErrorBundle();
+ assertEquals(opType, errorBundle.getInt(KEY_ERROR_CALLBACK_OP_TYPE));
+ assertEquals(exceptionClass, errorBundle.getSerializable(
+ KEY_ERROR_CALLBACK_THROWABLE, Throwable.class).getClass());
+ }
+
+ /** Asserts that there will be a transaction for activity reparented to Task. */
+ private void assertActivityReparentedToTaskTransaction(int taskId, @NonNull Intent intent,
+ @NonNull IBinder activityToken) {
+ verify(mOrganizer).onTransactionReady(mTransactionCaptor.capture());
+ final TaskFragmentTransaction transaction = mTransactionCaptor.getValue();
+ final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
+ assertFalse(changes.isEmpty());
+ final TaskFragmentTransaction.Change change = changes.get(0);
+ assertEquals(TYPE_ACTIVITY_REPARENTED_TO_TASK, change.getType());
+ assertEquals(taskId, change.getTaskId());
+ assertEquals(intent, change.getActivityIntent());
+ assertEquals(activityToken, change.getActivityToken());
}
/** Setups an embedded TaskFragment in a PIP Task. */
private void setupTaskFragmentInPip() {
- mOrganizer.applyTransaction(mTransaction);
- mController.registerOrganizer(mIOrganizer);
mTaskFragment = new TaskFragmentBuilder(mAtm)
.setCreateParentTask()
.setFragmentToken(mFragmentToken)
@@ -1182,8 +1309,7 @@
.createActivityCount(1)
.build();
mFragmentWindowToken = mTaskFragment.mRemoteToken.toWindowContainerToken();
- mAtm.mWindowOrganizerController.mLaunchTaskFragments
- .put(mFragmentToken, mTaskFragment);
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
mTaskFragment.getTask().setWindowingMode(WINDOWING_MODE_PINNED);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index 1e64e46..f5304d0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -18,6 +18,13 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT;
+import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
+import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
+import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.ITYPE_RIGHT_DISPLAY_CUTOUT;
+import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsState.ITYPE_TOP_DISPLAY_CUTOUT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
@@ -26,12 +33,9 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
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.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doReturn;
-
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
@@ -43,6 +47,7 @@
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
+import android.view.WindowInsets;
import com.android.server.wm.DisplayWindowSettings.SettingsProvider.SettingsEntry;
@@ -204,7 +209,26 @@
doReturn(true).when(newDisplay).supportsSystemDecorations();
doReturn(true).when(displayPolicy).hasNavigationBar();
doReturn(NAV_BAR_BOTTOM).when(displayPolicy).navigationBarPosition(anyInt());
- doReturn(20).when(displayPolicy).getNavigationBarHeight(anyInt());
+ doReturn(Insets.of(0, 0, 0, 20)).when(displayPolicy).getInsets(any(),
+ eq(WindowInsets.Type.displayCutout() | WindowInsets.Type.navigationBars()));
+ doReturn(Insets.of(0, 20, 0, 20)).when(displayPolicy).getInsets(any(),
+ eq(WindowInsets.Type.displayCutout() | WindowInsets.Type.navigationBars()
+ | WindowInsets.Type.statusBars()));
+ final int[] nonDecorTypes = new int[]{
+ ITYPE_TOP_DISPLAY_CUTOUT, ITYPE_RIGHT_DISPLAY_CUTOUT,
+ ITYPE_BOTTOM_DISPLAY_CUTOUT, ITYPE_LEFT_DISPLAY_CUTOUT, ITYPE_NAVIGATION_BAR
+ };
+ doReturn(Insets.of(0, 0, 0, 20)).when(displayPolicy).getInsetsWithInternalTypes(
+ any(),
+ eq(nonDecorTypes));
+ final int[] stableTypes = new int[]{
+ ITYPE_TOP_DISPLAY_CUTOUT, ITYPE_RIGHT_DISPLAY_CUTOUT,
+ ITYPE_BOTTOM_DISPLAY_CUTOUT, ITYPE_LEFT_DISPLAY_CUTOUT,
+ ITYPE_NAVIGATION_BAR, ITYPE_STATUS_BAR, ITYPE_CLIMATE_BAR
+ };
+ doReturn(Insets.of(0, 20, 0, 20)).when(displayPolicy).getInsetsWithInternalTypes(
+ any(),
+ eq(stableTypes));
} else {
doReturn(false).when(displayPolicy).hasNavigationBar();
doReturn(false).when(displayPolicy).hasStatusBar();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 0f13fb2..4f68e98 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -56,6 +56,7 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
@@ -72,6 +73,7 @@
import android.window.TaskFragmentOrganizer;
import android.window.TransitionInfo;
+import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
import org.junit.Test;
@@ -93,6 +95,7 @@
@RunWith(WindowTestRunner.class)
public class TransitionTests extends WindowTestsBase {
final SurfaceControl.Transaction mMockT = mock(SurfaceControl.Transaction.class);
+ private BLASTSyncEngine mSyncEngine;
private Transition createTestTransition(int transitType) {
TransitionTracer tracer = mock(TransitionTracer.class);
@@ -100,8 +103,8 @@
mock(ActivityTaskManagerService.class), mock(TaskSnapshotController.class),
mock(TransitionTracer.class));
- final BLASTSyncEngine sync = createTestBLASTSyncEngine();
- final Transition t = new Transition(transitType, 0 /* flags */, controller, sync);
+ mSyncEngine = createTestBLASTSyncEngine();
+ final Transition t = new Transition(transitType, 0 /* flags */, controller, mSyncEngine);
t.startCollecting(0 /* timeoutMs */);
return t;
}
@@ -1114,6 +1117,56 @@
assertTrue(targets.contains(activity));
}
+ @Test
+ public void testTransitionVisibleChange() {
+ registerTestTransitionPlayer();
+ final ActivityRecord app = createActivityRecord(mDisplayContent);
+ final Transition transition = new Transition(TRANSIT_OPEN, 0 /* flags */,
+ app.mTransitionController, mWm.mSyncEngine);
+ app.mTransitionController.moveToCollecting(transition, BLASTSyncEngine.METHOD_NONE);
+ final ArrayList<WindowContainer> freezeCalls = new ArrayList<>();
+ transition.setContainerFreezer(new Transition.IContainerFreezer() {
+ @Override
+ public boolean freeze(@NonNull WindowContainer wc, @NonNull Rect bounds) {
+ freezeCalls.add(wc);
+ return true;
+ }
+
+ @Override
+ public void cleanUp(SurfaceControl.Transaction t) {
+ }
+ });
+ final Task task = app.getTask();
+ transition.collect(task);
+ final Rect bounds = new Rect(task.getBounds());
+ Configuration c = new Configuration(task.getRequestedOverrideConfiguration());
+ bounds.inset(10, 10);
+ c.windowConfiguration.setBounds(bounds);
+ task.onRequestedOverrideConfigurationChanged(c);
+ assertTrue(freezeCalls.contains(task));
+ transition.abort();
+ }
+
+ @Test
+ public void testDeferTransitionReady_deferStartedTransition() {
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
+ transition.setAllReady();
+ transition.start();
+
+ assertTrue(mSyncEngine.isReady(transition.getSyncId()));
+
+ transition.deferTransitionReady();
+
+ // Both transition ready tracker and sync engine should be deferred.
+ assertFalse(transition.allReady());
+ assertFalse(mSyncEngine.isReady(transition.getSyncId()));
+
+ transition.continueTransitionReady();
+
+ assertTrue(transition.allReady());
+ assertTrue(mSyncEngine.isReady(transition.getSyncId()));
+ }
+
private static void makeTaskOrganized(Task... tasks) {
final ITaskOrganizer organizer = mock(ITaskOrganizer.class);
for (Task t : tasks) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index fba4ff1..8288713 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -33,17 +33,21 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
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.verify;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
@@ -61,9 +65,12 @@
import com.android.server.wm.utils.WmDisplayCutout;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.List;
+
/**
* Tests for the {@link WallpaperController} class.
*
@@ -74,6 +81,18 @@
@Presubmit
@RunWith(WindowTestRunner.class)
public class WallpaperControllerTests extends WindowTestsBase {
+ private static final int INITIAL_WIDTH = 600;
+ private static final int INITIAL_HEIGHT = 900;
+ private static final int SECOND_WIDTH = 300;
+
+ @Before
+ public void setup() {
+ Resources resources = mWm.mContext.getResources();
+ spyOn(resources);
+ doReturn(false).when(resources).getBoolean(
+ com.android.internal.R.bool.config_offsetWallpaperToCenterOfLargestDisplay);
+ }
+
@Test
public void testWallpaperScreenshot() {
WindowSurfaceController windowSurfaceController = mock(WindowSurfaceController.class);
@@ -365,6 +384,108 @@
assertTrue(token.isVisible());
}
+ private static void prepareSmallerSecondDisplay(DisplayContent dc, int width, int height) {
+ spyOn(dc.mWmService);
+ DisplayInfo firstDisplay = dc.getDisplayInfo();
+ DisplayInfo secondDisplay = new DisplayInfo(firstDisplay);
+ // Second display is narrower than first display.
+ secondDisplay.logicalWidth = width;
+ secondDisplay.logicalHeight = height;
+ doReturn(List.of(firstDisplay, secondDisplay)).when(
+ dc.mWmService).getPossibleDisplayInfoLocked(anyInt());
+ }
+
+ private static void resizeDisplayAndWallpaper(DisplayContent dc, WindowState wallpaperWindow,
+ int width, int height) {
+ dc.setBounds(0, 0, width, height);
+ dc.updateOrientation();
+ dc.sendNewConfiguration();
+ spyOn(wallpaperWindow);
+ doReturn(new Rect(0, 0, width, height)).when(wallpaperWindow).getLastReportedBounds();
+ }
+
+ @Test
+ public void testUpdateWallpaperOffset_initial_shouldCenterDisabled() {
+ final DisplayContent dc = new TestDisplayContent.Builder(mAtm, INITIAL_WIDTH,
+ INITIAL_HEIGHT).build();
+ dc.mWallpaperController.setShouldOffsetWallpaperCenter(false);
+ prepareSmallerSecondDisplay(dc, SECOND_WIDTH, INITIAL_HEIGHT);
+ final WindowState wallpaperWindow = createWallpaperWindow(dc, INITIAL_WIDTH,
+ INITIAL_HEIGHT);
+
+ dc.mWallpaperController.updateWallpaperOffset(wallpaperWindow, false);
+
+ // Wallpaper centering is disabled, so no offset.
+ assertThat(wallpaperWindow.mXOffset).isEqualTo(0);
+ assertThat(wallpaperWindow.mYOffset).isEqualTo(0);
+ }
+
+ @Test
+ public void testUpdateWallpaperOffset_initial_shouldCenterEnabled() {
+ final DisplayContent dc = new TestDisplayContent.Builder(mAtm, INITIAL_WIDTH,
+ INITIAL_HEIGHT).build();
+ dc.mWallpaperController.setShouldOffsetWallpaperCenter(true);
+ prepareSmallerSecondDisplay(dc, SECOND_WIDTH, INITIAL_HEIGHT);
+ final WindowState wallpaperWindow = createWallpaperWindow(dc, INITIAL_WIDTH,
+ INITIAL_HEIGHT);
+
+ dc.mWallpaperController.updateWallpaperOffset(wallpaperWindow, false);
+
+ // Wallpaper matches first display, so has no offset.
+ assertThat(wallpaperWindow.mXOffset).isEqualTo(0);
+ assertThat(wallpaperWindow.mYOffset).isEqualTo(0);
+ }
+
+ @Test
+ public void testUpdateWallpaperOffset_resize_shouldCenterEnabled() {
+ final DisplayContent dc = new TestDisplayContent.Builder(mAtm, INITIAL_WIDTH,
+ INITIAL_HEIGHT).build();
+ dc.mWallpaperController.setShouldOffsetWallpaperCenter(true);
+ prepareSmallerSecondDisplay(dc, SECOND_WIDTH, INITIAL_HEIGHT);
+ final WindowState wallpaperWindow = createWallpaperWindow(dc, INITIAL_WIDTH,
+ INITIAL_HEIGHT);
+
+ dc.mWallpaperController.updateWallpaperOffset(wallpaperWindow, false);
+
+ // Resize display to match second display bounds.
+ resizeDisplayAndWallpaper(dc, wallpaperWindow, SECOND_WIDTH, INITIAL_HEIGHT);
+
+ dc.mWallpaperController.updateWallpaperOffset(wallpaperWindow, false);
+
+ // Wallpaper is 300 wider than second display.
+ assertThat(wallpaperWindow.mXOffset).isEqualTo(-Math.abs(INITIAL_WIDTH - SECOND_WIDTH) / 2);
+ assertThat(wallpaperWindow.mYOffset).isEqualTo(0);
+ }
+
+ @Test
+ public void testUpdateWallpaperOffset_resize_shouldCenterDisabled() {
+ final DisplayContent dc = new TestDisplayContent.Builder(mAtm, INITIAL_WIDTH,
+ INITIAL_HEIGHT).build();
+ dc.mWallpaperController.setShouldOffsetWallpaperCenter(false);
+ prepareSmallerSecondDisplay(dc, SECOND_WIDTH, INITIAL_HEIGHT);
+ final WindowState wallpaperWindow = createWallpaperWindow(dc, INITIAL_WIDTH,
+ INITIAL_HEIGHT);
+
+ dc.mWallpaperController.updateWallpaperOffset(wallpaperWindow, false);
+
+ // Resize display to match second display bounds.
+ resizeDisplayAndWallpaper(dc, wallpaperWindow, SECOND_WIDTH, INITIAL_HEIGHT);
+
+ dc.mWallpaperController.updateWallpaperOffset(wallpaperWindow, false);
+
+ // Wallpaper is 300 wider than second display, but offset disabled.
+ assertThat(wallpaperWindow.mXOffset).isEqualTo(0);
+ assertThat(wallpaperWindow.mYOffset).isEqualTo(0);
+ }
+
+ private WindowState createWallpaperWindow(DisplayContent dc, int width, int height) {
+ final WindowState wallpaperWindow = createWallpaperWindow(dc);
+ // Wallpaper is cropped to match first display.
+ wallpaperWindow.getWindowFrames().mParentFrame.set(new Rect(0, 0, width, height));
+ wallpaperWindow.getWindowFrames().mFrame.set(0, 0, width, height);
+ return wallpaperWindow;
+ }
+
private WindowState createWallpaperWindow(DisplayContent dc) {
final WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
true /* explicit */, dc, true /* ownerCanManageAppTokens */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTransactionTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTransactionTests.java
new file mode 100644
index 0000000..d255271
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTransactionTests.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.atLeast;
+
+import android.content.Intent;
+import android.platform.test.annotations.Presubmit;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+
+import androidx.annotation.NonNull;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test class for {@link WindowContainerTransaction}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:WindowContainerTransactionTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(WindowTestRunner.class)
+public class WindowContainerTransactionTests extends WindowTestsBase {
+
+ @Test
+ public void testRemoveTask() {
+ final Task rootTask = createTask(mDisplayContent);
+ final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
+ final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
+
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ WindowContainerToken token = task.getTaskInfo().token;
+ wct.removeTask(token);
+ applyTransaction(wct);
+
+ // There is still an activity to be destroyed, so the task is not removed immediately.
+ assertNotNull(task.getParent());
+ assertTrue(rootTask.hasChild());
+ assertTrue(task.hasChild());
+ assertTrue(activity.finishing);
+
+ activity.destroyed("testRemoveContainer");
+ // Assert that the container was removed after the activity is destroyed.
+ assertNull(task.getParent());
+ assertEquals(0, task.getChildCount());
+ assertNull(activity.getParent());
+ verify(mAtm.getLockTaskController(), atLeast(1)).clearLockedTask(task);
+ verify(mAtm.getLockTaskController(), atLeast(1)).clearLockedTask(rootTask);
+ }
+
+ private Task createTask(int taskId) {
+ return new Task.Builder(mAtm)
+ .setTaskId(taskId)
+ .setIntent(new Intent())
+ .setRealActivity(ActivityBuilder.getDefaultComponent())
+ .setEffectiveUid(10050)
+ .buildInner();
+ }
+
+ private void applyTransaction(@NonNull WindowContainerTransaction t) {
+ if (!t.isEmpty()) {
+ mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
+ }
+ }
+}
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 7d4e6fa..24fc93a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -42,8 +42,10 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
+import static com.android.server.wm.BLASTSyncEngine.METHOD_BLAST;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowContainer.SYNC_STATE_READY;
+import static com.android.server.wm.WindowState.BLAST_TIMEOUT_DURATION;
import static com.google.common.truth.Truth.assertThat;
@@ -1000,7 +1002,7 @@
BLASTSyncEngine.TransactionReadyListener transactionListener =
mock(BLASTSyncEngine.TransactionReadyListener.class);
- int id = bse.startSyncSet(transactionListener);
+ int id = bse.startSyncSet(transactionListener, BLAST_TIMEOUT_DURATION, "", METHOD_BLAST);
bse.addToSyncSet(id, task);
bse.setReady(id);
bse.onSurfacePlacement();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index ee5f364..77e12f4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -323,6 +323,10 @@
mNavBarWindow.mAttrs.gravity = Gravity.BOTTOM;
mNavBarWindow.mAttrs.paramsForRotation = new WindowManager.LayoutParams[4];
mNavBarWindow.mAttrs.setFitInsetsTypes(0);
+ mNavBarWindow.mAttrs.layoutInDisplayCutoutMode =
+ LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ mNavBarWindow.mAttrs.privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
mNavBarWindow.mAttrs.paramsForRotation[rot] =
getNavBarLayoutParamsForRotation(rot);
@@ -379,6 +383,9 @@
lp.height = height;
lp.gravity = gravity;
lp.setFitInsetsTypes(0);
+ lp.privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
+ lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
return lp;
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index e032f65..cf6d681 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -584,6 +584,17 @@
KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
/**
+ * List of network capabilities which, if requested, will exempt the request from single PDN
+ * connection checks.
+ * @see NetworkCapabilities NET_CAPABILITY_*
+ * @see #KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY
+ *
+ * @hide
+ */
+ public static final String KEY_CAPABILITIES_EXEMPT_FROM_SINGLE_DC_CHECK_INT_ARRAY =
+ "capabilities_exempt_from_single_dc_check_int_array";
+
+ /**
* Override the platform's notion of a network operator being considered roaming.
* Value is string array of MCCMNCs to be considered roaming for 3GPP RATs.
*/
@@ -8749,6 +8760,8 @@
new int[] {TelephonyManager.NETWORK_TYPE_CDMA, TelephonyManager.NETWORK_TYPE_1xRTT,
TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyManager.NETWORK_TYPE_EVDO_A,
TelephonyManager.NETWORK_TYPE_EVDO_B});
+ sDefaults.putIntArray(KEY_CAPABILITIES_EXEMPT_FROM_SINGLE_DC_CHECK_INT_ARRAY,
+ new int[] {NetworkCapabilities.NET_CAPABILITY_IMS});
sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
sDefaults.putStringArray(KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY, null);
sDefaults.putString(KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, null);
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 5bae1ad..a6ccb22 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -223,6 +223,10 @@
private final int mSubId;
private final BinderCacheManager<ITelephony> mBinderCache;
+ // Cache Telephony Binder interfaces, one cache per process.
+ private static final BinderCacheManager<ITelephony> sTelephonyCache =
+ new BinderCacheManager<>(ImsMmTelManager::getITelephonyInterface);
+
/**
* Create an instance of {@link ImsMmTelManager} for the subscription id specified.
*
@@ -251,8 +255,7 @@
throw new IllegalArgumentException("Invalid subscription ID");
}
- return new ImsMmTelManager(subId, new BinderCacheManager<>(
- ImsMmTelManager::getITelephonyInterface));
+ return new ImsMmTelManager(subId, sTelephonyCache);
}
/**
diff --git a/tests/permission/src/com/android/framework/permission/tests/VibratorManagerServicePermissionTest.java b/tests/permission/src/com/android/framework/permission/tests/VibratorManagerServicePermissionTest.java
index e0f3f03..421ceb7 100644
--- a/tests/permission/src/com/android/framework/permission/tests/VibratorManagerServicePermissionTest.java
+++ b/tests/permission/src/com/android/framework/permission/tests/VibratorManagerServicePermissionTest.java
@@ -50,6 +50,7 @@
public class VibratorManagerServicePermissionTest {
private static final String PACKAGE_NAME = "com.android.framework.permission.tests";
+ private static final int DISPLAY_ID = 1;
private static final CombinedVibration EFFECT =
CombinedVibration.createParallel(
VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
@@ -106,7 +107,8 @@
@Test
public void testVibrateWithoutPermissionFails() throws RemoteException {
expectSecurityException("VIBRATE");
- mVibratorService.vibrate(Process.myUid(), PACKAGE_NAME, EFFECT, ATTRS, "testVibrate",
+ mVibratorService.vibrate(Process.myUid(), DISPLAY_ID, PACKAGE_NAME, EFFECT, ATTRS,
+ "testVibrate",
new Binder());
}
@@ -115,7 +117,8 @@
throws RemoteException {
getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
Manifest.permission.VIBRATE);
- mVibratorService.vibrate(Process.myUid(), PACKAGE_NAME, EFFECT, ATTRS, "testVibrate",
+ mVibratorService.vibrate(Process.myUid(), DISPLAY_ID, PACKAGE_NAME, EFFECT, ATTRS,
+ "testVibrate",
new Binder());
}
@@ -124,7 +127,8 @@
expectSecurityException("UPDATE_APP_OPS_STATS");
getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
Manifest.permission.VIBRATE);
- mVibratorService.vibrate(Process.SYSTEM_UID, "android", EFFECT, ATTRS, "testVibrate",
+ mVibratorService.vibrate(Process.SYSTEM_UID, DISPLAY_ID, "android", EFFECT, ATTRS,
+ "testVibrate",
new Binder());
}
@@ -133,7 +137,8 @@
getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
Manifest.permission.VIBRATE,
Manifest.permission.UPDATE_APP_OPS_STATS);
- mVibratorService.vibrate(Process.SYSTEM_UID, "android", EFFECT, ATTRS, "testVibrate",
+ mVibratorService.vibrate(Process.SYSTEM_UID, DISPLAY_ID, "android", EFFECT, ATTRS,
+ "testVibrate",
new Binder());
}
diff --git a/tests/testables/src/android/testing/TestableLooper.java b/tests/testables/src/android/testing/TestableLooper.java
index ebe9b57..edd6dd3 100644
--- a/tests/testables/src/android/testing/TestableLooper.java
+++ b/tests/testables/src/android/testing/TestableLooper.java
@@ -30,6 +30,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.lang.reflect.Field;
import java.util.Map;
/**
@@ -45,6 +46,9 @@
* catch crashes.
*/
public static final boolean HOLD_MAIN_THREAD = false;
+ private static final Field MESSAGE_QUEUE_MESSAGES_FIELD;
+ private static final Field MESSAGE_NEXT_FIELD;
+ private static final Field MESSAGE_WHEN_FIELD;
private Looper mLooper;
private MessageQueue mQueue;
@@ -54,6 +58,19 @@
private Runnable mEmptyMessage;
private TestLooperManager mQueueWrapper;
+ static {
+ try {
+ MESSAGE_QUEUE_MESSAGES_FIELD = MessageQueue.class.getDeclaredField("mMessages");
+ MESSAGE_QUEUE_MESSAGES_FIELD.setAccessible(true);
+ MESSAGE_NEXT_FIELD = Message.class.getDeclaredField("next");
+ MESSAGE_NEXT_FIELD.setAccessible(true);
+ MESSAGE_WHEN_FIELD = Message.class.getDeclaredField("when");
+ MESSAGE_WHEN_FIELD.setAccessible(true);
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException("Failed to initialize TestableLooper", e);
+ }
+ }
+
public TestableLooper(Looper l) throws Exception {
this(acquireLooperManager(l), l);
}
@@ -119,6 +136,33 @@
while (processQueuedMessages() != 0) ;
}
+ public void moveTimeForward(long milliSeconds) {
+ try {
+ Message msg = getMessageLinkedList();
+ while (msg != null) {
+ long updatedWhen = msg.getWhen() - milliSeconds;
+ if (updatedWhen < 0) {
+ updatedWhen = 0;
+ }
+ MESSAGE_WHEN_FIELD.set(msg, updatedWhen);
+ msg = (Message) MESSAGE_NEXT_FIELD.get(msg);
+ }
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Access failed in TestableLooper: set - Message.when", e);
+ }
+ }
+
+ private Message getMessageLinkedList() {
+ try {
+ MessageQueue queue = mLooper.getQueue();
+ return (Message) MESSAGE_QUEUE_MESSAGES_FIELD.get(queue);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(
+ "Access failed in TestableLooper: get - MessageQueue.mMessages",
+ e);
+ }
+ }
+
private int processQueuedMessages() {
int count = 0;
mEmptyMessage = () -> { };
diff --git a/tests/testables/tests/src/android/testing/TestableLooperTest.java b/tests/testables/tests/src/android/testing/TestableLooperTest.java
index 25f6a488..0f491b8 100644
--- a/tests/testables/tests/src/android/testing/TestableLooperTest.java
+++ b/tests/testables/tests/src/android/testing/TestableLooperTest.java
@@ -19,15 +19,19 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.InOrder;
import android.os.Handler;
import android.os.Looper;
@@ -162,7 +166,7 @@
@Test
public void testCorrectLooperExecution() throws Exception {
- boolean[] hasRun = new boolean[] { false };
+ boolean[] hasRun = new boolean[]{false};
Runnable r = () -> {
assertEquals("Should run on main looper", Looper.getMainLooper(), Looper.myLooper());
hasRun[0] = true;
@@ -177,4 +181,63 @@
testableLooper.destroy();
}
}
+
+ @Test
+ public void testDelayedDispatchNoTimeMove() {
+ Handler handler = spy(new Handler(mTestableLooper.getLooper()));
+ InOrder inOrder = inOrder(handler);
+
+ final Message messageA = handler.obtainMessage(1);
+ final Message messageB = handler.obtainMessage(2);
+
+ handler.sendMessageDelayed(messageA, 0);
+ handler.sendMessageDelayed(messageB, 0);
+
+ mTestableLooper.processAllMessages();
+
+ inOrder.verify(handler).dispatchMessage(messageA);
+ inOrder.verify(handler).dispatchMessage(messageB);
+ }
+
+ @Test
+ public void testDelayedMessageDoesntSend() {
+ Handler handler = spy(new Handler(mTestableLooper.getLooper()));
+ InOrder inOrder = inOrder(handler);
+
+ final Message messageA = handler.obtainMessage(1);
+ final Message messageB = handler.obtainMessage(2);
+ final Message messageC = handler.obtainMessage(3);
+
+ handler.sendMessageDelayed(messageA, 0);
+ handler.sendMessageDelayed(messageB, 0);
+ handler.sendMessageDelayed(messageC, 500);
+
+ mTestableLooper.processAllMessages();
+
+ inOrder.verify(handler).dispatchMessage(messageA);
+ inOrder.verify(handler).dispatchMessage(messageB);
+ verify(handler, never()).dispatchMessage(messageC);
+ }
+
+ @Test
+ public void testMessageSendsAfterDelay() {
+ Handler handler = spy(new Handler(mTestableLooper.getLooper()));
+ InOrder inOrder = inOrder(handler);
+
+ final Message messageA = handler.obtainMessage(1);
+ final Message messageB = handler.obtainMessage(2);
+ final Message messageC = handler.obtainMessage(3);
+
+ handler.sendMessageDelayed(messageA, 0);
+ handler.sendMessageDelayed(messageB, 0);
+ handler.sendMessageDelayed(messageC, 500);
+
+ mTestableLooper.moveTimeForward(500);
+ mTestableLooper.processAllMessages();
+
+ inOrder.verify(handler).dispatchMessage(messageA);
+ inOrder.verify(handler).dispatchMessage(messageB);
+ inOrder.verify(handler).dispatchMessage(messageC);
+ }
+
}
diff --git a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
index 3b201f9..e4add80 100644
--- a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
+++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
@@ -16,6 +16,9 @@
package android.net.vcn.persistablebundleutils;
+import static android.net.vcn.persistablebundleutils.IkeSessionParamsUtils.IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION;
+import static android.net.vcn.persistablebundleutils.IkeSessionParamsUtils.IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES;
+import static android.net.vcn.persistablebundleutils.IkeSessionParamsUtils.isIkeOptionValid;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
import static android.telephony.TelephonyManager.APPTYPE_USIM;
@@ -134,15 +137,37 @@
verifyPersistableBundleEncodeDecodeIsLossless(params);
}
+ private static IkeSessionParams.Builder createBuilderMinimumWithEap() throws Exception {
+ final X509Certificate serverCaCert = createCertFromPemFile("self-signed-ca.pem");
+
+ final byte[] eapId = "test@android.net".getBytes(StandardCharsets.US_ASCII);
+ final int subId = 1;
+ final EapSessionConfig eapConfig =
+ new EapSessionConfig.Builder()
+ .setEapIdentity(eapId)
+ .setEapSimConfig(subId, APPTYPE_USIM)
+ .setEapAkaConfig(subId, APPTYPE_USIM)
+ .build();
+ return createBuilderMinimum().setAuthEap(serverCaCert, eapConfig);
+ }
+
@Test
public void testEncodeDecodeParamsWithIkeOptions() throws Exception {
- final IkeSessionParams params =
- createBuilderMinimum()
+ final IkeSessionParams.Builder builder =
+ createBuilderMinimumWithEap()
.addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID)
+ .addIkeOption(IkeSessionParams.IKE_OPTION_EAP_ONLY_AUTH)
.addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE)
+ .addIkeOption(IkeSessionParams.IKE_OPTION_FORCE_PORT_4500)
.addIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT)
- .build();
- verifyPersistableBundleEncodeDecodeIsLossless(params);
+ .addIkeOption(IkeSessionParams.IKE_OPTION_REKEY_MOBILITY);
+ if (isIkeOptionValid(IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION)) {
+ builder.addIkeOption(IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION);
+ }
+ if (isIkeOptionValid(IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES)) {
+ builder.addIkeOption(IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES);
+ }
+ verifyPersistableBundleEncodeDecodeIsLossless(builder.build());
}
private static InputStream openAssetsFile(String fileName) throws Exception {
@@ -176,19 +201,7 @@
@Test
public void testEncodeRecodeParamsWithEapAuth() throws Exception {
- final X509Certificate serverCaCert = createCertFromPemFile("self-signed-ca.pem");
-
- final byte[] eapId = "test@android.net".getBytes(StandardCharsets.US_ASCII);
- final int subId = 1;
- final EapSessionConfig eapConfig =
- new EapSessionConfig.Builder()
- .setEapIdentity(eapId)
- .setEapSimConfig(subId, APPTYPE_USIM)
- .setEapAkaConfig(subId, APPTYPE_USIM)
- .build();
-
- final IkeSessionParams params =
- createBuilderMinimum().setAuthEap(serverCaCert, eapConfig).build();
+ final IkeSessionParams params = createBuilderMinimumWithEap().build();
verifyPersistableBundleEncodeDecodeIsLossless(params);
}
}
diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp
index ff24d16..25373f9 100644
--- a/tools/validatekeymaps/Android.bp
+++ b/tools/validatekeymaps/Android.bp
@@ -21,6 +21,7 @@
cflags: [
"-Wall",
"-Werror",
+ "-Wextra",
],
static_libs: [
@@ -31,6 +32,9 @@
"liblog",
"libui-types",
],
+ shared_libs: [
+ "libvintf",
+ ],
target: {
host_linux: {
static_libs: [
diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp
index 817effd..0d7d5f9 100644
--- a/tools/validatekeymaps/Main.cpp
+++ b/tools/validatekeymaps/Main.cpp
@@ -141,6 +141,11 @@
}
base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(filename);
if (!ret.ok()) {
+ if (ret.error().message() == "Missing kernel config") {
+ // It means the layout is valid, but won't be loaded on this device because
+ // this layout requires a certain kernel config.
+ return true;
+ }
error("Error %s parsing key layout file.\n\n", ret.error().message().c_str());
return false;
}