Merge "Camera: Remove code for log_ultrawide_usage" into main
diff --git a/BROADCASTS_OWNERS b/BROADCASTS_OWNERS
index 01f1f8a..f0cbe46 100644
--- a/BROADCASTS_OWNERS
+++ b/BROADCASTS_OWNERS
@@ -1,5 +1,5 @@
 # Bug component: 316181
-ctate@android.com
-jsharkey@google.com
+set noparent
+
 sudheersai@google.com
 yamasani@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
index f20b170..3577fcd 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
@@ -194,7 +194,7 @@
     /**
      * Simple benchmark for the amount of time to send a given number of messages
      */
-    @Test
+    // @Test Temporarily disabled
     @Parameters(method = "getParams")
     public void time(Config config) throws Exception {
         reset();
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
index af3c405..ac57100 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
@@ -198,7 +198,7 @@
         executor.awaitTermination(5, TimeUnit.SECONDS);
     }
 
-    @Test
+    // @Test Temporarily disabled
     @Parameters(method = "getParams")
     public void throughput(Config config) throws Exception {
         setup(config);
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ByteBufferPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ByteBufferPerfTest.java
index 4cf46e5..f01ac02 100644
--- a/apct-tests/perftests/core/src/android/libcore/regression/ByteBufferPerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/regression/ByteBufferPerfTest.java
@@ -565,7 +565,6 @@
     }
 
     @Test
-    @Parameters(method = "getData")
     public void time_new_byteArray() throws Exception {
         final BenchmarkState state = mBenchmarkRule.getState();
         while (state.keepRunning()) {
@@ -574,7 +573,6 @@
     }
 
     @Test
-    @Parameters(method = "getData")
     public void time_ByteBuffer_allocate() throws Exception {
         final BenchmarkState state = mBenchmarkRule.getState();
         while (state.keepRunning()) {
diff --git a/apex/blobstore/OWNERS b/apex/blobstore/OWNERS
index a53bbea..676cbc7 100644
--- a/apex/blobstore/OWNERS
+++ b/apex/blobstore/OWNERS
@@ -1,2 +1,5 @@
+# Bug component: 25692
+set noparent
+
 sudheersai@google.com
-yamasani@google.com
+yamasani@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/apex/jobscheduler/framework/aconfig/job.aconfig b/apex/jobscheduler/framework/aconfig/job.aconfig
index 80db264..5f55075 100644
--- a/apex/jobscheduler/framework/aconfig/job.aconfig
+++ b/apex/jobscheduler/framework/aconfig/job.aconfig
@@ -23,3 +23,10 @@
     description: "Introduce a new RUN_BACKUP_JOBS permission and exemption logic allowing for longer running jobs for apps whose primary purpose is to backup or sync content."
     bug: "318731461"
 }
+
+flag {
+   name: "cleanup_empty_jobs"
+   namespace: "backstage_power"
+   description: "Enables automatic cancellation of jobs due to leaked JobParameters, reducing unnecessary battery drain and improving system efficiency. This includes logging and traces for better issue diagnosis."
+   bug: "349688611"
+}
diff --git a/apex/jobscheduler/framework/java/android/app/job/IJobCallback.aidl b/apex/jobscheduler/framework/java/android/app/job/IJobCallback.aidl
index 96494ec..11d17ca 100644
--- a/apex/jobscheduler/framework/java/android/app/job/IJobCallback.aidl
+++ b/apex/jobscheduler/framework/java/android/app/job/IJobCallback.aidl
@@ -85,6 +85,14 @@
      */
     @UnsupportedAppUsage
     void jobFinished(int jobId, boolean reschedule);
+
+    /*
+     * Inform JobScheduler to force finish this job because the client has lost
+     * the job handle. jobFinished can no longer be called from the client.
+     * @param jobId Unique integer used to identify this job
+     */
+    void forceJobFinished(int jobId);
+
     /*
      * Inform JobScheduler of a change in the estimated transfer payload.
      *
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index e833bb9..52a761f 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -34,15 +34,21 @@
 import android.os.Parcelable;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
+import android.system.SystemCleaner;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.Cleaner;
 
 /**
  * Contains the parameters used to configure/identify your job. You do not create this object
  * yourself, instead it is handed in to your application by the System.
  */
 public class JobParameters implements Parcelable {
+    private static final String TAG = "JobParameters";
 
     /** @hide */
     public static final int INTERNAL_STOP_REASON_UNKNOWN = -1;
@@ -306,6 +312,10 @@
     private int mStopReason = STOP_REASON_UNDEFINED;
     private int mInternalStopReason = INTERNAL_STOP_REASON_UNKNOWN;
     private String debugStopReason; // Human readable stop reason for debugging.
+    @Nullable
+    private JobCleanupCallback mJobCleanupCallback;
+    @Nullable
+    private Cleaner.Cleanable mCleanable;
 
     /** @hide */
     public JobParameters(IBinder callback, String namespace, int jobId, PersistableBundle extras,
@@ -326,6 +336,8 @@
         this.mTriggeredContentAuthorities = triggeredContentAuthorities;
         this.mNetwork = network;
         this.mJobNamespace = namespace;
+        this.mJobCleanupCallback = null;
+        this.mCleanable = null;
     }
 
     /**
@@ -597,6 +609,8 @@
         mStopReason = in.readInt();
         mInternalStopReason = in.readInt();
         debugStopReason = in.readString();
+        mJobCleanupCallback = null;
+        mCleanable = null;
     }
 
     /** @hide */
@@ -612,6 +626,54 @@
         this.debugStopReason = debugStopReason;
     }
 
+    /** @hide */
+    public void initCleaner(JobCleanupCallback jobCleanupCallback) {
+        mJobCleanupCallback = jobCleanupCallback;
+        mCleanable = SystemCleaner.cleaner().register(this, mJobCleanupCallback);
+    }
+
+    /**
+     * Lazy initialize the cleaner and enable it
+     *
+     * @hide
+     */
+    public void enableCleaner() {
+        if (mJobCleanupCallback == null) {
+            initCleaner(new JobCleanupCallback(IJobCallback.Stub.asInterface(callback), jobId));
+        }
+        mJobCleanupCallback.enableCleaner();
+    }
+
+    /**
+     * Disable the cleaner from running and unregister it
+     *
+     * @hide
+     */
+    public void disableCleaner() {
+        if (mJobCleanupCallback != null) {
+            mJobCleanupCallback.disableCleaner();
+            if (mCleanable != null) {
+                mCleanable.clean();
+                mCleanable = null;
+            }
+            mJobCleanupCallback = null;
+        }
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    @Nullable
+    public Cleaner.Cleanable getCleanable() {
+        return mCleanable;
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    @Nullable
+    public JobCleanupCallback getJobCleanupCallback() {
+        return mJobCleanupCallback;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -647,6 +709,67 @@
         dest.writeString(debugStopReason);
     }
 
+    /**
+     * JobCleanupCallback is used track JobParameters leak. If the job is started
+     * and jobFinish is not called at the time of garbage collection of JobParameters
+     * instance, it is considered a job leak. Force finish the job.
+     *
+     * @hide
+     */
+    public static class JobCleanupCallback implements Runnable {
+        private final IJobCallback mCallback;
+        private final int mJobId;
+        private boolean mIsCleanerEnabled;
+
+        public JobCleanupCallback(
+                IJobCallback callback,
+                int jobId) {
+            mCallback = callback;
+            mJobId = jobId;
+            mIsCleanerEnabled = false;
+        }
+
+        /**
+         * Check if the cleaner is enabled
+         *
+         * @hide
+         */
+        public boolean isCleanerEnabled() {
+            return mIsCleanerEnabled;
+        }
+
+        /**
+         * Enable the cleaner to detect JobParameter leak
+         *
+         * @hide
+         */
+        public void enableCleaner() {
+            mIsCleanerEnabled = true;
+        }
+
+        /**
+         * Disable the cleaner from running.
+         *
+         * @hide
+         */
+        public void disableCleaner() {
+            mIsCleanerEnabled = false;
+        }
+
+        /** @hide */
+        @Override
+        public void run() {
+            if (!isCleanerEnabled()) {
+                return;
+            }
+            try {
+                mCallback.forceJobFinished(mJobId);
+            } catch (Exception e) {
+                Log.wtf(TAG, "Could not destroy running job", e);
+            }
+        }
+    }
+
     public static final @android.annotation.NonNull Creator<JobParameters> CREATOR = new Creator<JobParameters>() {
         @Override
         public JobParameters createFromParcel(Parcel in) {
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java b/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
index 79d87ed..5f80c52 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
@@ -165,7 +165,13 @@
                 case MSG_EXECUTE_JOB: {
                     final JobParameters params = (JobParameters) msg.obj;
                     try {
+                        if (Flags.cleanupEmptyJobs()) {
+                            params.enableCleaner();
+                        }
                         boolean workOngoing = JobServiceEngine.this.onStartJob(params);
+                        if (Flags.cleanupEmptyJobs() && !workOngoing) {
+                            params.disableCleaner();
+                        }
                         ackStartMessage(params, workOngoing);
                     } catch (Exception e) {
                         Log.e(TAG, "Error while executing job: " + params.getJobId());
@@ -190,6 +196,9 @@
                     IJobCallback callback = params.getCallback();
                     if (callback != null) {
                         try {
+                            if (Flags.cleanupEmptyJobs()) {
+                                params.disableCleaner();
+                            }
                             callback.jobFinished(params.getJobId(), needsReschedule);
                         } catch (RemoteException e) {
                             Log.e(TAG, "Error reporting job finish to system: binder has gone" +
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index be8e304..ee246d8 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -129,6 +129,8 @@
     private static final String[] VERB_STRINGS = {
             "VERB_BINDING", "VERB_STARTING", "VERB_EXECUTING", "VERB_STOPPING", "VERB_FINISHED"
     };
+    private static final String TRACE_JOB_FORCE_FINISHED_PREFIX = "forceJobFinished:";
+    private static final String TRACE_JOB_FORCE_FINISHED_DELIMITER = "#";
 
     // States that a job occupies while interacting with the client.
     static final int VERB_BINDING = 0;
@@ -292,6 +294,11 @@
         }
 
         @Override
+        public void forceJobFinished(int jobId) {
+            doForceJobFinished(this, jobId);
+        }
+
+        @Override
         public void updateEstimatedNetworkBytes(int jobId, JobWorkItem item,
                 long downloadBytes, long uploadBytes) {
             doUpdateEstimatedNetworkBytes(this, jobId, item, downloadBytes, uploadBytes);
@@ -762,6 +769,35 @@
         }
     }
 
+    /**
+     * This method just adds traces to evaluate jobs that leak jobparameters at the client.
+     * It does not stop the job.
+     */
+    void doForceJobFinished(JobCallback cb, int jobId) {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            final JobStatus executing;
+            synchronized (mLock) {
+                // not the current job, presumably it has finished in some way already
+                if (!verifyCallerLocked(cb)) {
+                    return;
+                }
+
+                executing = getRunningJobLocked();
+            }
+            if (executing != null && jobId == executing.getJobId()) {
+                final StringBuilder stateSuffix = new StringBuilder();
+                stateSuffix.append(TRACE_JOB_FORCE_FINISHED_PREFIX);
+                stateSuffix.append(executing.getBatteryName());
+                stateSuffix.append(TRACE_JOB_FORCE_FINISHED_DELIMITER);
+                stateSuffix.append(executing.getJobId());
+                Trace.instant(Trace.TRACE_TAG_POWER, stateSuffix.toString());
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     private void doAcknowledgeGetTransferredDownloadBytesMessage(JobCallback cb, int jobId,
             int workId, @BytesLong long transferredBytes) {
         // TODO(255393346): Make sure apps call this appropriately and monitor for abuse
diff --git a/api/api.go b/api/api.go
index 5b7f534..e9f1fee 100644
--- a/api/api.go
+++ b/api/api.go
@@ -15,7 +15,7 @@
 package api
 
 import (
-	"sort"
+	"slices"
 
 	"github.com/google/blueprint/proptools"
 
@@ -75,31 +75,25 @@
 
 var PrepareForCombinedApisTest = android.FixtureRegisterWithContext(registerBuildComponents)
 
-func (a *CombinedApis) bootclasspath(ctx android.ConfigAndErrorContext) []string {
-	return a.properties.Bootclasspath.GetOrDefault(a.ConfigurableEvaluator(ctx), nil)
-}
-
-func (a *CombinedApis) systemServerClasspath(ctx android.ConfigAndErrorContext) []string {
-	return a.properties.System_server_classpath.GetOrDefault(a.ConfigurableEvaluator(ctx), nil)
-}
-
 func (a *CombinedApis) apiFingerprintStubDeps(ctx android.BottomUpMutatorContext) []string {
-	ret := []string{}
+	bootClasspath := a.properties.Bootclasspath.GetOrDefault(ctx, nil)
+	systemServerClasspath := a.properties.System_server_classpath.GetOrDefault(ctx, nil)
+	var ret []string
 	ret = append(
 		ret,
-		transformArray(a.bootclasspath(ctx), "", ".stubs")...,
+		transformArray(bootClasspath, "", ".stubs")...,
 	)
 	ret = append(
 		ret,
-		transformArray(a.bootclasspath(ctx), "", ".stubs.system")...,
+		transformArray(bootClasspath, "", ".stubs.system")...,
 	)
 	ret = append(
 		ret,
-		transformArray(a.bootclasspath(ctx), "", ".stubs.module_lib")...,
+		transformArray(bootClasspath, "", ".stubs.module_lib")...,
 	)
 	ret = append(
 		ret,
-		transformArray(a.systemServerClasspath(ctx), "", ".stubs.system_server")...,
+		transformArray(systemServerClasspath, "", ".stubs.system_server")...,
 	)
 	return ret
 }
@@ -129,7 +123,7 @@
 	Cmd        *string
 	Dists      []android.Dist
 	Out        []string
-	Srcs       []string
+	Srcs       proptools.Configurable[[]string]
 	Tools      []string
 	Visibility []string
 }
@@ -137,7 +131,7 @@
 type libraryProps struct {
 	Name            *string
 	Sdk_version     *string
-	Static_libs     []string
+	Static_libs     proptools.Configurable[[]string]
 	Visibility      []string
 	Defaults        []string
 	Is_stubs_module *bool
@@ -145,7 +139,7 @@
 
 type fgProps struct {
 	Name       *string
-	Srcs       []string
+	Srcs       proptools.Configurable[[]string]
 	Visibility []string
 }
 
@@ -166,7 +160,7 @@
 	// The module for the non-updatable / non-module part of the api.
 	BaseTxt string
 	// The list of modules that are relevant for this merged txt.
-	Modules []string
+	Modules proptools.Configurable[[]string]
 	// The output tag for each module to use.e.g. {.public.api.txt} for current.txt
 	ModuleTag string
 	// public, system, module-lib or system-server
@@ -190,7 +184,8 @@
 	props.Tools = []string{"metalava"}
 	props.Out = []string{filename}
 	props.Cmd = proptools.StringPtr(metalavaCmd + "$(in) --out $(out)")
-	props.Srcs = append([]string{txt.BaseTxt}, createSrcs(txt.Modules, txt.ModuleTag)...)
+	props.Srcs = proptools.NewSimpleConfigurable([]string{txt.BaseTxt})
+	props.Srcs.Append(createSrcs(txt.Modules, txt.ModuleTag))
 	if doDist {
 		props.Dists = []android.Dist{
 			{
@@ -209,11 +204,11 @@
 	ctx.CreateModule(genrule.GenRuleFactory, &props)
 }
 
-func createMergedAnnotationsFilegroups(ctx android.LoadHookContext, modules, system_server_modules []string) {
+func createMergedAnnotationsFilegroups(ctx android.LoadHookContext, modules, system_server_modules proptools.Configurable[[]string]) {
 	for _, i := range []struct {
 		name    string
 		tag     string
-		modules []string
+		modules proptools.Configurable[[]string]
 	}{
 		{
 			name:    "all-modules-public-annotations",
@@ -240,33 +235,39 @@
 	}
 }
 
-func createMergedPublicStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedPublicStubs(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
+	modules = modules.Clone()
+	transformConfigurableArray(modules, "", ".stubs")
 	props := libraryProps{}
 	props.Name = proptools.StringPtr("all-modules-public-stubs")
-	props.Static_libs = transformArray(modules, "", ".stubs")
+	props.Static_libs = modules
 	props.Sdk_version = proptools.StringPtr("module_current")
 	props.Visibility = []string{"//frameworks/base"}
 	props.Is_stubs_module = proptools.BoolPtr(true)
 	ctx.CreateModule(java.LibraryFactory, &props)
 }
 
-func createMergedPublicExportableStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedPublicExportableStubs(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
+	modules = modules.Clone()
+	transformConfigurableArray(modules, "", ".stubs.exportable")
 	props := libraryProps{}
 	props.Name = proptools.StringPtr("all-modules-public-stubs-exportable")
-	props.Static_libs = transformArray(modules, "", ".stubs.exportable")
+	props.Static_libs = modules
 	props.Sdk_version = proptools.StringPtr("module_current")
 	props.Visibility = []string{"//frameworks/base"}
 	props.Is_stubs_module = proptools.BoolPtr(true)
 	ctx.CreateModule(java.LibraryFactory, &props)
 }
 
-func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedSystemStubs(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
 	// First create the all-updatable-modules-system-stubs
 	{
-		updatable_modules := removeAll(modules, non_updatable_modules)
+		updatable_modules := modules.Clone()
+		removeAll(updatable_modules, non_updatable_modules)
+		transformConfigurableArray(updatable_modules, "", ".stubs.system")
 		props := libraryProps{}
 		props.Name = proptools.StringPtr("all-updatable-modules-system-stubs")
-		props.Static_libs = transformArray(updatable_modules, "", ".stubs.system")
+		props.Static_libs = updatable_modules
 		props.Sdk_version = proptools.StringPtr("module_current")
 		props.Visibility = []string{"//frameworks/base"}
 		props.Is_stubs_module = proptools.BoolPtr(true)
@@ -275,10 +276,11 @@
 	// Now merge all-updatable-modules-system-stubs and stubs from non-updatable modules
 	// into all-modules-system-stubs.
 	{
+		static_libs := transformArray(non_updatable_modules, "", ".stubs.system")
+		static_libs = append(static_libs, "all-updatable-modules-system-stubs")
 		props := libraryProps{}
 		props.Name = proptools.StringPtr("all-modules-system-stubs")
-		props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.system")
-		props.Static_libs = append(props.Static_libs, "all-updatable-modules-system-stubs")
+		props.Static_libs = proptools.NewSimpleConfigurable(static_libs)
 		props.Sdk_version = proptools.StringPtr("module_current")
 		props.Visibility = []string{"//frameworks/base"}
 		props.Is_stubs_module = proptools.BoolPtr(true)
@@ -286,13 +288,15 @@
 	}
 }
 
-func createMergedSystemExportableStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedSystemExportableStubs(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
 	// First create the all-updatable-modules-system-stubs
 	{
-		updatable_modules := removeAll(modules, non_updatable_modules)
+		updatable_modules := modules.Clone()
+		removeAll(updatable_modules, non_updatable_modules)
+		transformConfigurableArray(updatable_modules, "", ".stubs.exportable.system")
 		props := libraryProps{}
 		props.Name = proptools.StringPtr("all-updatable-modules-system-stubs-exportable")
-		props.Static_libs = transformArray(updatable_modules, "", ".stubs.exportable.system")
+		props.Static_libs = updatable_modules
 		props.Sdk_version = proptools.StringPtr("module_current")
 		props.Visibility = []string{"//frameworks/base"}
 		props.Is_stubs_module = proptools.BoolPtr(true)
@@ -301,10 +305,11 @@
 	// Now merge all-updatable-modules-system-stubs and stubs from non-updatable modules
 	// into all-modules-system-stubs.
 	{
+		static_libs := transformArray(non_updatable_modules, "", ".stubs.exportable.system")
+		static_libs = append(static_libs, "all-updatable-modules-system-stubs-exportable")
 		props := libraryProps{}
 		props.Name = proptools.StringPtr("all-modules-system-stubs-exportable")
-		props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.exportable.system")
-		props.Static_libs = append(props.Static_libs, "all-updatable-modules-system-stubs-exportable")
+		props.Static_libs = proptools.NewSimpleConfigurable(static_libs)
 		props.Sdk_version = proptools.StringPtr("module_current")
 		props.Visibility = []string{"//frameworks/base"}
 		props.Is_stubs_module = proptools.BoolPtr(true)
@@ -315,7 +320,7 @@
 func createMergedTestStubsForNonUpdatableModules(ctx android.LoadHookContext) {
 	props := libraryProps{}
 	props.Name = proptools.StringPtr("all-non-updatable-modules-test-stubs")
-	props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.test")
+	props.Static_libs = proptools.NewSimpleConfigurable(transformArray(non_updatable_modules, "", ".stubs.test"))
 	props.Sdk_version = proptools.StringPtr("module_current")
 	props.Visibility = []string{"//frameworks/base"}
 	props.Is_stubs_module = proptools.BoolPtr(true)
@@ -325,25 +330,27 @@
 func createMergedTestExportableStubsForNonUpdatableModules(ctx android.LoadHookContext) {
 	props := libraryProps{}
 	props.Name = proptools.StringPtr("all-non-updatable-modules-test-stubs-exportable")
-	props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.exportable.test")
+	props.Static_libs = proptools.NewSimpleConfigurable(transformArray(non_updatable_modules, "", ".stubs.exportable.test"))
 	props.Sdk_version = proptools.StringPtr("module_current")
 	props.Visibility = []string{"//frameworks/base"}
 	props.Is_stubs_module = proptools.BoolPtr(true)
 	ctx.CreateModule(java.LibraryFactory, &props)
 }
 
-func createMergedFrameworkImpl(ctx android.LoadHookContext, modules []string) {
+func createMergedFrameworkImpl(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
+	modules = modules.Clone()
 	// This module is for the "framework-all" module, which should not include the core libraries.
-	modules = removeAll(modules, core_libraries_modules)
+	removeAll(modules, core_libraries_modules)
 	// Remove the modules that belong to non-updatable APEXes since those are allowed to compile
 	// against unstable APIs.
-	modules = removeAll(modules, non_updatable_modules)
+	removeAll(modules, non_updatable_modules)
 	// First create updatable-framework-module-impl, which contains all updatable modules.
 	// This module compiles against module_lib SDK.
 	{
+		transformConfigurableArray(modules, "", ".impl")
 		props := libraryProps{}
 		props.Name = proptools.StringPtr("updatable-framework-module-impl")
-		props.Static_libs = transformArray(modules, "", ".impl")
+		props.Static_libs = modules
 		props.Sdk_version = proptools.StringPtr("module_current")
 		props.Visibility = []string{"//frameworks/base"}
 		ctx.CreateModule(java.LibraryFactory, &props)
@@ -352,65 +359,74 @@
 	// Now create all-framework-module-impl, which contains updatable-framework-module-impl
 	// and all non-updatable modules. This module compiles against hidden APIs.
 	{
+		static_libs := transformArray(non_updatable_modules, "", ".impl")
+		static_libs = append(static_libs, "updatable-framework-module-impl")
 		props := libraryProps{}
 		props.Name = proptools.StringPtr("all-framework-module-impl")
-		props.Static_libs = transformArray(non_updatable_modules, "", ".impl")
-		props.Static_libs = append(props.Static_libs, "updatable-framework-module-impl")
+		props.Static_libs = proptools.NewSimpleConfigurable(static_libs)
 		props.Sdk_version = proptools.StringPtr("core_platform")
 		props.Visibility = []string{"//frameworks/base"}
 		ctx.CreateModule(java.LibraryFactory, &props)
 	}
 }
 
-func createMergedFrameworkModuleLibExportableStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedFrameworkModuleLibExportableStubs(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
+	modules = modules.Clone()
 	// The user of this module compiles against the "core" SDK and against non-updatable modules,
 	// so remove to avoid dupes.
-	modules = removeAll(modules, core_libraries_modules)
-	modules = removeAll(modules, non_updatable_modules)
+	removeAll(modules, core_libraries_modules)
+	removeAll(modules, non_updatable_modules)
+	transformConfigurableArray(modules, "", ".stubs.exportable.module_lib")
 	props := libraryProps{}
 	props.Name = proptools.StringPtr("framework-updatable-stubs-module_libs_api-exportable")
-	props.Static_libs = transformArray(modules, "", ".stubs.exportable.module_lib")
+	props.Static_libs = modules
 	props.Sdk_version = proptools.StringPtr("module_current")
 	props.Visibility = []string{"//frameworks/base"}
 	props.Is_stubs_module = proptools.BoolPtr(true)
 	ctx.CreateModule(java.LibraryFactory, &props)
 }
 
-func createMergedFrameworkModuleLibStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedFrameworkModuleLibStubs(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
+	modules = modules.Clone()
 	// The user of this module compiles against the "core" SDK and against non-updatable modules,
 	// so remove to avoid dupes.
-	modules = removeAll(modules, core_libraries_modules)
-	modules = removeAll(modules, non_updatable_modules)
+	removeAll(modules, core_libraries_modules)
+	removeAll(modules, non_updatable_modules)
+	transformConfigurableArray(modules, "", ".stubs.module_lib")
 	props := libraryProps{}
 	props.Name = proptools.StringPtr("framework-updatable-stubs-module_libs_api")
-	props.Static_libs = transformArray(modules, "", ".stubs.module_lib")
+	props.Static_libs = modules
 	props.Sdk_version = proptools.StringPtr("module_current")
 	props.Visibility = []string{"//frameworks/base"}
 	props.Is_stubs_module = proptools.BoolPtr(true)
 	ctx.CreateModule(java.LibraryFactory, &props)
 }
 
-func createMergedFrameworkSystemServerExportableStubs(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) {
+func createMergedFrameworkSystemServerExportableStubs(ctx android.LoadHookContext, bootclasspath, system_server_classpath proptools.Configurable[[]string]) {
 	// The user of this module compiles against the "core" SDK and against non-updatable bootclasspathModules,
 	// so remove to avoid dupes.
-	bootclasspathModules := removeAll(bootclasspath, core_libraries_modules)
-	bootclasspathModules = removeAll(bootclasspath, non_updatable_modules)
-	modules := append(
-		// Include all the module-lib APIs from the bootclasspath libraries.
-		transformArray(bootclasspathModules, "", ".stubs.exportable.module_lib"),
-		// Then add all the system-server APIs from the service-* libraries.
-		transformArray(system_server_classpath, "", ".stubs.exportable.system_server")...,
-	)
+	bootclasspathModules := bootclasspath.Clone()
+	removeAll(bootclasspathModules, core_libraries_modules)
+	removeAll(bootclasspathModules, non_updatable_modules)
+	transformConfigurableArray(bootclasspathModules, "", ".stubs.exportable.module_lib")
+
+	system_server_classpath = system_server_classpath.Clone()
+	transformConfigurableArray(system_server_classpath, "", ".stubs.exportable.system_server")
+
+	// Include all the module-lib APIs from the bootclasspath libraries.
+	// Then add all the system-server APIs from the service-* libraries.
+	bootclasspathModules.Append(system_server_classpath)
+
 	props := libraryProps{}
 	props.Name = proptools.StringPtr("framework-updatable-stubs-system_server_api-exportable")
-	props.Static_libs = modules
+	props.Static_libs = bootclasspathModules
 	props.Sdk_version = proptools.StringPtr("system_server_current")
 	props.Visibility = []string{"//frameworks/base"}
 	props.Is_stubs_module = proptools.BoolPtr(true)
 	ctx.CreateModule(java.LibraryFactory, &props)
 }
 
-func createPublicStubsSourceFilegroup(ctx android.LoadHookContext, modules []string) {
+func createPublicStubsSourceFilegroup(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
 	props := fgProps{}
 	props.Name = proptools.StringPtr("all-modules-public-stubs-source")
 	props.Srcs = createSrcs(modules, "{.public.stubs.source}")
@@ -418,7 +434,14 @@
 	ctx.CreateModule(android.FileGroupFactory, &props)
 }
 
-func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string, baseTxtModulePrefix, stubsTypeSuffix string, doDist bool) {
+func createMergedTxts(
+	ctx android.LoadHookContext,
+	bootclasspath proptools.Configurable[[]string],
+	system_server_classpath proptools.Configurable[[]string],
+	baseTxtModulePrefix string,
+	stubsTypeSuffix string,
+	doDist bool,
+) {
 	var textFiles []MergedTxtDefinition
 
 	tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
@@ -463,11 +486,10 @@
 }
 
 func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) {
-	bootclasspath := a.bootclasspath(ctx)
-	system_server_classpath := a.systemServerClasspath(ctx)
+	bootclasspath := a.properties.Bootclasspath.Clone()
+	system_server_classpath := a.properties.System_server_classpath.Clone()
 	if ctx.Config().VendorConfig("ANDROID").Bool("include_nonpublic_framework_api") {
-		bootclasspath = append(bootclasspath, a.properties.Conditional_bootclasspath...)
-		sort.Strings(bootclasspath)
+		bootclasspath.AppendSimpleValue(a.properties.Conditional_bootclasspath)
 	}
 	createMergedTxts(ctx, bootclasspath, system_server_classpath, "non-updatable-", "-", false)
 	createMergedTxts(ctx, bootclasspath, system_server_classpath, "non-updatable-exportable-", "-exportable-", true)
@@ -500,8 +522,10 @@
 // Various utility methods below.
 
 // Creates an array of ":<m><tag>" for each m in <modules>.
-func createSrcs(modules []string, tag string) []string {
-	return transformArray(modules, ":", tag)
+func createSrcs(modules proptools.Configurable[[]string], tag string) proptools.Configurable[[]string] {
+	result := modules.Clone()
+	transformConfigurableArray(result, ":", tag)
+	return result
 }
 
 // Creates an array of "<prefix><m><suffix>", for each m in <modules>.
@@ -513,11 +537,23 @@
 	return a
 }
 
-func removeAll(s []string, vs []string) []string {
-	for _, v := range vs {
-		s = remove(s, v)
-	}
-	return s
+// Creates an array of "<prefix><m><suffix>", for each m in <modules>.
+func transformConfigurableArray(modules proptools.Configurable[[]string], prefix, suffix string) {
+	modules.AddPostProcessor(func(s []string) []string {
+		return transformArray(s, prefix, suffix)
+	})
+}
+
+func removeAll(s proptools.Configurable[[]string], vs []string) {
+	s.AddPostProcessor(func(s []string) []string {
+		a := make([]string, 0, len(s))
+		for _, module := range s {
+			if !slices.Contains(vs, module) {
+				a = append(a, module)
+			}
+		}
+		return a
+	})
 }
 
 func remove(s []string, v string) []string {
diff --git a/cmds/uinput/examples/test-touchpad.evemu b/cmds/uinput/examples/test-touchpad.evemu
new file mode 100644
index 0000000..34ee572
--- /dev/null
+++ b/cmds/uinput/examples/test-touchpad.evemu
@@ -0,0 +1,44 @@
+# EVEMU 1.2
+# This is an evemu "recording" of an Apple Magic Trackpad (1st generation), but
+# that doesn't actually make any movements. It just runs for a very long time,
+# to make Android think a touchpad is connected. This is useful for testing
+# things like the settings in System > Touchpad, which only appear when one is
+# connected.
+#
+# It can be played by piping it to the uinput command over ADB:
+#     $ adb shell uinput - < test-touchpad.evemu
+N: Fake touchpad
+I: 0005 05ac 030e 0160
+P: 05 00 00 00 00 00 00 00
+B: 00 0b 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 01 00 00 00 00 00
+B: 01 20 e5 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 02 00 00 00 00 00 00 00 00
+B: 03 03 00 00 00 00 80 73 02
+B: 04 10 00 00 00 00 00 00 00
+B: 05 00 00 00 00 00 00 00 00
+B: 11 00 00 00 00 00 00 00 00
+B: 12 00 00 00 00 00 00 00 00
+A: 00 -2909 3167 4 0 46
+A: 01 -2456 2565 4 0 45
+A: 2f 0 15 0 0 0
+A: 30 0 1020 4 0 0
+A: 31 0 1020 4 0 0
+A: 34 -31 32 1 0 0
+A: 35 -2909 3167 4 0 46
+A: 36 -2456 2565 4 0 45
+A: 39 0 65535 0 0 0
+E: 0.000001 0004 0005 1234
+E: 0.000001 0000 0000 0000
+E: 1000000000.000000 0004 0005 1235
+E: 1000000000.000000 0000 0000 0000
diff --git a/core/api/current.txt b/core/api/current.txt
index 5685221..5e8febe 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -145,12 +145,12 @@
     field public static final String MANAGE_DEVICE_POLICY_AUDIO_OUTPUT = "android.permission.MANAGE_DEVICE_POLICY_AUDIO_OUTPUT";
     field public static final String MANAGE_DEVICE_POLICY_AUTOFILL = "android.permission.MANAGE_DEVICE_POLICY_AUTOFILL";
     field public static final String MANAGE_DEVICE_POLICY_BACKUP_SERVICE = "android.permission.MANAGE_DEVICE_POLICY_BACKUP_SERVICE";
-    field @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled") public static final String MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL = "android.permission.MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL";
+    field public static final String MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL = "android.permission.MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL";
     field public static final String MANAGE_DEVICE_POLICY_BLUETOOTH = "android.permission.MANAGE_DEVICE_POLICY_BLUETOOTH";
     field public static final String MANAGE_DEVICE_POLICY_BUGREPORT = "android.permission.MANAGE_DEVICE_POLICY_BUGREPORT";
     field public static final String MANAGE_DEVICE_POLICY_CALLS = "android.permission.MANAGE_DEVICE_POLICY_CALLS";
     field public static final String MANAGE_DEVICE_POLICY_CAMERA = "android.permission.MANAGE_DEVICE_POLICY_CAMERA";
-    field @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled") public static final String MANAGE_DEVICE_POLICY_CAMERA_TOGGLE = "android.permission.MANAGE_DEVICE_POLICY_CAMERA_TOGGLE";
+    field public static final String MANAGE_DEVICE_POLICY_CAMERA_TOGGLE = "android.permission.MANAGE_DEVICE_POLICY_CAMERA_TOGGLE";
     field public static final String MANAGE_DEVICE_POLICY_CERTIFICATES = "android.permission.MANAGE_DEVICE_POLICY_CERTIFICATES";
     field public static final String MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE = "android.permission.MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE";
     field @FlaggedApi("android.view.contentprotection.flags.manage_device_policy_enabled") public static final String MANAGE_DEVICE_POLICY_CONTENT_PROTECTION = "android.permission.MANAGE_DEVICE_POLICY_CONTENT_PROTECTION";
@@ -172,7 +172,7 @@
     field public static final String MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS = "android.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS";
     field public static final String MANAGE_DEVICE_POLICY_METERED_DATA = "android.permission.MANAGE_DEVICE_POLICY_METERED_DATA";
     field public static final String MANAGE_DEVICE_POLICY_MICROPHONE = "android.permission.MANAGE_DEVICE_POLICY_MICROPHONE";
-    field @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled") public static final String MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE = "android.permission.MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE";
+    field public static final String MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE = "android.permission.MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE";
     field public static final String MANAGE_DEVICE_POLICY_MOBILE_NETWORK = "android.permission.MANAGE_DEVICE_POLICY_MOBILE_NETWORK";
     field public static final String MANAGE_DEVICE_POLICY_MODIFY_USERS = "android.permission.MANAGE_DEVICE_POLICY_MODIFY_USERS";
     field public static final String MANAGE_DEVICE_POLICY_MTE = "android.permission.MANAGE_DEVICE_POLICY_MTE";
@@ -8121,7 +8121,7 @@
     method public boolean isLogoutEnabled();
     method public boolean isManagedProfile(@NonNull android.content.ComponentName);
     method public boolean isMasterVolumeMuted(@NonNull android.content.ComponentName);
-    method @FlaggedApi("android.app.admin.flags.is_mte_policy_enforced") public static boolean isMtePolicyEnforced();
+    method public static boolean isMtePolicyEnforced();
     method public boolean isNetworkLoggingEnabled(@Nullable android.content.ComponentName);
     method public boolean isOrganizationOwnedDeviceWithManagedProfile();
     method public boolean isOverrideApnEnabled(@NonNull android.content.ComponentName);
@@ -8597,7 +8597,7 @@
     field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
     field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
     field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field @FlaggedApi("android.app.admin.flags.backup_service_security_log_event_enabled") public static final int TAG_BACKUP_SERVICE_TOGGLED = 210044; // 0x3347c
+    field public static final int TAG_BACKUP_SERVICE_TOGGLED = 210044; // 0x3347c
     field public static final int TAG_BLUETOOTH_CONNECTION = 210039; // 0x33477
     field public static final int TAG_BLUETOOTH_DISCONNECTION = 210040; // 0x33478
     field public static final int TAG_CAMERA_POLICY_SET = 210034; // 0x33472
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index ba16037..60dc52b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1322,7 +1322,7 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getDeviceOwnerUser();
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public android.app.admin.DevicePolicyState getDevicePolicyState();
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public String getFinancedDeviceKioskRoleHolder();
-    method @FlaggedApi("android.app.admin.flags.device_policy_size_tracking_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public int getMaxPolicyStorageLimit();
+    method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public int getMaxPolicyStorageLimit();
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_ADMIN_POLICY}) public java.util.List<java.lang.String> getPermittedAccessibilityServices(int);
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_ADMIN_POLICY}) public java.util.List<java.lang.String> getPermittedInputMethodsForCurrentUser();
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public java.util.List<android.os.UserHandle> getPolicyManagedProfiles(@NonNull android.os.UserHandle);
@@ -1349,7 +1349,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_POLICY_AUDIT_LOGGING) public void setAuditLogEventCallback(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.app.admin.SecurityLog.SecurityEvent>>);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setDeviceProvisioningConfigApplied();
     method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void setDpcDownloaded(boolean);
-    method @FlaggedApi("android.app.admin.flags.device_policy_size_tracking_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void setMaxPolicyStorageLimit(int);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void setMaxPolicyStorageLimit(int);
     method @Deprecated @RequiresPermission(value=android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS, conditional=true) public void setProfileOwnerCanAccessDeviceIds(@NonNull android.content.ComponentName);
     method public void setSecondaryLockscreenEnabled(@NonNull android.content.ComponentName, boolean);
     method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void setUserProvisioningState(int, @NonNull android.os.UserHandle);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 42f7615..4fc7076 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2003,6 +2003,7 @@
     method public void setRampingRingerEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) public void setRs2Value(float);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setTestDeviceConnectionState(@NonNull android.media.AudioDeviceAttributes, boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) public void setVolumeControllerLongPressTimeoutEnabled(boolean);
     method @FlaggedApi("android.media.audio.focus_exclusive_with_recording") @RequiresPermission(android.Manifest.permission.QUERY_AUDIO_STATE) public boolean shouldNotificationSoundPlay(@NonNull android.media.AudioAttributes);
   }
 
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index b83be6b..b4fb480 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -88,6 +88,7 @@
 import android.view.WindowInsetsController.Appearance;
 import android.window.TaskSnapshot;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.LocalePicker;
 import com.android.internal.app.procstats.ProcessStats;
 import com.android.internal.os.RoSystemProperties;
@@ -238,6 +239,14 @@
     private static final RateLimitingCache<List<ProcessErrorStateInfo>> mErrorProcessesCache =
             new RateLimitingCache<>(10, 2);
 
+    /** Rate-Limiting cache that allows no more than 100 calls to the service per second. */
+    @GuardedBy("mMemoryInfoCache")
+    private static final RateLimitingCache<MemoryInfo> mMemoryInfoCache =
+            new RateLimitingCache<>(10);
+    /** Used to store cached results for rate-limited calls to getMemoryInfo(). */
+    @GuardedBy("mMemoryInfoCache")
+    private static final MemoryInfo mRateLimitedMemInfo = new MemoryInfo();
+
     /**
      * Query handler for mGetCurrentUserIdCache - returns a cached value of the current foreground
      * user id if the backstage_power/android.app.cache_get_current_user_id flag is enabled.
@@ -3510,6 +3519,19 @@
             foregroundAppThreshold = source.readLong();
         }
 
+        /** @hide */
+        public void copyTo(MemoryInfo other) {
+            other.advertisedMem = advertisedMem;
+            other.availMem = availMem;
+            other.totalMem = totalMem;
+            other.threshold = threshold;
+            other.lowMemory = lowMemory;
+            other.hiddenAppThreshold = hiddenAppThreshold;
+            other.secondaryServerThreshold = secondaryServerThreshold;
+            other.visibleAppThreshold = visibleAppThreshold;
+            other.foregroundAppThreshold = foregroundAppThreshold;
+        }
+
         public static final @android.annotation.NonNull Creator<MemoryInfo> CREATOR
                 = new Creator<MemoryInfo>() {
             public MemoryInfo createFromParcel(Parcel source) {
@@ -3536,6 +3558,20 @@
      * manage its memory.
      */
     public void getMemoryInfo(MemoryInfo outInfo) {
+        if (Flags.rateLimitGetMemoryInfo()) {
+            synchronized (mMemoryInfoCache) {
+                mMemoryInfoCache.get(() -> {
+                    getMemoryInfoInternal(mRateLimitedMemInfo);
+                    return mRateLimitedMemInfo;
+                });
+                mRateLimitedMemInfo.copyTo(outInfo);
+            }
+        } else {
+            getMemoryInfoInternal(outInfo);
+        }
+    }
+
+    private void getMemoryInfoInternal(MemoryInfo outInfo) {
         try {
             getService().getMemoryInfo(outInfo);
         } catch (RemoteException e) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 8fd3326..f27dc32 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -79,7 +79,6 @@
 import android.provider.DeviceConfig;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.LongSparseLongArray;
 import android.util.Pools;
@@ -3156,12 +3155,6 @@
     /** @hide */
     public static final String KEY_HISTORICAL_OPS = "historical_ops";
 
-    /** System properties for debug logging of noteOp call sites */
-    private static final String DEBUG_LOGGING_ENABLE_PROP = "appops.logging_enabled";
-    private static final String DEBUG_LOGGING_PACKAGES_PROP = "appops.logging_packages";
-    private static final String DEBUG_LOGGING_OPS_PROP = "appops.logging_ops";
-    private static final String DEBUG_LOGGING_TAG = "AppOpsManager";
-
     /**
      * Retrieve the op switch that controls the given operation.
      * @hide
@@ -8066,14 +8059,6 @@
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setUidMode(int code, int uid, @Mode int mode) {
         try {
-            // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
-            if (code == OP_BLUETOOTH_CONNECT) {
-                Log.i(DEBUG_LOGGING_TAG,
-                        "setUidMode called for OP_BLUETOOTH_CONNECT with mode: " + mode
-                                + " for uid: " + uid + " calling uid: " + Binder.getCallingUid()
-                                + " trace: "
-                                + Arrays.toString(Thread.currentThread().getStackTrace()));
-            }
             mService.setUidMode(code, uid, mode);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -8094,15 +8079,6 @@
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setUidMode(@NonNull String appOp, int uid, @Mode int mode) {
         try {
-            // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
-            if (appOp.equals(OPSTR_BLUETOOTH_CONNECT)) {
-                Log.i(DEBUG_LOGGING_TAG,
-                        "setUidMode called for OPSTR_BLUETOOTH_CONNECT with mode: " + mode
-                                + " for uid: " + uid + " calling uid: " + Binder.getCallingUid()
-                                + " trace: "
-                                + Arrays.toString(Thread.currentThread().getStackTrace()));
-            }
-
             mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -8143,14 +8119,6 @@
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setMode(int code, int uid, String packageName, @Mode int mode) {
         try {
-            // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
-            if (code == OP_BLUETOOTH_CONNECT) {
-                Log.i(DEBUG_LOGGING_TAG,
-                        "setMode called for OPSTR_BLUETOOTH_CONNECT with mode: " + mode
-                                + " for uid: " + uid + " calling uid: " + Binder.getCallingUid()
-                                + " trace: "
-                                + Arrays.toString(Thread.currentThread().getStackTrace()));
-            }
             mService.setMode(code, uid, packageName, mode);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -8173,14 +8141,6 @@
     public void setMode(@NonNull String op, int uid, @Nullable String packageName,
             @Mode int mode) {
         try {
-            // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
-            if (op.equals(OPSTR_BLUETOOTH_CONNECT)) {
-                Log.i(DEBUG_LOGGING_TAG,
-                        "setMode called for OPSTR_BLUETOOTH_CONNECT with mode: " + mode
-                                + " for uid: " + uid + " calling uid: " + Binder.getCallingUid()
-                                + " trace: "
-                                + Arrays.toString(Thread.currentThread().getStackTrace()));
-            }
             mService.setMode(strOpToOp(op), uid, packageName, mode);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/activity_manager.aconfig b/core/java/android/app/activity_manager.aconfig
index 4c97dbb..c0c81df 100644
--- a/core/java/android/app/activity_manager.aconfig
+++ b/core/java/android/app/activity_manager.aconfig
@@ -106,6 +106,17 @@
 
 flag {
      namespace: "backstage_power"
+     name: "use_app_info_not_launched"
+     description: "Use the notLaunched state from ApplicationInfo instead of current value"
+     is_fixed_read_only: true
+     bug: "362516211"
+     metadata {
+         purpose: PURPOSE_BUGFIX
+     }
+}
+
+flag {
+     namespace: "backstage_power"
      name: "cache_get_current_user_id"
      description: "Add caching for getCurrentUserId"
      is_fixed_read_only: true
@@ -114,3 +125,14 @@
          purpose: PURPOSE_BUGFIX
      }
 }
+
+flag {
+     namespace: "backstage_power"
+     name: "rate_limit_get_memory_info"
+     description: "Rate limit calls to getMemoryInfo using a cache"
+     is_fixed_read_only: true
+     bug: "364312431"
+     metadata {
+         purpose: PURPOSE_BUGFIX
+     }
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 0f54cb7..daa15f0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -55,10 +55,8 @@
 import static android.Manifest.permission.SET_TIME_ZONE;
 import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;
 import static android.app.admin.flags.Flags.FLAG_DEVICE_THEFT_API_ENABLED;
-import static android.app.admin.flags.Flags.FLAG_DEVICE_POLICY_SIZE_TRACKING_ENABLED;
 import static android.app.admin.flags.Flags.onboardingBugreportV2Enabled;
 import static android.app.admin.flags.Flags.onboardingConsentlessBugreports;
-import static android.app.admin.flags.Flags.FLAG_IS_MTE_POLICY_ENFORCED;
 import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
 import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
@@ -4232,7 +4230,6 @@
      *
      * @return whether MTE is currently enabled on the device.
      */
-    @FlaggedApi(FLAG_IS_MTE_POLICY_ENFORCED)
     public static boolean isMtePolicyEnforced() {
         return Zygote.nativeSupportsMemoryTagging();
     }
@@ -8664,6 +8661,7 @@
      *             {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}.
      */
     @RequiresPermission(value = MANAGE_DEVICE_POLICY_CAMERA, conditional = true)
+    @SupportsCoexistence
     public void setCameraDisabled(@Nullable ComponentName admin, boolean disabled) {
         if (mService != null) {
             try {
@@ -10249,6 +10247,7 @@
      * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_TASK}.
      */
     @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_TASK, conditional = true)
+    @SupportsCoexistence
     public void clearPackagePersistentPreferredActivities(@Nullable ComponentName admin,
             String packageName) {
         throwIfParentInstance("clearPackagePersistentPreferredActivities");
@@ -11940,6 +11939,7 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner and if the caller
      * has not been granted the permission to set the given user restriction.
      */
+    @SupportsCoexistence
     public void addUserRestriction(@NonNull ComponentName admin,
             @UserManager.UserRestrictionKey String key) {
         if (mService != null) {
@@ -12021,6 +12021,7 @@
      * @throws IllegalStateException if caller is not targeting Android
      * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or above.
      */
+    @SupportsCoexistence
     public void addUserRestrictionGlobally(@NonNull @UserManager.UserRestrictionKey String key) {
         throwIfParentInstance("addUserRestrictionGlobally");
         if (mService != null) {
@@ -12076,6 +12077,7 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner  and if the
      *  caller has not been granted the permission to set the given user restriction.
      */
+    @SupportsCoexistence
     public void clearUserRestriction(@NonNull ComponentName admin,
             @UserManager.UserRestrictionKey String key) {
         if (mService != null) {
@@ -12312,6 +12314,7 @@
      * @see #DELEGATION_PACKAGE_ACCESS
      */
     @RequiresPermission(value = MANAGE_DEVICE_POLICY_PACKAGE_STATE, conditional = true)
+    @SupportsCoexistence
     public boolean setApplicationHidden(@Nullable ComponentName admin, String packageName,
             boolean hidden) {
         if (mService != null) {
@@ -12492,6 +12495,7 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     @RequiresPermission(value = MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT, conditional = true)
+    @SupportsCoexistence
     public void setAccountManagementDisabled(@Nullable ComponentName admin, String accountType,
             boolean disabled) {
         if (mService != null) {
@@ -12575,10 +12579,24 @@
      **/
     @SystemApi
     public void setSecondaryLockscreenEnabled(@NonNull ComponentName admin, boolean enabled) {
+        setSecondaryLockscreenEnabled(admin, enabled, null);
+    }
+
+    /**
+     * Called by the system supervision app to set whether a secondary lockscreen needs to be shown.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
+     * @param enabled Whether or not the lockscreen needs to be shown.
+     * @param options A {@link PersistableBundle} to supply options to the lock screen.
+     * @hide
+     */
+    public void setSecondaryLockscreenEnabled(@Nullable ComponentName admin, boolean enabled,
+            @Nullable PersistableBundle options) {
         throwIfParentInstance("setSecondaryLockscreenEnabled");
         if (mService != null) {
             try {
-                mService.setSecondaryLockscreenEnabled(admin, enabled);
+                mService.setSecondaryLockscreenEnabled(admin, enabled, options);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -14276,6 +14294,7 @@
      * @see #retrieveSecurityLogs
      */
     @RequiresPermission(value = MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional = true)
+    @SupportsCoexistence
     public void setSecurityLoggingEnabled(@Nullable ComponentName admin, boolean enabled) {
         throwIfParentInstance("setSecurityLoggingEnabled");
         try {
@@ -17181,6 +17200,7 @@
      * if USB data signaling fails to be enabled/disabled.
      */
     @RequiresPermission(value = MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, conditional = true)
+    @SupportsCoexistence
     public void setUsbDataSignalingEnabled(boolean enabled) {
         throwIfParentInstance("setUsbDataSignalingEnabled");
         if (mService != null) {
@@ -17746,7 +17766,6 @@
      */
     @SystemApi
     @RequiresPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
-    @FlaggedApi(FLAG_DEVICE_POLICY_SIZE_TRACKING_ENABLED)
     public void setMaxPolicyStorageLimit(int storageLimit) {
         if (mService != null) {
             try {
@@ -17766,7 +17785,6 @@
      */
     @SystemApi
     @RequiresPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
-    @FlaggedApi(FLAG_DEVICE_POLICY_SIZE_TRACKING_ENABLED)
     public int getMaxPolicyStorageLimit() {
         if (mService != null) {
             try {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index d4e5c99..a4e2b8f 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -303,7 +303,7 @@
     String[] getAccountTypesWithManagementDisabled(String callerPackageName);
     String[] getAccountTypesWithManagementDisabledAsUser(int userId, String callerPackageName, in boolean parent);
 
-    void setSecondaryLockscreenEnabled(in ComponentName who, boolean enabled);
+    void setSecondaryLockscreenEnabled(in ComponentName who, boolean enabled, in PersistableBundle options);
     boolean isSecondaryLockscreenEnabled(in UserHandle userHandle);
 
     void setPreferentialNetworkServiceConfigs(
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 477f2e0..beb93fd 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -16,10 +16,7 @@
 
 package android.app.admin;
 
-import static android.app.admin.flags.Flags.FLAG_BACKUP_SERVICE_SECURITY_LOG_EVENT_ENABLED;
-
 import android.Manifest;
-import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -611,7 +608,6 @@
      * <li> [2] backup service state ({@code Integer}, 1 for enabled, 0 for disabled)
      * @see DevicePolicyManager#setBackupServiceEnabled(ComponentName, boolean)
      */
-    @FlaggedApi(FLAG_BACKUP_SERVICE_SECURITY_LOG_EVENT_ENABLED)
     public static final int TAG_BACKUP_SERVICE_TOGGLED =
             SecurityLogTags.SECURITY_BACKUP_SERVICE_TOGGLED;
     /**
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index 9ed5aa6..081dfe6 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -13,6 +13,7 @@
   bug: "289520697"
 }
 
+# Fully rolled out and must not be used.
 flag {
   name: "device_policy_size_tracking_enabled"
   is_exported: true
@@ -22,13 +23,6 @@
 }
 
 flag {
-  name: "device_policy_size_tracking_internal_enabled"
-  namespace: "enterprise"
-  description: "Add feature to track the total policy size and have a max threshold - internal changes"
-  bug: "281543351"
-}
-
-flag {
   name: "onboarding_bugreport_v2_enabled"
   is_exported: true
   namespace: "enterprise"
@@ -44,13 +38,7 @@
   is_fixed_read_only: true
 }
 
-flag {
-  name: "dedicated_device_control_enabled"
-  namespace: "enterprise"
-  description: "Allow the device management role holder to control which platform features are available on dedicated devices."
-  bug: "281964214"
-}
-
+# Fully rolled out and must not be used.
 flag {
   name: "dedicated_device_control_api_enabled"
   is_exported: true
@@ -164,12 +152,23 @@
 }
 
 flag {
+  name: "fix_race_condition_in_tie_profile_lock"
+  namespace: "enterprise"
+  description: "Fix race condition in tieProfileLockIfNecessary()"
+  bug: "355905501"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
   name: "quiet_mode_credential_bug_fix"
   namespace: "enterprise"
   description: "Guards a bugfix that ends the credential input flow if the managed user has not stopped."
   bug: "293441361"
 }
 
+# Fully rolled out and must not be used.
 flag {
   name: "assist_content_user_restriction_enabled"
   is_exported: true
@@ -188,6 +187,7 @@
     }
 }
 
+# Fully rolled out and must not be used.
 flag {
   name: "backup_service_security_log_event_enabled"
   is_exported: true
@@ -196,6 +196,7 @@
   bug: "304999634"
 }
 
+# Fully rolled out and must not be used.
 flag {
   name: "esim_management_enabled"
   is_exported: true
@@ -213,6 +214,7 @@
   bug: "289515470"
 }
 
+# Fully rolled out and must not be used.
 flag {
   name: "is_mte_policy_enforced"
   is_exported: true
diff --git a/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java b/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java
index c4e8b41..c4bfae9 100644
--- a/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java
+++ b/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java
@@ -72,14 +72,32 @@
      * we need to have per-package app function schemas.
      *
      * <p>This schema should be set visible to callers from the package owner itself and for callers
-     * with {@link android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@link
-     * android.permission.EXECUTE_APP_FUNCTIONS} permissions.
+     * with {@link android.Manifest.permission#EXECUTE_APP_FUNCTIONS} or {@link
+     * android.Manifest.permission#EXECUTE_APP_FUNCTIONS_TRUSTED} permissions.
      *
      * @param packageName The package name to create a schema for.
      */
     @NonNull
     public static AppSearchSchema createAppFunctionRuntimeSchema(@NonNull String packageName) {
-        return new AppSearchSchema.Builder(getRuntimeSchemaNameForPackage(packageName))
+        return getAppFunctionRuntimeSchemaBuilder(getRuntimeSchemaNameForPackage(packageName))
+                .addParentType(RUNTIME_SCHEMA_TYPE)
+                .build();
+    }
+
+    /**
+     * Creates a parent schema for all app function runtime schemas.
+     *
+     * <p>This schema should be set visible to the owner itself and for callers with {@link
+     * android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@link
+     * android.permission.EXECUTE_APP_FUNCTIONS} permissions.
+     */
+    public static AppSearchSchema createParentAppFunctionRuntimeSchema() {
+        return getAppFunctionRuntimeSchemaBuilder(RUNTIME_SCHEMA_TYPE).build();
+    }
+
+    private static AppSearchSchema.Builder getAppFunctionRuntimeSchemaBuilder(
+            @NonNull String schemaType) {
+        return new AppSearchSchema.Builder(schemaType)
                 .addProperty(
                         new AppSearchSchema.StringPropertyConfig.Builder(PROPERTY_FUNCTION_ID)
                                 .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
@@ -111,9 +129,7 @@
                                 .setJoinableValueType(
                                         AppSearchSchema.StringPropertyConfig
                                                 .JOINABLE_VALUE_TYPE_QUALIFIED_ID)
-                                .build())
-                .addParentType(RUNTIME_SCHEMA_TYPE)
-                .build();
+                                .build());
     }
 
     /** Returns the function id. This might look like "com.example.message#send_message". */
diff --git a/core/java/android/app/jank/OWNERS b/core/java/android/app/jank/OWNERS
new file mode 100644
index 0000000..806de57
--- /dev/null
+++ b/core/java/android/app/jank/OWNERS
@@ -0,0 +1,4 @@
+steventerrell@google.com
+carmenjackson@google.com
+jjaggi@google.com
+pmuetschard@google.com
\ No newline at end of file
diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig
index 297fe8a..748260b 100644
--- a/core/java/android/companion/virtual/flags/flags.aconfig
+++ b/core/java/android/companion/virtual/flags/flags.aconfig
@@ -98,11 +98,11 @@
 }
 
 flag {
-  name: "camera_multiple_input_streams"
-  is_exported: true
-  namespace: "virtual_devices"
-  description: "Expose multiple surface for the virtual camera owner for different stream resolution"
-  bug: "341083465"
+    name: "camera_multiple_input_streams"
+    is_exported: true
+    namespace: "virtual_devices"
+    description: "Expose multiple surface for the virtual camera owner for different stream resolution"
+    bug: "341083465"
 }
 
 flag {
@@ -113,8 +113,16 @@
 }
 
 flag {
-  name: "status_bar_and_insets"
-  namespace: "virtual_devices"
-  description: "Allow for status bar and insets on virtual devices"
-  bug: "350007866"
+    namespace: "virtual_devices"
+    name: "display_power_manager_apis"
+    description: "Make relevant PowerManager APIs display aware by default"
+    bug: "365042486"
+    is_fixed_read_only: true
+}
+
+flag {
+    name: "status_bar_and_insets"
+    namespace: "virtual_devices"
+    description: "Allow for status bar and insets on virtual devices"
+    bug: "350007866"
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index da3cc1b..031380d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -86,6 +86,7 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.XmlUtils;
+import com.android.modules.expresslog.Counter;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -12805,6 +12806,8 @@
                             new ClipData.Item(text, htmlText, null, stream));
                     setClipData(clipData);
                     if (stream != null) {
+                        logCounterIfFlagsMissing(FLAG_GRANT_READ_URI_PERMISSION,
+                                "intents.value_explicit_uri_grant_for_send_action");
                         addFlags(FLAG_GRANT_READ_URI_PERMISSION);
                     }
                     return true;
@@ -12846,6 +12849,8 @@
 
                     setClipData(clipData);
                     if (streams != null) {
+                        logCounterIfFlagsMissing(FLAG_GRANT_READ_URI_PERMISSION,
+                                "intents.value_explicit_uri_grant_for_send_multiple_action");
                         addFlags(FLAG_GRANT_READ_URI_PERMISSION);
                     }
                     return true;
@@ -12865,6 +12870,10 @@
                 putExtra(MediaStore.EXTRA_OUTPUT, output);
 
                 setClipData(ClipData.newRawUri("", output));
+
+                logCounterIfFlagsMissing(
+                        FLAG_GRANT_WRITE_URI_PERMISSION | FLAG_GRANT_READ_URI_PERMISSION,
+                        "intents.value_explicit_uri_grant_for_image_capture_action");
                 addFlags(FLAG_GRANT_WRITE_URI_PERMISSION|FLAG_GRANT_READ_URI_PERMISSION);
                 return true;
             }
@@ -12873,6 +12882,12 @@
         return false;
     }
 
+    private void logCounterIfFlagsMissing(int requiredFlags, String metricId) {
+        if ((getFlags() & requiredFlags) != requiredFlags) {
+            Counter.logIncrement(metricId);
+        }
+    }
+
     @android.ravenwood.annotation.RavenwoodThrow
     private Uri maybeConvertFileToContentUri(Context context, Uri uri) {
         if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 495ae60..34bea1a 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -849,6 +849,12 @@
      */
     public static final int PRIVATE_FLAG_EXT_CPU_OVERRIDE = 1 << 5;
 
+    /**
+     * Whether the app has been previously not launched
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_EXT_NOT_LAUNCHED = 1 << 6;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "PRIVATE_FLAG_EXT_" }, value = {
             PRIVATE_FLAG_EXT_PROFILEABLE,
@@ -857,6 +863,7 @@
             PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK,
             PRIVATE_FLAG_EXT_ALLOWLISTED_FOR_HIDDEN_APIS,
             PRIVATE_FLAG_EXT_CPU_OVERRIDE,
+            PRIVATE_FLAG_EXT_NOT_LAUNCHED,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ApplicationInfoPrivateFlagsExt {}
@@ -2664,6 +2671,22 @@
     }
 
     /**
+     * Returns whether the app in the STOPPED state.
+     * @hide
+     */
+    public boolean isStopped() {
+        return (flags & ApplicationInfo.FLAG_STOPPED) != 0;
+    }
+
+    /**
+     * Returns whether the app was never launched (any process started) before.
+     * @hide
+     */
+    public boolean isNotLaunched() {
+        return (privateFlagsExt & ApplicationInfo.PRIVATE_FLAG_EXT_NOT_LAUNCHED) != 0;
+    }
+
+    /**
      * Checks if a changeId is enabled for the current user
      * @param changeId The changeId to verify
      * @return True of the changeId is enabled
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig
index 28534ad..9eec7a4 100644
--- a/core/java/android/content/pm/multiuser.aconfig
+++ b/core/java/android/content/pm/multiuser.aconfig
@@ -426,4 +426,13 @@
   metadata {
     purpose: PURPOSE_BUGFIX
   }
-}
\ No newline at end of file
+}
+
+
+flag {
+    name: "caching_development_improvements"
+    namespace: "multiuser"
+    description: "System API to simplify caching implamentations"
+    bug: "364947162"
+    is_fixed_read_only: true
+}
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index 6514872..ef59e0a 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -26,6 +26,10 @@
 import android.database.sqlite.SQLiteException;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
+import android.ravenwood.annotation.RavenwoodThrow;
 
 import dalvik.annotation.optimization.FastNative;
 import dalvik.system.CloseGuard;
@@ -40,9 +44,8 @@
  * consumer for reading.
  * </p>
  */
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
-        "com.android.platform.test.ravenwood.nativesubstitution.CursorWindow_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("CursorWindow_host")
 public class CursorWindow extends SQLiteClosable implements Parcelable {
     private static final String STATS_TAG = "CursorWindowStats";
 
@@ -63,48 +66,69 @@
     private final CloseGuard mCloseGuard;
 
     // May throw CursorWindowAllocationException
+    @RavenwoodRedirect
     private static native long nativeCreate(String name, int cursorWindowSize);
 
     // May throw CursorWindowAllocationException
+    @RavenwoodRedirect
     private static native long nativeCreateFromParcel(Parcel parcel);
+    @RavenwoodRedirect
     private static native void nativeDispose(long windowPtr);
+    @RavenwoodRedirect
     private static native void nativeWriteToParcel(long windowPtr, Parcel parcel);
 
+    @RavenwoodRedirect
     private static native String nativeGetName(long windowPtr);
+    @RavenwoodRedirect
     private static native byte[] nativeGetBlob(long windowPtr, int row, int column);
+    @RavenwoodRedirect
     private static native String nativeGetString(long windowPtr, int row, int column);
+    @RavenwoodThrow
     private static native void nativeCopyStringToBuffer(long windowPtr, int row, int column,
             CharArrayBuffer buffer);
+    @RavenwoodRedirect
     private static native boolean nativePutBlob(long windowPtr, byte[] value, int row, int column);
+    @RavenwoodRedirect
     private static native boolean nativePutString(long windowPtr, String value,
             int row, int column);
 
     // Below native methods don't do unconstrained work, so are FastNative for performance
 
     @FastNative
+    @RavenwoodThrow
     private static native void nativeClear(long windowPtr);
 
     @FastNative
+    @RavenwoodRedirect
     private static native int nativeGetNumRows(long windowPtr);
     @FastNative
+    @RavenwoodRedirect
     private static native boolean nativeSetNumColumns(long windowPtr, int columnNum);
     @FastNative
+    @RavenwoodRedirect
     private static native boolean nativeAllocRow(long windowPtr);
     @FastNative
+    @RavenwoodThrow
     private static native void nativeFreeLastRow(long windowPtr);
 
     @FastNative
+    @RavenwoodRedirect
     private static native int nativeGetType(long windowPtr, int row, int column);
     @FastNative
+    @RavenwoodRedirect
     private static native long nativeGetLong(long windowPtr, int row, int column);
     @FastNative
+    @RavenwoodRedirect
     private static native double nativeGetDouble(long windowPtr, int row, int column);
 
     @FastNative
+    @RavenwoodRedirect
     private static native boolean nativePutLong(long windowPtr, long value, int row, int column);
     @FastNative
+    @RavenwoodRedirect
     private static native boolean nativePutDouble(long windowPtr, double value, int row, int column);
     @FastNative
+    @RavenwoodThrow
     private static native boolean nativePutNull(long windowPtr, int row, int column);
 
 
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 8975191..9355937 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -170,6 +170,12 @@
     int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE = 20;
 
     /**
+     * Biometrics is not allowed to verify in apps.
+     * @hide
+     */
+    int BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS = 21;
+
+    /**
      * This constant is only used by SystemUI. It notifies SystemUI that authentication was paused
      * because the authentication attempt was unsuccessful.
      * @hide
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 9bc46b9..a4f7485f 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -94,6 +94,13 @@
             BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE;
 
     /**
+     * Biometrics is not allowed to verify in apps.
+     * @hide
+     */
+    public static final int BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS =
+            BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS;
+
+    /**
      * A security vulnerability has been discovered and the sensor is unavailable until a
      * security update has addressed this issue. This error can be received if for example,
      * authentication was requested with {@link Authenticators#BIOMETRIC_STRONG}, but the
diff --git a/core/java/android/os/AppZygote.java b/core/java/android/os/AppZygote.java
index 07fbe4a..0541a96 100644
--- a/core/java/android/os/AppZygote.java
+++ b/core/java/android/os/AppZygote.java
@@ -111,12 +111,15 @@
         try {
             int runtimeFlags = Zygote.getMemorySafetyRuntimeFlagsForSecondaryZygote(
                     mAppInfo, mProcessInfo);
+
+            final int[] sharedAppGid = {
+                    UserHandle.getSharedAppGid(UserHandle.getAppId(mAppInfo.uid)) };
             mZygote = Process.ZYGOTE_PROCESS.startChildZygote(
                     "com.android.internal.os.AppZygoteInit",
                     mAppInfo.processName + "_zygote",
                     mZygoteUid,
                     mZygoteUid,
-                    null,  // gids
+                    sharedAppGid,  // Zygote gets access to shared app GID for profiles
                     runtimeFlags,
                     "app_zygote",  // seInfo
                     abi,  // abi
diff --git a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
index da2eec9..b2d9260 100644
--- a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
@@ -19,9 +19,9 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Trace;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
 import android.util.Log;
 import android.util.Printer;
 import android.util.SparseArray;
@@ -51,9 +51,8 @@
  * <p>You can retrieve the MessageQueue for the current thread with
  * {@link Looper#myQueue() Looper.myQueue()}.
  */
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
-        "com.android.platform.test.ravenwood.nativesubstitution.MessageQueue_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("MessageQueue_host")
 public final class MessageQueue {
     private static final String TAG = "ConcurrentMessageQueue";
     private static final boolean DEBUG = false;
@@ -345,11 +344,17 @@
     // Barriers are indicated by messages with a null target whose arg1 field carries the token.
     private final AtomicInteger mNextBarrierToken = new AtomicInteger(1);
 
+    @RavenwoodRedirect
     private static native long nativeInit();
+    @RavenwoodRedirect
     private static native void nativeDestroy(long ptr);
+    @RavenwoodRedirect
     private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
+    @RavenwoodRedirect
     private static native void nativeWake(long ptr);
+    @RavenwoodRedirect
     private static native boolean nativeIsPolling(long ptr);
+    @RavenwoodRedirect
     private static native void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
 
     MessageQueue(boolean quitAllowed) {
diff --git a/core/java/android/os/LegacyMessageQueue/MessageQueue.java b/core/java/android/os/LegacyMessageQueue/MessageQueue.java
index 6b9b349..4474e7e 100644
--- a/core/java/android/os/LegacyMessageQueue/MessageQueue.java
+++ b/core/java/android/os/LegacyMessageQueue/MessageQueue.java
@@ -20,9 +20,9 @@
 import android.annotation.NonNull;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Handler;
-import android.os.Process;
-import android.os.Trace;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
 import android.util.Log;
 import android.util.Printer;
 import android.util.SparseArray;
@@ -42,9 +42,8 @@
  * <p>You can retrieve the MessageQueue for the current thread with
  * {@link Looper#myQueue() Looper.myQueue()}.
  */
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
-        "com.android.platform.test.ravenwood.nativesubstitution.MessageQueue_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("MessageQueue_host")
 public final class MessageQueue {
     private static final String TAG = "MessageQueue";
     private static final boolean DEBUG = false;
@@ -79,12 +78,18 @@
     @UnsupportedAppUsage
     private int mNextBarrierToken;
 
+    @RavenwoodRedirect
     private native static long nativeInit();
+    @RavenwoodRedirect
     private native static void nativeDestroy(long ptr);
     @UnsupportedAppUsage
+    @RavenwoodRedirect
     private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
+    @RavenwoodRedirect
     private native static void nativeWake(long ptr);
+    @RavenwoodRedirect
     private native static boolean nativeIsPolling(long ptr);
+    @RavenwoodRedirect
     private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
 
     MessageQueue(boolean quitAllowed) {
diff --git a/core/java/android/os/LockedMessageQueue/MessageQueue.java b/core/java/android/os/LockedMessageQueue/MessageQueue.java
index b24e14b..f1affce 100644
--- a/core/java/android/os/LockedMessageQueue/MessageQueue.java
+++ b/core/java/android/os/LockedMessageQueue/MessageQueue.java
@@ -20,8 +20,9 @@
 import android.annotation.NonNull;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Handler;
-import android.os.Trace;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
 import android.util.Log;
 import android.util.Printer;
 import android.util.SparseArray;
@@ -44,9 +45,8 @@
  * <p>You can retrieve the MessageQueue for the current thread with
  * {@link Looper#myQueue() Looper.myQueue()}.
  */
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
-        "com.android.platform.test.ravenwood.nativesubstitution.MessageQueue_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("MessageQueue_host")
 public final class MessageQueue {
     private static final String TAG = "LockedMessageQueue";
     private static final boolean DEBUG = false;
@@ -389,12 +389,18 @@
     @UnsupportedAppUsage
     private int mNextBarrierToken;
 
+    @RavenwoodRedirect
     private native static long nativeInit();
+    @RavenwoodRedirect
     private native static void nativeDestroy(long ptr);
     @UnsupportedAppUsage
+    @RavenwoodRedirect
     private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
+    @RavenwoodRedirect
     private native static void nativeWake(long ptr);
+    @RavenwoodRedirect
     private native static boolean nativeIsPolling(long ptr);
+    @RavenwoodRedirect
     private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
 
     MessageQueue(boolean quitAllowed) {
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 47096db..2ac2ae9 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -28,7 +28,8 @@
 import android.app.AppOpsManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.ravenwood.annotation.RavenwoodKeepWholeClass;
-import android.ravenwood.annotation.RavenwoodNativeSubstitutionClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
 import android.ravenwood.annotation.RavenwoodReplace;
 import android.ravenwood.annotation.RavenwoodThrow;
 import android.text.TextUtils;
@@ -233,8 +234,7 @@
  * {@link #readSparseArray(ClassLoader, Class)}.
  */
 @RavenwoodKeepWholeClass
-@RavenwoodNativeSubstitutionClass(
-        "com.android.platform.test.ravenwood.nativesubstitution.Parcel_host")
+@RavenwoodRedirectionClass("Parcel_host")
 public final class Parcel {
 
     private static final boolean DEBUG_RECYCLE = false;
@@ -387,6 +387,7 @@
     private static final int SIZE_COMPLEX_TYPE = 1;
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void nativeMarkSensitive(long nativePtr);
     @FastNative
     @RavenwoodThrow
@@ -395,86 +396,126 @@
     @RavenwoodThrow
     private static native boolean nativeIsForRpc(long nativePtr);
     @CriticalNative
+    @RavenwoodRedirect
     private static native int nativeDataSize(long nativePtr);
     @CriticalNative
+    @RavenwoodRedirect
     private static native int nativeDataAvail(long nativePtr);
     @CriticalNative
+    @RavenwoodRedirect
     private static native int nativeDataPosition(long nativePtr);
     @CriticalNative
+    @RavenwoodRedirect
     private static native int nativeDataCapacity(long nativePtr);
     @FastNative
+    @RavenwoodRedirect
     private static native void nativeSetDataSize(long nativePtr, int size);
     @CriticalNative
+    @RavenwoodRedirect
     private static native void nativeSetDataPosition(long nativePtr, int pos);
     @FastNative
+    @RavenwoodRedirect
     private static native void nativeSetDataCapacity(long nativePtr, int size);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native boolean nativePushAllowFds(long nativePtr, boolean allowFds);
     @CriticalNative
+    @RavenwoodRedirect
     private static native void nativeRestoreAllowFds(long nativePtr, boolean lastValue);
 
+    @RavenwoodRedirect
     private static native void nativeWriteByteArray(long nativePtr, byte[] b, int offset, int len);
+    @RavenwoodRedirect
     private static native void nativeWriteBlob(long nativePtr, byte[] b, int offset, int len);
     @CriticalNative
+    @RavenwoodRedirect
     private static native int nativeWriteInt(long nativePtr, int val);
     @CriticalNative
+    @RavenwoodRedirect
     private static native int nativeWriteLong(long nativePtr, long val);
     @CriticalNative
+    @RavenwoodRedirect
     private static native int nativeWriteFloat(long nativePtr, float val);
     @CriticalNative
+    @RavenwoodRedirect
     private static native int nativeWriteDouble(long nativePtr, double val);
     @RavenwoodThrow
     private static native void nativeSignalExceptionForError(int error);
     @FastNative
+    @RavenwoodRedirect
     private static native void nativeWriteString8(long nativePtr, String val);
     @FastNative
+    @RavenwoodRedirect
     private static native void nativeWriteString16(long nativePtr, String val);
     @FastNative
     @RavenwoodThrow
     private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
     @FastNative
+    @RavenwoodRedirect
     private static native void nativeWriteFileDescriptor(long nativePtr, FileDescriptor val);
 
+    @RavenwoodRedirect
     private static native byte[] nativeCreateByteArray(long nativePtr);
+    @RavenwoodRedirect
     private static native boolean nativeReadByteArray(long nativePtr, byte[] dest, int destLen);
+    @RavenwoodRedirect
     private static native byte[] nativeReadBlob(long nativePtr);
     @CriticalNative
+    @RavenwoodRedirect
     private static native int nativeReadInt(long nativePtr);
     @CriticalNative
+    @RavenwoodRedirect
     private static native long nativeReadLong(long nativePtr);
     @CriticalNative
+    @RavenwoodRedirect
     private static native float nativeReadFloat(long nativePtr);
     @CriticalNative
+    @RavenwoodRedirect
     private static native double nativeReadDouble(long nativePtr);
     @FastNative
+    @RavenwoodRedirect
     private static native String nativeReadString8(long nativePtr);
     @FastNative
+    @RavenwoodRedirect
     private static native String nativeReadString16(long nativePtr);
     @FastNative
     @RavenwoodThrow
     private static native IBinder nativeReadStrongBinder(long nativePtr);
     @FastNative
+    @RavenwoodRedirect
     private static native FileDescriptor nativeReadFileDescriptor(long nativePtr);
 
+    @RavenwoodRedirect
     private static native long nativeCreate();
+    @RavenwoodRedirect
     private static native void nativeFreeBuffer(long nativePtr);
+    @RavenwoodRedirect
     private static native void nativeDestroy(long nativePtr);
 
+    @RavenwoodRedirect
     private static native byte[] nativeMarshall(long nativePtr);
+    @RavenwoodRedirect
     private static native void nativeUnmarshall(
             long nativePtr, byte[] data, int offset, int length);
+    @RavenwoodRedirect
     private static native int nativeCompareData(long thisNativePtr, long otherNativePtr);
+    @RavenwoodRedirect
     private static native boolean nativeCompareDataInRange(
             long ptrA, int offsetA, long ptrB, int offsetB, int length);
+    @RavenwoodRedirect
     private static native void nativeAppendFrom(
             long thisNativePtr, long otherNativePtr, int offset, int length);
     @CriticalNative
+    @RavenwoodRedirect
     private static native boolean nativeHasFileDescriptors(long nativePtr);
+    @RavenwoodRedirect
     private static native boolean nativeHasFileDescriptorsInRange(
             long nativePtr, int offset, int length);
 
+    @RavenwoodRedirect
     private static native boolean nativeHasBinders(long nativePtr);
+    @RavenwoodRedirect
     private static native boolean nativeHasBindersInRange(
             long nativePtr, int offset, int length);
     @RavenwoodThrow
diff --git a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
index 79f229a..80c24a9 100644
--- a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
@@ -19,8 +19,9 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
-import android.os.Handler;
-import android.os.Trace;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
 import android.util.Log;
 import android.util.Printer;
 import android.util.SparseArray;
@@ -37,8 +38,6 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.PriorityQueue;
-import java.util.PriorityQueue;
-import java.util.PriorityQueue;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
@@ -50,9 +49,8 @@
  * <p>You can retrieve the MessageQueue for the current thread with
  * {@link Looper#myQueue() Looper.myQueue()}.
  */
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
-        "com.android.platform.test.ravenwood.nativesubstitution.MessageQueue_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("MessageQueue_host")
 public final class MessageQueue {
     private static final String TAG = "SemiConcurrentMessageQueue";
     private static final boolean DEBUG = false;
@@ -338,11 +336,17 @@
     // Barriers are indicated by messages with a null target whose arg1 field carries the token.
     private final AtomicInteger mNextBarrierToken = new AtomicInteger(1);
 
+    @RavenwoodRedirect
     private static native long nativeInit();
+    @RavenwoodRedirect
     private static native void nativeDestroy(long ptr);
+    @RavenwoodRedirect
     private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
+    @RavenwoodRedirect
     private static native void nativeWake(long ptr);
+    @RavenwoodRedirect
     private static native boolean nativeIsPolling(long ptr);
+    @RavenwoodRedirect
     private static native void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
 
     MessageQueue(boolean quitAllowed) {
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 0a38691..e53873b 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -21,11 +21,13 @@
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.ravenwood.annotation.RavenwoodKeepWholeClass;
-import android.ravenwood.annotation.RavenwoodNativeSubstitutionClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
 import android.util.Log;
 import android.util.MutableInt;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.ravenwood.RavenwoodEnvironment;
 
 import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
@@ -56,8 +58,7 @@
  */
 @SystemApi
 @RavenwoodKeepWholeClass
-@RavenwoodNativeSubstitutionClass(
-        "com.android.platform.test.ravenwood.nativesubstitution.SystemProperties_host")
+@RavenwoodRedirectionClass("SystemProperties_host")
 public class SystemProperties {
     private static final String TAG = "SystemProperties";
     private static final boolean TRACK_KEY_ACCESS = false;
@@ -75,7 +76,7 @@
 
     @UnsupportedAppUsage
     @GuardedBy("sChangeCallbacks")
-    private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
+    static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
 
     @GuardedBy("sRoReads")
     private static final HashMap<String, MutableInt> sRoReads =
@@ -102,30 +103,18 @@
     }
 
     /** @hide */
+    @RavenwoodRedirect
     public static void init$ravenwood(Map<String, String> values,
             Predicate<String> keyReadablePredicate, Predicate<String> keyWritablePredicate) {
-        native_init$ravenwood(values, keyReadablePredicate, keyWritablePredicate,
-                SystemProperties::callChangeCallbacks);
-        synchronized (sChangeCallbacks) {
-            sChangeCallbacks.clear();
-        }
+        throw RavenwoodEnvironment.notSupportedOnDevice();
     }
 
     /** @hide */
+    @RavenwoodRedirect
     public static void reset$ravenwood() {
-        native_reset$ravenwood();
-        synchronized (sChangeCallbacks) {
-            sChangeCallbacks.clear();
-        }
+        throw RavenwoodEnvironment.notSupportedOnDevice();
     }
 
-    // These native methods are currently only implemented by Ravenwood, as it's the only
-    // mechanism we have to jump to our RavenwoodNativeSubstitutionClass
-    private static native void native_init$ravenwood(Map<String, String> values,
-            Predicate<String> keyReadablePredicate, Predicate<String> keyWritablePredicate,
-            Runnable changeCallback);
-    private static native void native_reset$ravenwood();
-
     // The one-argument version of native_get used to be a regular native function. Nowadays,
     // we use the two-argument form of native_get all the time, but we can't just delete the
     // one-argument overload: apps use it via reflection, as the UnsupportedAppUsage annotation
@@ -137,34 +126,46 @@
 
     @FastNative
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @RavenwoodRedirect
     private static native String native_get(String key, String def);
     @FastNative
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @RavenwoodRedirect
     private static native int native_get_int(String key, int def);
     @FastNative
     @UnsupportedAppUsage
+    @RavenwoodRedirect
     private static native long native_get_long(String key, long def);
     @FastNative
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @RavenwoodRedirect
     private static native boolean native_get_boolean(String key, boolean def);
 
     @FastNative
+    @RavenwoodRedirect
     private static native long native_find(String name);
     @FastNative
+    @RavenwoodRedirect
     private static native String native_get(long handle);
     @CriticalNative
+    @RavenwoodRedirect
     private static native int native_get_int(long handle, int def);
     @CriticalNative
+    @RavenwoodRedirect
     private static native long native_get_long(long handle, long def);
     @CriticalNative
+    @RavenwoodRedirect
     private static native boolean native_get_boolean(long handle, boolean def);
 
     // _NOT_ FastNative: native_set performs IPC and can block
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @RavenwoodRedirect
     private static native void native_set(String key, String def);
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @RavenwoodRedirect
     private static native void native_add_change_callback();
+    @RavenwoodRedirect
     private static native void native_report_sysprop_change();
 
     /**
@@ -300,7 +301,7 @@
     }
 
     @SuppressWarnings("unused")  // Called from native code.
-    private static void callChangeCallbacks() {
+    static void callChangeCallbacks() {
         ArrayList<Runnable> callbacks = null;
         synchronized (sChangeCallbacks) {
             //Log.i("foo", "Calling " + sChangeCallbacks.size() + " change callbacks!");
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 98904fe..0a05f70 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5150,13 +5150,19 @@
         public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout";
 
         /**
-         * The screen backlight brightness between 0 and 255.
+         * The screen backlight brightness between 1 (minimum) and 255 (maximum).
+         *
+         * Use {@link android.view.WindowManager.LayoutParams#screenBrightness} to set the screen
+         * brightness instead.
          */
         @Readable
         public static final String SCREEN_BRIGHTNESS = "screen_brightness";
 
         /**
-         * Control whether to enable automatic brightness mode.
+         * Controls whether to enable automatic brightness mode. Value can be set to
+         * {@link #SCREEN_BRIGHTNESS_MODE_MANUAL} or {@link #SCREEN_BRIGHTNESS_MODE_AUTOMATIC}.
+         * If {@link #SCREEN_BRIGHTNESS_MODE_AUTOMATIC} is set, the system may change
+         * {@link #SCREEN_BRIGHTNESS} automatically.
          */
         @Readable
         public static final String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
diff --git a/core/java/android/text/ClientFlags.java b/core/java/android/text/ClientFlags.java
index 5d84d17..bbe9cdb 100644
--- a/core/java/android/text/ClientFlags.java
+++ b/core/java/android/text/ClientFlags.java
@@ -35,20 +35,6 @@
     }
 
     /**
-     * @see Flags#phraseStrictFallback()
-     */
-    public static boolean phraseStrictFallback() {
-        return TextFlags.isFeatureEnabled(Flags.FLAG_PHRASE_STRICT_FALLBACK);
-    }
-
-    /**
-     * @see Flags#useBoundsForWidth()
-     */
-    public static boolean useBoundsForWidth() {
-        return TextFlags.isFeatureEnabled(Flags.FLAG_USE_BOUNDS_FOR_WIDTH);
-    }
-
-    /**
      * @see Flags#fixLineHeightForLocale()
      */
     public static boolean fixLineHeightForLocale() {
diff --git a/core/java/android/text/TextFlags.java b/core/java/android/text/TextFlags.java
index 9e02460..0f1b031 100644
--- a/core/java/android/text/TextFlags.java
+++ b/core/java/android/text/TextFlags.java
@@ -56,8 +56,6 @@
      */
     public static final String[] TEXT_ACONFIGS_FLAGS = {
             Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN,
-            Flags.FLAG_PHRASE_STRICT_FALLBACK,
-            Flags.FLAG_USE_BOUNDS_FOR_WIDTH,
             Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE,
             Flags.FLAG_ICU_BIDI_MIGRATION,
             Flags.FLAG_FIX_MISALIGNED_CONTEXT_MENU,
@@ -70,8 +68,6 @@
      */
     public static final boolean[] TEXT_ACONFIG_DEFAULT_VALUE = {
             Flags.noBreakNoHyphenationSpan(),
-            Flags.phraseStrictFallback(),
-            Flags.useBoundsForWidth(),
             Flags.fixLineHeightForLocale(),
             Flags.icuBidiMigration(),
             Flags.fixMisalignedContextMenu(),
diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig
index d33c95e..b2be1a7 100644
--- a/core/java/android/text/flags/flags.aconfig
+++ b/core/java/android/text/flags/flags.aconfig
@@ -2,14 +2,6 @@
 container: "system"
 
 flag {
-  name: "vendor_custom_locale_fallback"
-  namespace: "text"
-  description: "A feature flag that adds custom locale fallback to the vendor customization XML. This enables vendors to add their locale specific fonts, e.g. Japanese font."
-  is_fixed_read_only: true
-  bug: "278768958"
-}
-
-flag {
   name: "new_fonts_fallback_xml"
   is_exported: true
   namespace: "text"
@@ -20,13 +12,6 @@
 }
 
 flag {
-  name: "fix_double_underline"
-  namespace: "text"
-  description: "Feature flag for fixing double underline because of the multiple font used in the single line."
-  bug: "297336724"
-}
-
-flag {
   name: "fix_line_height_for_locale"
   is_exported: true
   namespace: "text"
@@ -66,13 +51,6 @@
 }
 
 flag {
-  name: "phrase_strict_fallback"
-  namespace: "text"
-  description: "Feature flag for automatic fallback from phrase based line break to strict line break."
-  bug: "281970875"
-}
-
-flag {
   name: "use_bounds_for_width"
   is_exported: true
   namespace: "text"
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index 0a73fd1..00545da 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -21,6 +21,10 @@
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
+import android.ravenwood.annotation.RavenwoodThrow;
 
 import java.io.BufferedReader;
 import java.io.FileReader;
@@ -48,9 +52,8 @@
  * They carry a payload of one or more int, long, or String values.  The
  * event-log-tags file defines the payload contents for each type code.
  */
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
-        "com.android.platform.test.ravenwood.nativesubstitution.EventLog_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("EventLog_host")
 public class EventLog {
     /** @hide */ public EventLog() {}
 
@@ -339,6 +342,7 @@
      * @param value A value to log
      * @return The number of bytes written
      */
+    @RavenwoodRedirect
     public static native int writeEvent(int tag, int value);
 
     /**
@@ -347,6 +351,7 @@
      * @param value A value to log
      * @return The number of bytes written
      */
+    @RavenwoodRedirect
     public static native int writeEvent(int tag, long value);
 
     /**
@@ -355,6 +360,7 @@
      * @param value A value to log
      * @return The number of bytes written
      */
+    @RavenwoodRedirect
     public static native int writeEvent(int tag, float value);
 
     /**
@@ -363,6 +369,7 @@
      * @param str A value to log
      * @return The number of bytes written
      */
+    @RavenwoodRedirect
     public static native int writeEvent(int tag, String str);
 
     /**
@@ -371,6 +378,7 @@
      * @param list A list of values to log
      * @return The number of bytes written
      */
+    @RavenwoodRedirect
     public static native int writeEvent(int tag, Object... list);
 
     /**
@@ -379,6 +387,7 @@
      * @param output container to add events into
      * @throws IOException if something goes wrong reading events
      */
+    @RavenwoodThrow
     public static native void readEvents(int[] tags, Collection<Event> output)
             throws IOException;
 
@@ -391,6 +400,7 @@
      * @hide
      */
     @SystemApi
+    @RavenwoodThrow
     public static native void readEventsOnWrapping(int[] tags, long timestamp,
             Collection<Event> output)
             throws IOException;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7b4ea41..0ed0e60 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -371,7 +371,7 @@
  *     </tr>
  *     <tr>
  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
- *         <td>Called when a touch screen motion event occurs.
+ *         <td>Called when a motion event occurs with pointers down on the view.
  *         </td>
  *     </tr>
  *     <tr>
@@ -17873,7 +17873,13 @@
     }
 
     /**
-     * Implement this method to handle touch screen motion events.
+     * Implement this method to handle pointer events.
+     * <p>
+     * This method is called to handle motion events where pointers are down on
+     * the view. For example, this could include touchscreen touches, stylus
+     * touches, or click-and-drag events from a mouse. However, it is not called
+     * for motion events that do not involve pointers being down, such as hover
+     * events or mouse scroll wheel movements.
      * <p>
      * If this method is used to detect click actions, it is recommended that
      * the actions be performed by implementing and calling
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f021bdf..e10cc28 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4345,6 +4345,7 @@
 
             handleSyncRequestWhenNoAsyncDraw(mActiveSurfaceSyncGroup, mHasPendingTransactions,
                     mPendingTransaction, "view not visible");
+            mHasPendingTransactions = false;
         } else if (cancelAndRedraw) {
             if (!mWasLastDrawCanceled) {
                 logAndTrace("Canceling draw."
@@ -4372,6 +4373,7 @@
             if (!performDraw(mActiveSurfaceSyncGroup)) {
                 handleSyncRequestWhenNoAsyncDraw(mActiveSurfaceSyncGroup, mHasPendingTransactions,
                         mPendingTransaction, mLastPerformDrawSkippedReason);
+                mHasPendingTransactions = false;
             }
         }
         mWasLastDrawCanceled = cancelAndRedraw;
@@ -4388,7 +4390,14 @@
             mReportNextDraw = false;
             mLastReportNextDrawReason = null;
             mActiveSurfaceSyncGroup = null;
-            mHasPendingTransactions = false;
+            if (mHasPendingTransactions) {
+                // TODO: We shouldn't ever actually hit this, it means mPendingTransaction wasn't
+                // merged with a sync group or BLASTBufferQueue before making it to this point
+                // But better a one or two frame flicker than steady-state broken from dropping
+                // whatever is in this transaction
+                mPendingTransaction.apply();
+                mHasPendingTransactions = false;
+            }
             mSyncBuffer = false;
             if (isInWMSRequestedSync()) {
                 mWmsRequestSyncGroup.markSyncReady();
@@ -5305,6 +5314,7 @@
     private void registerCallbackForPendingTransactions() {
         Transaction t = new Transaction();
         t.merge(mPendingTransaction);
+        mHasPendingTransactions = false;
 
         registerRtFrameCallback(new FrameDrawingCallback() {
             @Override
@@ -5384,6 +5394,7 @@
         if (!usingAsyncReport && mHasPendingTransactions) {
             pendingTransaction = new Transaction();
             pendingTransaction.merge(mPendingTransaction);
+            mHasPendingTransactions = false;
         } else {
             pendingTransaction = null;
         }
@@ -9942,6 +9953,7 @@
         }
         handleSyncRequestWhenNoAsyncDraw(mActiveSurfaceSyncGroup, mHasPendingTransactions,
                 mPendingTransaction, "shutting down VRI");
+        mHasPendingTransactions = false;
         WindowManagerGlobal.getInstance().doRemoveView(this);
     }
 
@@ -12601,6 +12613,7 @@
         if (mHasPendingTransactions) {
             t = new Transaction();
             t.merge(mPendingTransaction);
+            mHasPendingTransactions = false;
         } else {
             t = null;
         }
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index 8501474..4c5802c 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -137,9 +137,13 @@
      */
     @Deprecated
     public void detachDrawGlFunctor(View containerView, long nativeDrawGLFunctor) {
-        ViewRootImpl viewRootImpl = containerView.getViewRootImpl();
-        if (nativeDrawGLFunctor != 0 && viewRootImpl != null) {
-            viewRootImpl.detachFunctor(nativeDrawGLFunctor);
+        if (Flags.mainlineApis()) {
+            throw new UnsupportedOperationException();
+        } else {
+            ViewRootImpl viewRootImpl = containerView.getViewRootImpl();
+            if (nativeDrawGLFunctor != 0 && viewRootImpl != null) {
+                viewRootImpl.detachFunctor(nativeDrawGLFunctor);
+            }
         }
     }
 
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index eb35817..a395c1a 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1447,6 +1447,11 @@
                         }
 
                         @Override
+                        public void onNullBinding(ComponentName name) {
+                            context.unbindService(this);
+                        }
+
+                        @Override
                         public void onServiceDisconnected(ComponentName componentName) { }
                     });
 
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 2f28a87..118edc2 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -241,6 +241,11 @@
         }
 
         @Override
+        public void onNullBinding(ComponentName name) {
+            enqueueDeferredUnbindServiceMessage();
+        }
+
+        @Override
         public void handleMessage(Message msg) {
             RemoteViewsAdapter adapter = mAdapter.get();
 
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index b5bf529..511c832 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import static android.view.flags.Flags.enableTouchScrollFeedback;
 import static android.view.flags.Flags.viewVelocityApi;
 
 import android.annotation.ColorInt;
@@ -846,6 +847,8 @@
                         deltaY += mTouchSlop;
                     }
                 }
+                boolean hitTopLimit = false;
+                boolean hitBottomLimit = false;
                 if (mIsBeingDragged) {
                     // Scroll to follow the motion event
                     mLastMotionY = y - mScrollOffset[1];
@@ -889,12 +892,14 @@
                             if (!mEdgeGlowBottom.isFinished()) {
                                 mEdgeGlowBottom.onRelease();
                             }
+                            hitTopLimit = true;
                         } else if (pulledToY > range) {
                             mEdgeGlowBottom.onPullDistance((float) deltaY / getHeight(),
                                     1.f - displacement);
                             if (!mEdgeGlowTop.isFinished()) {
                                 mEdgeGlowTop.onRelease();
                             }
+                            hitBottomLimit = true;
                         }
                         if (shouldDisplayEdgeEffects()
                                 && (!mEdgeGlowTop.isFinished() || !mEdgeGlowBottom.isFinished())) {
@@ -902,6 +907,20 @@
                         }
                     }
                 }
+
+                // TODO: b/360198915 - Add unit tests.
+                if (enableTouchScrollFeedback()) {
+                    if (hitTopLimit || hitBottomLimit) {
+                        initHapticScrollFeedbackProviderIfNotExists();
+                        mHapticScrollFeedbackProvider.onScrollLimit(vtev.getDeviceId(),
+                                vtev.getSource(), MotionEvent.AXIS_Y,
+                                /* isStart= */ hitTopLimit);
+                    } else if (Math.abs(deltaY) != 0) {
+                        initHapticScrollFeedbackProviderIfNotExists();
+                        mHapticScrollFeedbackProvider.onScrollProgress(vtev.getDeviceId(),
+                                vtev.getSource(), MotionEvent.AXIS_Y, deltaY);
+                    }
+                }
                 break;
             case MotionEvent.ACTION_UP:
                 if (mIsBeingDragged) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a4b28ad..ef941da 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1659,11 +1659,7 @@
         }
 
         if (!hasUseBoundForWidthValue) {
-            if (CompatChanges.isChangeEnabled(USE_BOUNDS_FOR_WIDTH)) {
-                mUseBoundsForWidth = Flags.useBoundsForWidth();
-            } else {
-                mUseBoundsForWidth = false;
-            }
+            mUseBoundsForWidth = CompatChanges.isChangeEnabled(USE_BOUNDS_FOR_WIDTH);
         }
 
         // TODO(b/179693024): Use a ChangeId instead.
diff --git a/core/java/android/widget/flags/flags.aconfig b/core/java/android/widget/flags/flags.aconfig
new file mode 100644
index 0000000..f0ed83b
--- /dev/null
+++ b/core/java/android/widget/flags/flags.aconfig
@@ -0,0 +1,11 @@
+package: "android.widget.flags"
+container: "system"
+flag {
+  name: "enable_fading_view_group"
+  namespace: "system_performance"
+  description: "FRP screen during OOBE must have fading and scaling animation in Wear Watches"
+  bug: "348515581"
+  metadata {
+      purpose: PURPOSE_BUGFIX
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/window/TaskFragmentOrganizer.java b/core/java/android/window/TaskFragmentOrganizer.java
index 4cc0d8a..c3168001 100644
--- a/core/java/android/window/TaskFragmentOrganizer.java
+++ b/core/java/android/window/TaskFragmentOrganizer.java
@@ -69,6 +69,23 @@
     public static final String KEY_ERROR_CALLBACK_OP_TYPE = "operation_type";
 
     /**
+     * Key to bundle {@link TaskFragmentInfo}s from the system in
+     * {@link #registerOrganizer(boolean, Bundle)}
+     *
+     * @hide
+     */
+    public static final String KEY_RESTORE_TASK_FRAGMENTS_INFO = "key_restore_task_fragments_info";
+
+    /**
+     * Key to bundle {@link TaskFragmentParentInfo} from the system in
+     * {@link #registerOrganizer(boolean, Bundle)}
+     *
+     * @hide
+     */
+    public static final String KEY_RESTORE_TASK_FRAGMENT_PARENT_INFO =
+            "key_restore_task_fragment_parent_info";
+
+    /**
      * No change set.
      */
     @WindowManager.TransitionType
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 405217c..3998ac6 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -23,6 +23,13 @@
 }
 
 flag {
+    name: "enable_windowing_scaled_resizing"
+    namespace: "lse_desktop_experience"
+    description: "Enables the resizing of non-resizable apps through scaling their bounds up/down"
+    bug: "319844447"
+}
+
+flag {
     name: "disable_non_resizable_app_snap_resizing"
     namespace: "lse_desktop_experience"
     description: "Stops non-resizable app desktop windows from being snap resized"
diff --git a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
index 07fa679..dfb2884 100644
--- a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
@@ -18,6 +18,10 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
+import android.ravenwood.annotation.RavenwoodReplace;
 
 import com.android.internal.util.Preconditions;
 
@@ -55,18 +59,15 @@
  *
  * @hide
  */
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
-        "com.android.platform.test.ravenwood.nativesubstitution.LongArrayMultiStateCounter_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("LongArrayMultiStateCounter_host")
 public final class LongArrayMultiStateCounter implements Parcelable {
 
     /**
      * Container for a native equivalent of a long[].
      */
-    @android.ravenwood.annotation.RavenwoodKeepWholeClass
-    @android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
-            "com.android.platform.test.ravenwood.nativesubstitution"
-            + ".LongArrayMultiStateCounter_host$LongArrayContainer_host")
+    @RavenwoodKeepWholeClass
+    @RavenwoodRedirectionClass("LongArrayContainer_host")
     public static class LongArrayContainer {
         private static NativeAllocationRegistry sRegistry;
 
@@ -81,7 +82,7 @@
             registerNativeAllocation();
         }
 
-        @android.ravenwood.annotation.RavenwoodReplace
+        @RavenwoodReplace
         private void registerNativeAllocation() {
             if (sRegistry == null) {
                 synchronized (LongArrayMultiStateCounter.class) {
@@ -140,18 +141,23 @@
         }
 
         @CriticalNative
+        @RavenwoodRedirect
         private static native long native_init(int length);
 
         @CriticalNative
+        @RavenwoodRedirect
         private static native long native_getReleaseFunc();
 
         @FastNative
+        @RavenwoodRedirect
         private static native void native_setValues(long nativeObject, long[] array);
 
         @FastNative
+        @RavenwoodRedirect
         private static native void native_getValues(long nativeObject, long[] array);
 
         @FastNative
+        @RavenwoodRedirect
         private static native boolean native_combineValues(long nativeObject, long[] array,
                 int[] indexMap);
     }
@@ -175,7 +181,7 @@
         registerNativeAllocation();
     }
 
-    @android.ravenwood.annotation.RavenwoodReplace
+    @RavenwoodReplace
     private void registerNativeAllocation() {
         if (sRegistry == null) {
             synchronized (LongArrayMultiStateCounter.class) {
@@ -374,57 +380,73 @@
 
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native long native_init(int stateCount, int arrayLength);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native long native_getReleaseFunc();
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_setEnabled(long nativeObject, boolean enabled,
             long timestampMs);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_setState(long nativeObject, int state, long timestampMs);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_copyStatesFrom(long nativeObjectTarget,
             long nativeObjectSource);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_setValues(long nativeObject, int state,
             long longArrayContainerNativeObject);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_updateValues(long nativeObject,
             long longArrayContainerNativeObject, long timestampMs);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_incrementValues(long nativeObject,
             long longArrayContainerNativeObject, long timestampMs);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_addCounts(long nativeObject,
             long longArrayContainerNativeObject);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_reset(long nativeObject);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_getCounts(long nativeObject,
             long longArrayContainerNativeObject, int state);
 
     @FastNative
+    @RavenwoodRedirect
     private static native String native_toString(long nativeObject);
 
     @FastNative
+    @RavenwoodRedirect
     private static native void native_writeToParcel(long nativeObject, Parcel dest, int flags);
 
     @FastNative
+    @RavenwoodRedirect
     private static native long native_initFromParcel(Parcel parcel);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native int native_getStateCount(long nativeObject);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native int native_getArrayLength(long nativeObject);
 }
diff --git a/core/java/com/android/internal/os/LongMultiStateCounter.java b/core/java/com/android/internal/os/LongMultiStateCounter.java
index e5662c7..c386a86 100644
--- a/core/java/com/android/internal/os/LongMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongMultiStateCounter.java
@@ -18,6 +18,10 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
+import android.ravenwood.annotation.RavenwoodReplace;
 
 import com.android.internal.util.Preconditions;
 
@@ -55,9 +59,8 @@
  *
  * @hide
  */
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
-        "com.android.platform.test.ravenwood.nativesubstitution.LongMultiStateCounter_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("LongMultiStateCounter_host")
 public final class LongMultiStateCounter implements Parcelable {
 
     private static NativeAllocationRegistry sRegistry;
@@ -82,7 +85,7 @@
         mStateCount = native_getStateCount(mNativeObject);
     }
 
-    @android.ravenwood.annotation.RavenwoodReplace
+    @RavenwoodReplace
     private void registerNativeAllocation() {
         if (sRegistry == null) {
             synchronized (LongMultiStateCounter.class) {
@@ -210,43 +213,56 @@
 
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native long native_init(int stateCount);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native long native_getReleaseFunc();
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_setEnabled(long nativeObject, boolean enabled,
             long timestampMs);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_setState(long nativeObject, int state, long timestampMs);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native long native_updateValue(long nativeObject, long value, long timestampMs);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_incrementValue(long nativeObject, long increment,
             long timestampMs);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_addCount(long nativeObject, long count);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native void native_reset(long nativeObject);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native long native_getCount(long nativeObject, int state);
 
     @FastNative
+    @RavenwoodRedirect
     private static native String native_toString(long nativeObject);
 
     @FastNative
+    @RavenwoodRedirect
     private static native void native_writeToParcel(long nativeObject, Parcel dest, int flags);
 
     @FastNative
+    @RavenwoodRedirect
     private static native long native_initFromParcel(Parcel parcel);
 
     @CriticalNative
+    @RavenwoodRedirect
     private static native int native_getStateCount(long nativeObject);
 }
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index cdac097..1709ca7 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -404,6 +404,17 @@
     }
 
     public static void redirectLogStreams$ravenwood() {
+        if (sOut$ravenwood != null && sErr$ravenwood != null) {
+            return; // Already initialized.
+        }
+
+        // Make sure the Log class is loaded and the JNI methods are hooked up,
+        // before redirecting System.out/err.
+        // Otherwise, because ClassLoadHook tries to write to System.out, this would cause
+        // a circular initialization problem and would cause a UnsatisfiedLinkError
+        // on the JNI methods.
+        Log.isLoggable("X", Log.VERBOSE);
+
         if (sOut$ravenwood == null) {
             sOut$ravenwood = System.out;
             System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
diff --git a/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
index 12d3264..032ac42 100644
--- a/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
+++ b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
@@ -3025,6 +3025,7 @@
     @Override
     public PackageImpl setSplitCodePaths(@Nullable String[] splitCodePaths) {
         this.splitCodePaths = splitCodePaths;
+        this.mSplits = null; // reset for paths changed
         if (splitCodePaths != null) {
             int size = splitCodePaths.length;
             for (int index = 0; index < size; index++) {
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 58818f3..4708be8 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1144,7 +1144,8 @@
             mDrawLegacyNavigationBarBackground =
                     ((requestedVisibleTypes | mLastForceConsumingTypes)
                             & WindowInsets.Type.navigationBars()) != 0
-                    && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0;
+                    && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
+                    && navBarSize > 0;
             if (oldDrawLegacy != mDrawLegacyNavigationBarBackground) {
                 mDrawLegacyNavigationBarBackgroundHandled =
                         mWindow.onDrawLegacyNavigationBarBackgroundChanged(
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index 1fd933f..e440dc9 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -34,7 +34,6 @@
 import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MESSAGES;
 import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.GROUP_ID;
 import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.LEVEL;
-import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.LOCATION;
 import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE;
 import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.INTERNED_DATA;
 import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.PROTOLOG_MESSAGE;
@@ -72,7 +71,6 @@
 
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
@@ -103,6 +101,7 @@
     private final ProtoLogDataSource mDataSource;
     @Nullable
     private final ProtoLogViewerConfigReader mViewerConfigReader;
+    @Deprecated
     @Nullable
     private final ViewerConfigInputStreamProvider mViewerConfigInputStreamProvider;
     @NonNull
@@ -148,6 +147,7 @@
                 cacheUpdater, groups);
     }
 
+    @Deprecated
     @VisibleForTesting
     public PerfettoProtoLogImpl(
             @Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
@@ -160,6 +160,18 @@
                 groups, dataSourceBuilder, configurationService);
     }
 
+    @VisibleForTesting
+    public PerfettoProtoLogImpl(
+            @Nullable String viewerConfigFilePath,
+            @Nullable ProtoLogViewerConfigReader viewerConfigReader,
+            @NonNull Runnable cacheUpdater,
+            @NonNull IProtoLogGroup[] groups,
+            @NonNull ProtoLogDataSourceBuilder dataSourceBuilder,
+            @NonNull ProtoLogConfigurationService configurationService) {
+        this(viewerConfigFilePath, null, viewerConfigReader, cacheUpdater,
+                groups, dataSourceBuilder, configurationService);
+    }
+
     private PerfettoProtoLogImpl(
             @Nullable String viewerConfigFilePath,
             @Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
@@ -449,6 +461,7 @@
         Log.d(LOG_TAG, "Finished onTracingFlush");
     }
 
+    @Deprecated
     private void dumpViewerConfig() {
         if (mViewerConfigInputStreamProvider == null) {
             // No viewer config available
@@ -457,103 +470,29 @@
 
         Log.d(LOG_TAG, "Dumping viewer config to trace");
 
-        mDataSource.trace(ctx -> {
-            try {
-                ProtoInputStream pis = mViewerConfigInputStreamProvider.getInputStream();
-
-                final ProtoOutputStream os = ctx.newTracePacket();
-
-                os.write(TIMESTAMP, SystemClock.elapsedRealtimeNanos());
-
-                final long outProtologViewerConfigToken = os.start(PROTOLOG_VIEWER_CONFIG);
-                while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
-                    if (pis.getFieldNumber() == (int) MESSAGES) {
-                        writeViewerConfigMessage(pis, os);
-                    }
-
-                    if (pis.getFieldNumber() == (int) GROUPS) {
-                        writeViewerConfigGroup(pis, os);
-                    }
-                }
-
-                os.end(outProtologViewerConfigToken);
-            } catch (IOException e) {
-                Log.e(LOG_TAG, "Failed to read ProtoLog viewer config to dump on tracing end", e);
-            }
-        });
+        Utils.dumpViewerConfig(mDataSource, mViewerConfigInputStreamProvider);
 
         Log.d(LOG_TAG, "Dumped viewer config to trace");
     }
 
-    private static void writeViewerConfigGroup(
-            ProtoInputStream pis, ProtoOutputStream os) throws IOException {
-        final long inGroupToken = pis.start(GROUPS);
-        final long outGroupToken = os.start(GROUPS);
-
-        while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
-            switch (pis.getFieldNumber()) {
-                case (int) ID:
-                    int id = pis.readInt(ID);
-                    os.write(ID, id);
-                    break;
-                case (int) NAME:
-                    String name = pis.readString(NAME);
-                    os.write(NAME, name);
-                    break;
-                case (int) TAG:
-                    String tag = pis.readString(TAG);
-                    os.write(TAG, tag);
-                    break;
-                default:
-                    throw new RuntimeException(
-                            "Unexpected field id " + pis.getFieldNumber());
-            }
-        }
-
-        pis.end(inGroupToken);
-        os.end(outGroupToken);
-    }
-
-    private static void writeViewerConfigMessage(
-            ProtoInputStream pis, ProtoOutputStream os) throws IOException {
-        final long inMessageToken = pis.start(MESSAGES);
-        final long outMessagesToken = os.start(MESSAGES);
-
-        while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
-            switch (pis.getFieldNumber()) {
-                case (int) MessageData.MESSAGE_ID:
-                    os.write(MessageData.MESSAGE_ID,
-                            pis.readLong(MessageData.MESSAGE_ID));
-                    break;
-                case (int) MESSAGE:
-                    os.write(MESSAGE, pis.readString(MESSAGE));
-                    break;
-                case (int) LEVEL:
-                    os.write(LEVEL, pis.readInt(LEVEL));
-                    break;
-                case (int) GROUP_ID:
-                    os.write(GROUP_ID, pis.readInt(GROUP_ID));
-                    break;
-                case (int) LOCATION:
-                    os.write(LOCATION, pis.readString(LOCATION));
-                    break;
-                default:
-                    throw new RuntimeException(
-                            "Unexpected field id " + pis.getFieldNumber());
-            }
-        }
-
-        pis.end(inMessageToken);
-        os.end(outMessagesToken);
-    }
-
     private void logToLogcat(String tag, LogLevel level, Message message,
             @Nullable Object[] args) {
         String messageString;
         if (mViewerConfigReader == null) {
             messageString = message.getMessage();
+
+            if (messageString == null) {
+                Log.e(LOG_TAG, "Failed to decode message for logcat. "
+                        + "Message not available without ViewerConfig to decode the hash.");
+            }
         } else {
             messageString = message.getMessage(mViewerConfigReader);
+
+            if (messageString == null) {
+                Log.e(LOG_TAG, "Failed to decode message for logcat. "
+                        + "Message hash either not available in viewerConfig file or "
+                        + "not loaded into memory from file before decoding.");
+            }
         }
 
         if (messageString == null) {
@@ -760,7 +699,7 @@
 
             os.write(MessageData.MESSAGE_ID, messageHash);
             os.write(MESSAGE, message);
-            os.write(LEVEL, level.ordinal());
+            os.write(LEVEL, level.id);
             os.write(GROUP_ID, logGroup.getId());
 
             os.end(messageConfigToken);
@@ -954,8 +893,7 @@
     private static class Message {
         @Nullable
         private final Long mMessageHash;
-        @Nullable
-        private final Integer mMessageMask;
+        private final int mMessageMask;
         @Nullable
         private final String mMessageString;
 
@@ -972,8 +910,7 @@
             this.mMessageString = messageString;
         }
 
-        @Nullable
-        private Integer getMessageMask() {
+        private int getMessageMask() {
             return mMessageMask;
         }
 
diff --git a/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java b/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java
index d54a80b..7031d69 100644
--- a/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java
+++ b/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java
@@ -26,8 +26,6 @@
 import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.LOCATION;
 import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE;
 import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID;
-import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.PROTOLOG_VIEWER_CONFIG;
-import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.TIMESTAMP;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -36,7 +34,6 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
-import android.os.SystemClock;
 import android.tracing.perfetto.DataSourceParams;
 import android.tracing.perfetto.InitArguments;
 import android.tracing.perfetto.Producer;
@@ -125,7 +122,8 @@
         this(ProtoLogDataSource::new, tracer);
     }
 
-    private ProtoLogConfigurationService(
+    @VisibleForTesting
+    public ProtoLogConfigurationService(
             @NonNull ProtoLogDataSourceBuilder dataSourceBuilder,
             @NonNull ViewerConfigFileTracer tracer) {
         mDataSource = dataSourceBuilder.build(
@@ -374,32 +372,13 @@
 
     private static void dumpTransitionTraceConfig(@NonNull ProtoLogDataSource dataSource,
             @NonNull String viewerConfigFilePath) {
-        dataSource.trace(ctx -> {
-            final ProtoInputStream pis;
+        Utils.dumpViewerConfig(dataSource, () -> {
             try {
-                pis = new ProtoInputStream(new FileInputStream(viewerConfigFilePath));
+                return new ProtoInputStream(new FileInputStream(viewerConfigFilePath));
             } catch (FileNotFoundException e) {
                 throw new RuntimeException(
                         "Failed to load viewer config file " + viewerConfigFilePath, e);
             }
-
-            try {
-                final ProtoOutputStream os = ctx.newTracePacket();
-
-                os.write(TIMESTAMP, SystemClock.elapsedRealtimeNanos());
-
-                final long outProtologViewerConfigToken = os.start(PROTOLOG_VIEWER_CONFIG);
-                while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
-                    switch (pis.getFieldNumber()) {
-                        case (int) MESSAGES -> writeViewerConfigMessage(pis, os);
-                        case (int) GROUPS -> writeViewerConfigGroup(pis, os);
-                    }
-                }
-
-                os.end(outProtologViewerConfigToken);
-            } catch (IOException e) {
-                Log.e(LOG_TAG, "Failed to read ProtoLog viewer config to dump on tracing end", e);
-            }
         });
     }
 
diff --git a/core/java/com/android/internal/protolog/ProtoLogDataSource.java b/core/java/com/android/internal/protolog/ProtoLogDataSource.java
index 1b2f5f7..0afb135 100644
--- a/core/java/com/android/internal/protolog/ProtoLogDataSource.java
+++ b/core/java/com/android/internal/protolog/ProtoLogDataSource.java
@@ -283,10 +283,24 @@
     public static class Instance extends DataSourceInstance {
 
         public interface TracingInstanceStartCallback {
+            /**
+             * Execute the tracing instance's onStart callback.
+             * @param instanceIdx The index of the tracing instance we are executing the callback
+             *                    for.
+             * @param config The protolog configuration for the tracing instance we are executing
+             *               the callback for.
+             */
             void run(int instanceIdx, @NonNull ProtoLogConfig config);
         }
 
         public interface TracingInstanceStopCallback {
+            /**
+             * Execute the tracing instance's onStop callback.
+             * @param instanceIdx The index of the tracing instance we are executing the callback
+             *                    for.
+             * @param config The protolog configuration for the tracing instance we are executing
+             *               the callback for.
+             */
             void run(int instanceIdx, @NonNull ProtoLogConfig config);
         }
 
diff --git a/core/java/com/android/internal/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java
index da6d8cf..7bdcf2d 100644
--- a/core/java/com/android/internal/protolog/ProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java
@@ -23,6 +23,7 @@
 import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.VIEWER_CONFIG_PATH;
 
 import android.annotation.Nullable;
+import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.IProtoLog;
@@ -37,6 +38,8 @@
  * A service for the ProtoLog logging system.
  */
 public class ProtoLogImpl {
+    private static final String LOG_TAG = "ProtoLogImpl";
+
     private static IProtoLog sServiceInstance = null;
 
     @ProtoLogToolInjected(VIEWER_CONFIG_PATH)
@@ -97,6 +100,9 @@
      */
     public static synchronized IProtoLog getSingleInstance() {
         if (sServiceInstance == null) {
+            Log.i(LOG_TAG, "Setting up " + ProtoLogImpl.class.getSimpleName() + " with "
+                    + "viewerConfigPath = " + sViewerConfigPath);
+
             final var groups = sLogGroups.values().toArray(new IProtoLogGroup[0]);
 
             if (android.tracing.Flags.perfettoProtologTracing()) {
@@ -105,6 +111,9 @@
                     // TODO(b/353530422): Remove - temporary fix to unblock b/352290057
                     // In some tests the viewer config file might not exist in which we don't
                     // want to provide config path to the user
+                    Log.w(LOG_TAG, "Failed to find viewerConfigFile when setting up "
+                            + ProtoLogImpl.class.getSimpleName() + ". "
+                            + "Setting up without a viewer config instead...");
                     sServiceInstance = new PerfettoProtoLogImpl(sCacheUpdater, groups);
                 } else {
                     sServiceInstance =
diff --git a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
index 6c8996e..0a80e00 100644
--- a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
+++ b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
@@ -43,6 +43,13 @@
         return mLogMessageMap.get(messageHash);
     }
 
+    /**
+     * Load the viewer configs for the target groups into memory.
+     * Only viewer configs loaded into memory can be required. So this must be called for all groups
+     * we want to query before we query their viewer config.
+     *
+     * @param groups Groups to load the viewer configs from file into memory.
+     */
     public synchronized void loadViewerConfig(@NonNull String[] groups) {
         loadViewerConfig(groups, (message) -> {});
     }
diff --git a/core/java/com/android/internal/protolog/Utils.java b/core/java/com/android/internal/protolog/Utils.java
new file mode 100644
index 0000000..1e6ba30
--- /dev/null
+++ b/core/java/com/android/internal/protolog/Utils.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.protolog;
+
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.GROUPS;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.ID;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.NAME;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.TAG;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MESSAGES;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.GROUP_ID;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.LEVEL;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.LOCATION;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.PROTOLOG_VIEWER_CONFIG;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.TIMESTAMP;
+
+import android.annotation.NonNull;
+import android.internal.perfetto.protos.Protolog;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.proto.ProtoInputStream;
+import android.util.proto.ProtoOutputStream;
+
+import java.io.IOException;
+
+public class Utils {
+    private static final String LOG_TAG = "ProtoLogUtils";
+
+    /**
+     * Dump the viewer config provided by the input stream to the target datasource.
+     * @param dataSource The datasource to dump the ProtoLog viewer config to.
+     * @param viewerConfigInputStreamProvider The InputStream that provided the proto viewer config.
+     */
+    public static void dumpViewerConfig(@NonNull ProtoLogDataSource dataSource,
+            @NonNull ViewerConfigInputStreamProvider viewerConfigInputStreamProvider) {
+        dataSource.trace(ctx -> {
+            try {
+                ProtoInputStream pis = viewerConfigInputStreamProvider.getInputStream();
+
+                final ProtoOutputStream os = ctx.newTracePacket();
+
+                os.write(TIMESTAMP, SystemClock.elapsedRealtimeNanos());
+
+                final long outProtologViewerConfigToken = os.start(PROTOLOG_VIEWER_CONFIG);
+                while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+                    if (pis.getFieldNumber() == (int) MESSAGES) {
+                        writeViewerConfigMessage(pis, os);
+                    }
+
+                    if (pis.getFieldNumber() == (int) GROUPS) {
+                        writeViewerConfigGroup(pis, os);
+                    }
+                }
+
+                os.end(outProtologViewerConfigToken);
+            } catch (IOException e) {
+                Log.e(LOG_TAG, "Failed to read ProtoLog viewer config to dump to datasource", e);
+            }
+        });
+    }
+
+    private static void writeViewerConfigGroup(
+            @NonNull ProtoInputStream pis, @NonNull ProtoOutputStream os) throws IOException {
+        final long inGroupToken = pis.start(GROUPS);
+        final long outGroupToken = os.start(GROUPS);
+
+        while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+            switch (pis.getFieldNumber()) {
+                case (int) ID:
+                    int id = pis.readInt(ID);
+                    os.write(ID, id);
+                    break;
+                case (int) NAME:
+                    String name = pis.readString(NAME);
+                    os.write(NAME, name);
+                    break;
+                case (int) TAG:
+                    String tag = pis.readString(TAG);
+                    os.write(TAG, tag);
+                    break;
+                default:
+                    throw new RuntimeException(
+                            "Unexpected field id " + pis.getFieldNumber());
+            }
+        }
+
+        pis.end(inGroupToken);
+        os.end(outGroupToken);
+    }
+
+    private static void writeViewerConfigMessage(
+            ProtoInputStream pis, ProtoOutputStream os) throws IOException {
+        final long inMessageToken = pis.start(MESSAGES);
+        final long outMessagesToken = os.start(MESSAGES);
+
+        while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+            switch (pis.getFieldNumber()) {
+                case (int) Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID:
+                    os.write(Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID,
+                            pis.readLong(Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID));
+                    break;
+                case (int) MESSAGE:
+                    os.write(MESSAGE, pis.readString(MESSAGE));
+                    break;
+                case (int) LEVEL:
+                    os.write(LEVEL, pis.readInt(LEVEL));
+                    break;
+                case (int) GROUP_ID:
+                    os.write(GROUP_ID, pis.readInt(GROUP_ID));
+                    break;
+                case (int) LOCATION:
+                    os.write(LOCATION, pis.readString(LOCATION));
+                    break;
+                default:
+                    throw new RuntimeException(
+                            "Unexpected field id " + pis.getFieldNumber());
+            }
+        }
+
+        pis.end(inMessageToken);
+        os.end(outMessagesToken);
+    }
+
+}
diff --git a/core/java/com/android/internal/protolog/common/LogLevel.java b/core/java/com/android/internal/protolog/common/LogLevel.java
index 16c34e1..b5541ae 100644
--- a/core/java/com/android/internal/protolog/common/LogLevel.java
+++ b/core/java/com/android/internal/protolog/common/LogLevel.java
@@ -17,10 +17,18 @@
 package com.android.internal.protolog.common;
 
 public enum LogLevel {
-    DEBUG("d"), VERBOSE("v"), INFO("i"), WARN("w"), ERROR("e"), WTF("wtf");
+    DEBUG("d", 1),
+    VERBOSE("v", 2),
+    INFO("i", 3),
+    WARN("w", 4),
+    ERROR("e", 5),
+    WTF("wtf", 6);
 
     public final String shortCode;
-    LogLevel(String shortCode) {
+    public final int id;
+
+    LogLevel(String shortCode, int id) {
         this.shortCode = shortCode;
+        this.id = id;
     }
 }
diff --git a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
index 319efe0..30b160a 100644
--- a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
+++ b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
@@ -16,15 +16,15 @@
 package com.android.internal.ravenwood;
 
 import android.ravenwood.annotation.RavenwoodKeepWholeClass;
-import android.ravenwood.annotation.RavenwoodNativeSubstitutionClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
 import android.ravenwood.annotation.RavenwoodReplace;
 
 /**
  * Class to interact with the Ravenwood environment.
  */
 @RavenwoodKeepWholeClass
-@RavenwoodNativeSubstitutionClass(
-        "com.android.platform.test.ravenwood.nativesubstitution.RavenwoodEnvironment_host")
+@RavenwoodRedirectionClass("RavenwoodEnvironment_host")
 public final class RavenwoodEnvironment {
     public static final String TAG = "RavenwoodEnvironment";
 
@@ -40,7 +40,7 @@
         ensureRavenwoodInitialized();
     }
 
-    private static RuntimeException notSupportedOnDevice() {
+    public static RuntimeException notSupportedOnDevice() {
         return new UnsupportedOperationException("This method can only be used on Ravenwood");
     }
 
@@ -56,14 +56,10 @@
      *
      * No-op if called on the device side.
      */
-    @RavenwoodReplace
+    @RavenwoodRedirect
     public static void ensureRavenwoodInitialized() {
     }
 
-    private static void ensureRavenwoodInitialized$ravenwood() {
-        nativeEnsureRavenwoodInitialized();
-    }
-
     /**
      * USE IT SPARINGLY! Returns true if it's running on Ravenwood, hostside test environment.
      *
@@ -89,15 +85,11 @@
      * Get the object back from the address obtained from
      * {@link dalvik.system.VMRuntime#addressOf(Object)}.
      */
-    @RavenwoodReplace
+    @RavenwoodRedirect
     public <T> T fromAddress(long address) {
         throw notSupportedOnDevice();
     }
 
-    private <T> T fromAddress$ravenwood(long address) {
-        return nativeFromAddress(address);
-    }
-
     /**
      * See {@link Workaround}. It's only usable on Ravenwood.
      */
@@ -113,20 +105,11 @@
     /**
      * @return the "ravenwood-runtime" directory.
      */
-    @RavenwoodReplace
+    @RavenwoodRedirect
     public String getRavenwoodRuntimePath() {
         throw notSupportedOnDevice();
     }
 
-    private String getRavenwoodRuntimePath$ravenwood() {
-        return nativeGetRavenwoodRuntimePath();
-    }
-
-    // Private native methods that are actually substituted on Ravenwood
-    private native <T> T nativeFromAddress(long address);
-    private native String nativeGetRavenwoodRuntimePath();
-    private static native void nativeEnsureRavenwoodInitialized();
-
     /**
      * A set of APIs used to work around missing features on Ravenwood. Ideally, this class should
      * be empty, and all its APIs should be able to be implemented properly.
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 11c220b..0ec55f9 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -120,6 +120,7 @@
     private static final String TAG = "LockPatternView";
 
     private OnPatternListener mOnPatternListener;
+    private ExternalHapticsPlayer mExternalHapticsPlayer;
     @UnsupportedAppUsage
     private final ArrayList<Cell> mPattern = new ArrayList<Cell>(9);
 
@@ -317,6 +318,13 @@
         void onPatternDetected(List<Cell> pattern);
     }
 
+    /** An external haptics player for pattern updates. */
+    public interface ExternalHapticsPlayer{
+
+        /** Perform haptic feedback when a cell is added to the pattern. */
+        void performCellAddedFeedback();
+    }
+
     public LockPatternView(Context context) {
         this(context, null);
     }
@@ -461,6 +469,15 @@
     }
 
     /**
+     * Set the external haptics player for feedback on pattern detection.
+     * @param player The external player.
+     */
+    @UnsupportedAppUsage
+    public void setExternalHapticsPlayer(ExternalHapticsPlayer player) {
+        mExternalHapticsPlayer = player;
+    }
+
+    /**
      * Set the pattern explicitely (rather than waiting for the user to input
      * a pattern).
      * @param displayMode How to display the pattern.
@@ -847,6 +864,16 @@
         return null;
     }
 
+    @Override
+    public boolean performHapticFeedback(int feedbackConstant, int flags) {
+        if (mExternalHapticsPlayer != null) {
+            mExternalHapticsPlayer.performCellAddedFeedback();
+            return true;
+        } else {
+            return super.performHapticFeedback(feedbackConstant, flags);
+        }
+    }
+
     private void addCellToPattern(Cell newCell) {
         mPatternDrawLookup[newCell.getRow()][newCell.getColumn()] = true;
         mPattern.add(newCell);
diff --git a/core/java/com/android/internal/widget/ViewGroupFader.java b/core/java/com/android/internal/widget/ViewGroupFader.java
index b54023a..21206c2 100644
--- a/core/java/com/android/internal/widget/ViewGroupFader.java
+++ b/core/java/com/android/internal/widget/ViewGroupFader.java
@@ -16,12 +16,14 @@
 
 package com.android.internal.widget;
 
+import android.content.res.Resources;
 import android.graphics.Rect;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroup.MarginLayoutParams;
 import android.view.animation.BaseInterpolator;
 import android.view.animation.PathInterpolator;
+import android.widget.flags.Flags;
 
 /**
  * This class is ported from
@@ -36,7 +38,7 @@
  * height of the child. When not in the top or bottom regions, children have their default alpha and
  * scale.
  */
-class ViewGroupFader {
+public class ViewGroupFader {
 
     private static final float SCALE_LOWER_BOUND = 0.7f;
     private float mScaleLowerBound = SCALE_LOWER_BOUND;
@@ -68,7 +70,7 @@
     private BaseInterpolator mBottomInterpolator = new PathInterpolator(0.3f, 0f, 0.7f, 1f);
 
     /** Callback which is called when attempting to fade a view. */
-    interface AnimationCallback {
+    public interface AnimationCallback {
         boolean shouldFadeFromTop(View view);
 
         boolean shouldFadeFromBottom(View view);
@@ -82,7 +84,7 @@
      * of the current position.
      */
     // TODO(b/182846214): Clean up the interface design to avoid exposing too much details to users.
-    interface ChildViewBoundsProvider {
+    public interface ChildViewBoundsProvider {
         /**
          * Provide the bounds of the child view.
          *
@@ -168,7 +170,7 @@
         }
     }
 
-    ViewGroupFader(
+    public ViewGroupFader(
             ViewGroup parent,
             AnimationCallback callback,
             ChildViewBoundsProvider childViewBoundsProvider) {
@@ -212,7 +214,7 @@
         this.mContainerBoundsProvider = boundsProvider;
     }
 
-    void updateFade() {
+    public void updateFade() {
         mContainerBoundsProvider.provideBounds(mParent, mContainerBounds);
         mTopBoundPixels = mContainerBounds.height() * mChainedBoundsTop;
         mBottomBoundPixels = mContainerBounds.height() * mChainedBoundsBottom;
@@ -221,13 +223,20 @@
     }
 
     /** For each list element, calculate and adjust the scale and alpha based on its position */
-    private void updateListElementFades(ViewGroup parent, boolean shouldFade) {
+    public void updateListElementFades(ViewGroup parent, boolean shouldFade) {
         for (int i = 0; i < parent.getChildCount(); i++) {
             View child = parent.getChildAt(i);
             if (child.getVisibility() != View.VISIBLE) {
                 continue;
             }
 
+            if (Flags.enableFadingViewGroup() && Resources.getSystem().getBoolean(
+                    com.android.internal.R.bool.config_enableViewGroupScalingFading)) {
+                if (child instanceof ViewGroup) {
+                    updateListElementFades((ViewGroup) child, true);
+                }
+            }
+
             if (shouldFade) {
                 fadeElement(parent, child);
             }
@@ -312,4 +321,4 @@
     private static float lerp(float min, float max, float fraction) {
         return min + (max - min) * fraction;
     }
-}
+}
\ No newline at end of file
diff --git a/core/jni/android_view_TunnelModeEnabledListener.cpp b/core/jni/android_view_TunnelModeEnabledListener.cpp
index af7bae8..d9ab957 100644
--- a/core/jni/android_view_TunnelModeEnabledListener.cpp
+++ b/core/jni/android_view_TunnelModeEnabledListener.cpp
@@ -88,20 +88,19 @@
 
 void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr) {
     sp<TunnelModeEnabledListener> listener = reinterpret_cast<TunnelModeEnabledListener*>(ptr);
-    if (SurfaceComposerClient::addTunnelModeEnabledListener(listener) != OK) {
-        constexpr auto error_msg = "Couldn't addTunnelModeEnabledListener";
-        ALOGE(error_msg);
-        jniThrowRuntimeException(env, error_msg);
+    status_t status = SurfaceComposerClient::addTunnelModeEnabledListener(listener);
+    if (status != OK) {
+        ALOGE("Couldn't addTunnelModeEnabledListener (%d)", status);
+        jniThrowRuntimeException(env, "Couldn't addTunnelModeEnabledListener");
     }
 }
 
 void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) {
     sp<TunnelModeEnabledListener> listener = reinterpret_cast<TunnelModeEnabledListener*>(ptr);
-
-    if (SurfaceComposerClient::removeTunnelModeEnabledListener(listener) != OK) {
-        constexpr auto error_msg = "Couldn't removeTunnelModeEnabledListener";
-        ALOGE(error_msg);
-        jniThrowRuntimeException(env, error_msg);
+    status_t status = SurfaceComposerClient::removeTunnelModeEnabledListener(listener);
+    if (status != OK) {
+        ALOGE("Couldn't removeTunnelModeEnabledListener (%d)", status);
+        jniThrowRuntimeException(env, "Couldn't removeTunnelModeEnabledListener");
     }
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a19b71c..d35c66e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4033,7 +4033,6 @@
     <!-- Allows an application to manage policy related to block package uninstallation.
         <p>Protection level: internal|role
         <p>Intended for use by the DEVICE_POLICY_MANAGEMENT role only.
-        @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")
     -->
     <permission android:name="android.permission.MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL"
         android:protectionLevel="internal|role" />
@@ -4041,7 +4040,6 @@
     <!-- Allows an application to manage policy related to camera toggle.
         <p>Protection level: internal|role
         <p>Intended for use by the DEVICE_POLICY_MANAGEMENT role only.
-        @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")
     -->
     <permission android:name="android.permission.MANAGE_DEVICE_POLICY_CAMERA_TOGGLE"
         android:protectionLevel="internal|role" />
@@ -4049,7 +4047,6 @@
     <!-- Allows an application to manage policy related to microphone toggle.
         <p>Protection level: internal|role
         <p>Intended for use by the DEVICE_POLICY_MANAGEMENT role only.
-        @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")
     -->
     <permission android:name="android.permission.MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE"
         android:protectionLevel="internal|role" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 381111c..a1dea82 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"’n App verberg die toestemmingversoek en jou antwoord kan dus nie geverifieer word nie."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tik op \'n kenmerk om dit te begin gebruik:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Kies kenmerke om saam met die toeganklikheidknoppie te gebruik"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Kies kenmerke om saam met die volumesleutelkortpad te gebruik"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> is afgeskakel"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Wysig kortpaaie"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klaar"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index aa7dcec..2873785 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"አንድ መተግበሪያ የፍቃድ ጥያቄውን እያደበዘዘ ነው ስለዚህ የእርስዎ ምላሽ ሊረጋገጥ አይችልም።"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"አንድ ባህሪን መጠቀም ለመጀመር መታ ያድርጉት፦"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"በተደራሽነት አዝራር የሚጠቀሙባቸው ባሕሪያት ይምረጡ"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"በድምጽ ቁልፍ አቋራጭ የሚጠቀሙባቸው ባሕሪያት ይምረጡ"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ጠፍቷል"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"አቋራጮችን አርትዕ ያድርጉ"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ተከናውኗል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 4f03ff3..7f02576 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1750,7 +1750,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"تعذَّر التحقّق من ردّك بسبب حجب أحد التطبيقات طلب الحصول على الإذن."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"انقر على ميزة لبدء استخدامها:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"اختيار الميزات التي تريد استخدامها مع زر أدوات تمكين الوصول"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"اختيار الميزات التي تريد استخدامها مع اختصار مفتاح التحكّم في مستوى الصوت"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"تم إيقاف <xliff:g id="SERVICE_NAME">%s</xliff:g>."</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"تعديل الاختصارات"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"تم"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 8c9cda9..bc1dba27 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"এটা এপে অনুমতিৰ অনুৰোধটো অস্পষ্ট কৰি আছে আৰু সেয়েহে আপোনাৰ সঁহাৰিটো সত্যাপন কৰিব নোৱাৰি।"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"কোনো এটা সুবিধা ব্যৱহাৰ কৰিবলৈ সেইটোত টিপক:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"সাধ্য-সুবিধা বুটামটোৰ জৰিয়তে ব্যৱহাৰ কৰিবলৈ সুবিধাসমূহ বাছনি কৰক"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ভলিউম কীৰ শ্বৰ্টকাটটোৰ জৰিয়তে ব্যৱহাৰ কৰিবলৈ সুবিধাসমূহ বাছনি কৰক"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> বন্ধ কৰা হৈছে"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"শ্বৰ্টকাটসমূহ সম্পাদনা কৰক"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"কৰা হ’ল"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index afbe715..e93a57b 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Bir tətbiq icazə sorğusunu gizlətdiyi üçün cavabı yoxlamaq mümkün deyil."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Funksiyanı istifadə etmək üçün onun üzərinə toxunun:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Xüsusi imkanlar düyməsinin köməyilə işə salınacaq funksiyaları seçin"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Səs səviyyəsi düyməsinin qısayolu ilə istifadə edəcəyiniz funksiyaları seçin"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> deaktiv edilib"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Qısayolları redaktə edin"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hazırdır"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index a20775d..b83eca5 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacija krije zahtev za dozvolu, pa odgovor ne može da se verifikuje."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Dodirnite neku funkciju da biste počeli da je koristite:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Odaberite funkcije koje ćete koristiti sa dugmetom Pristupačnost"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Odaberite funkcije za prečicu tasterom jačine zvuka"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usluga <xliff:g id="SERVICE_NAME">%s</xliff:g> je isključena"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Izmenite prečice"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gotovo"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 871f8d4..59645706 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1748,7 +1748,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Праграма хавае запыт дазволу, таму ваш адказ немагчыма спраўдзіць."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Каб пачаць выкарыстоўваць функцыю, націсніце на яе:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Выберыце функцыі, якія будзеце выкарыстоўваць з кнопкай спецыяльных магчымасцей"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Выберыце функцыі для выкарыстання з клавішай гучнасці"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Сэрвіс \"<xliff:g id="SERVICE_NAME">%s</xliff:g>\" выключаны"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Змяніць ярлыкі"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Гатова"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index c22325c..b6fad9e 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Отговорът ви не може да бъде потвърден, тъй като приложение прикрива заявката за разрешение."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Докоснете дадена функция, за да започнете да я използвате:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Избиране на функции, които да използвате с бутона за достъпност"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Избиране на функции, които да използвате с прекия път чрез бутона за силата на звука"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Изключихте <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Редактиране на преките пътища"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 776714c..c434fe9 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"কোনও অ্যাপ অনুমতির অনুরোধ আড়াল করছে তাই আপনার উত্তর যাচাই করা যাবে না।"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"কোনও ফিচার ব্যবহার করা শুরু করতে, সেটিতে ট্যাপ করুন:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"অ্যাক্সেসিবিলিটি বোতামের সাহায্যে আপনি যেসব ফিচার ব্যবহার করতে চান সেগুলি বেছে নিন"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ভলিউম কী শর্টকাটের সাহায্যে আপনি যেসব ফিচার ব্যবহার করতে চান সেগুলি বেছে নিন"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> বন্ধ করে দেওয়া হয়েছে"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"শর্টকাট এডিট করুন"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"হয়ে গেছে"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 9306cfd..91c7701 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacija skriva zahtjev za odobrenje, pa se vaš odgovor ne može potvrditi."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Dodirnite funkciju da je počnete koristiti:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Odaberite funkcije koje ćete koristiti s dugmetom Pristupačnost"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Odaberite funkcije koje ćete koristiti pomoću prečice tipke za jačinu zvuka"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usluga <xliff:g id="SERVICE_NAME">%s</xliff:g> je isključena"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi prečice"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gotovo"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 80420dd..cbe9c39 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Una aplicació està ocultant la sol·licitud de permís, de manera que la teva resposta no es pot verificar"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toca una funció per començar a utilitzar-la:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Tria les funcions que vols utilitzar amb el botó d\'accessibilitat"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Tria les funcions que vols utilitzar amb la drecera per a tecles de volum"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> s\'ha desactivat"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edita les dreceres"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fet"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index bc5cdfe..b9ceede 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1748,7 +1748,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Žádost o oprávnění skrývá nějaká aplikace, proto vaši odpověď nelze ověřit."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Chcete-li některou funkci začít používat, klepněte na ni:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Vyberte funkce, které budete používat s tlačítkem přístupnosti"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Vyberte funkce, které budete používat se zkratkou tlačítka hlasitosti"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Služba <xliff:g id="SERVICE_NAME">%s</xliff:g> byla vypnuta"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Upravit zkratky"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hotovo"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 6cbe673..d66ebd9 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"En app skjuler anmodningen om tilladelse, så dit svar kan ikke verificeres."</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 til hjælpefunktioner"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Vælg de funktioner, du vil bruge via lydstyrkeknapperne"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <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>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Udfør"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index dece83f..3879767 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Die Berechtigungsanfrage wird durch eine andere App verdeckt. Daher kann deine Antwort nicht geprüft werden."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Zum Auswählen der gewünschten Funktion tippen:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Funktionen auswählen, die du mit der Schaltfläche \"Bedienungshilfen\" verwenden möchtest"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Funktionen für Verknüpfung mit Lautstärketaste auswählen"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> wurde deaktiviert"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kurzbefehle bearbeiten"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fertig"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index cc179a4..28a5e55 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Μια εφαρμογή αποκρύπτει το αίτημα άδειας, με αποτέλεσμα να μην είναι δυνατή η επαλήθευση της απάντησής σας."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Πατήστε μια λειτουργία για να ξεκινήσετε να τη χρησιμοποιείτε:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Επιλέξτε τις λειτουργίες που θέλετε να χρησιμοποιείτε με το κουμπί προσβασιμότητας."</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Επιλέξτε τις λειτουργίες που θέλετε να χρησιμοποιείτε με τη συντόμευση κουμπιού έντασης ήχου"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Η υπηρεσία <xliff:g id="SERVICE_NAME">%s</xliff:g> έχει απενεργοποιηθεί."</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Επεξεργασία συντομεύσεων"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Τέλος"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index caa52c4..70d86e7 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"An app is obscuring the permission request so your response cannot be verified."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tap a feature to start using it:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choose features to use with the Accessibility button"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choose features to use with the volume key shortcut"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> has been turned off"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Done"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 3850b00..19547f8 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"An app is obscuring the permission request so your response cannot be verified."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tap a feature to start using it:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choose features to use with the accessibility button"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choose features to use with the volume key shortcut"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> has been turned off"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Done"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index bf5c61c..d3f0c64 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"An app is obscuring the permission request so your response cannot be verified."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tap a feature to start using it:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choose features to use with the Accessibility button"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choose features to use with the volume key shortcut"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> has been turned off"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Done"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index e829fa3..7c3be15 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"An app is obscuring the permission request so your response cannot be verified."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tap a feature to start using it:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choose features to use with the Accessibility button"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choose features to use with the volume key shortcut"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> has been turned off"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Done"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 0b9be3b..c1eade1 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‏‎An app is obscuring the permission request so your response cannot be verified.‎‏‎‎‏‎"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‎‏‏‎‎‎‎Tap a feature to start using it:‎‏‎‎‏‎"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎Choose features to use with the accessibility button‎‏‎‎‏‎"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‎‏‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎Choose features to use with the volume key shortcut‎‏‎‎‏‎"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎‎‏‏‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%s</xliff:g>‎‏‎‎‏‏‏‎ has been turned off‎‏‎‎‏‎"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‎‏‏‏‎Edit shortcuts‎‏‎‎‏‎"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‎‎Done‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 3814944..773edd3 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Una app está cubriendo la solicitud de permiso, por lo que no se puede verificar tu respuesta."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Presiona una función para comenzar a usarla:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Selecciona las funciones a utilizar con el botón de accesibilidad"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Selecciona las funciones a usar con las teclas de volumen"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Se desactivó <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar accesos directos"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Listo"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 215cf39..ff7d912 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Una aplicación está ocultando la solicitud de permiso, por lo que no se puede verificar tu respuesta."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toca una función para empezar a usarla:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Selecciona qué funciones usar con el botón de accesibilidad"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Selecciona qué funciones usar con la tecla de volumen"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Se ha desactivado <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar accesos directos"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hecho"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 4694efa..f313fb2 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Rakendus varjab loataotlust, nii et teie vastust ei saa kinnitada."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Puudutage funktsiooni, et selle kasutamist alustada."</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Valige funktsioonid, mida juurdepääsetavuse nupuga kasutada"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Valige helitugevuse nupu otsetee funktsioonid"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> on välja lülitatud"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Muuda otseteid"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Valmis"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 2cae18a..b0775d0 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -252,7 +252,7 @@
     <string name="shutdown_confirm_question" msgid="796151167261608447">"Itzali egin nahi duzu?"</string>
     <string name="reboot_safemode_title" msgid="5853949122655346734">"Berrabiarazi modu seguruan"</string>
     <string name="reboot_safemode_confirm" msgid="1658357874737219624">"Modu seguruan berrabiarazi nahi duzu? Instalatutako hirugarrenen aplikazioak desgaituko dira. Berriro berrabiarazi ondoren leheneratuko dira."</string>
-    <string name="recent_tasks_title" msgid="8183172372995396653">"Azkenak"</string>
+    <string name="recent_tasks_title" msgid="8183172372995396653">"Azkenaldikoak"</string>
     <string name="no_recent_tasks" msgid="9063946524312275906">"Ez dago azkenaldian erabilitako aplikaziorik."</string>
     <string name="global_actions" product="tablet" msgid="4412132498517933867">"Tabletaren aukerak"</string>
     <string name="global_actions" product="tv" msgid="3871763739487450369">"Android TV gailuaren aukerak"</string>
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikazio bat baimen-eskaera oztopatzen ari da eta, ondorioz, ezin da egiaztatu erantzuna."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Eginbide bat erabiltzen hasteko, saka ezazu:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Aukeratu zein eginbide erabili nahi duzun Erabilerraztasuna botoiarekin"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Aukeratu zein eginbide erabili nahi duzun bolumen-botoien lasterbidearekin"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Desaktibatu da <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editatu lasterbideak"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Eginda"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 54a3b32..5e474cd 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"پاسخ شما تأیید نشد زیرا یک برنامه درخواست اجازه را مسدود کرده است."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"برای استفاده از ویژگی، روی آن تک‌ضرب بزنید:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"انتخاب ویژگی‌های موردنظر برای استفاده با دکمه دسترس‌پذیری"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"انتخاب ویژگی‌های موردنظر برای استفاده با میان‌بر کلید میزان صدا"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> خاموش شده است"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ویرایش میان‌برها"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"تمام"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 1b2ddb0..dec5b64 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Sovellus peittää lupapyynnön, joten vastaustasi ei voi vahvistaa."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Aloita ominaisuuden käyttö napauttamalla sitä:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Valitse ominaisuudet, joita käytetään esteettömyyspainikkeella"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Valitse ominaisuudet, joita käytetään äänenvoimakkuuspikanäppäimellä"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> on laitettu pois päältä"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Muokkaa pikakuvakkeita"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Valmis"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index d3ebe5a..7cb9e06 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Une appli masque la demande d\'autorisation de sorte que votre réponse ne peut pas être vérifiée."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toucher une fonctionnalité pour commencer à l\'utiliser :"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choisir les fonctionnalités à utiliser à l\'aide du bouton d\'accessibilité"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choisir les fonctionnalités à utiliser avec le raccourci des touches de volume"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> a été désactivé"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifier les raccourcis"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index d617143..ca3998c 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Une application masque la demande d\'autorisation. Votre réponse ne peut donc pas être vérifiée."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Appuyez sur une fonctionnalité pour commencer à l\'utiliser :"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choisir les fonctionnalités à utiliser avec le bouton Accessibilité"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choisir les fonctionnalités à utiliser avec le raccourci des touches de volume"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Le service <xliff:g id="SERVICE_NAME">%s</xliff:g> a été désactivé"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifier les raccourcis"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 9366f4e..e07218c 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Hai unha aplicación que está ocultando a solicitude de permiso, polo que non se pode verificar a túa resposta."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tocar unha función para comezar a utilizala:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escoller as funcións que queres utilizar co botón Accesibilidade"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Escolle as funcións que queres utilizar co atallo da tecla de volume"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g>: desactivouse"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atallos"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Feito"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 6df63d6..2810b5e 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -266,7 +266,7 @@
     <string name="global_action_logout" msgid="6093581310002476511">"સત્ર સમાપ્ત કરો"</string>
     <string name="global_action_screenshot" msgid="2610053466156478564">"સ્ક્રીનશૉટ"</string>
     <string name="bugreport_title" msgid="8549990811777373050">"બગ રિપોર્ટ"</string>
-    <string name="bugreport_message" msgid="5212529146119624326">"આ, એક ઇ-મેઇલ સંદેશ તરીકે મોકલવા માટે, તમારા વર્તમાન ઉપકરણ સ્થિતિ વિશેની માહિતી એકત્રિત કરશે. એક બગ રિપોર્ટ પ્રારંભ કરીને તે મોકલવા માટે તૈયાર ન થઈ જાય ત્યાં સુધી તેમાં થોડો સમય લાગશે; કૃપા કરીને ધીરજ રાખો."</string>
+    <string name="bugreport_message" msgid="5212529146119624326">"આ, એક ઇ-મેઇલ મેસેજ તરીકે મોકલવા માટે, તમારા વર્તમાન ડિવાઇસના સ્ટેટસ વિશે માહિતી એકત્રિત કરશે. એક બગ રિપોર્ટના શરુ થવાથી લઈને મોકલવા માટે તૈયાર થવા સુધીની પ્રક્રિયામાં થોડો સમય લાગશે; કૃપા કરીને ધીરજ રાખો."</string>
     <string name="bugreport_option_interactive_title" msgid="7968287837902871289">"ક્રિયાપ્રતિક્રિયાત્મક રિપોર્ટ"</string>
     <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"મોટાભાગના સંજોગોમાં આનો ઉપયોગ કરો. તે રિપોર્ટની પ્રગતિને ટ્રૅક કરવા, સમસ્યા વિશે વધુ વિગતો દાખલ કરવાની અને સ્ક્રીનશૉટ્સ લેવાની મંજૂરી આપે છે. તે કેટલાક ઓછા ઉપયોગમાં આવતાં વિભાગો કે જે જાણ કરવામાં વધુ સમય લેતાં હોય તેને છોડી દઈ શકે છે."</string>
     <string name="bugreport_option_full_title" msgid="7681035745950045690">"પૂર્ણ રિપોર્ટ"</string>
@@ -324,7 +324,7 @@
     <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>
+    <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS મેસેજ મોકલો અને જુઓ"</string>
     <string name="permgrouplab_storage" msgid="17339216290379241">"ફાઇલો"</string>
     <string name="permgroupdesc_storage" msgid="5378659041354582769">"તમારા ડિવાઇસ પરની ફાઇલો ઍક્સેસ કરો"</string>
     <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"મ્યુઝિક અને ઑડિયો"</string>
@@ -1363,7 +1363,7 @@
     <string name="sms_control_message" msgid="6574313876316388239">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; મોટા પ્રમાણમાં SMS મેસેજ મોકલી રહ્યું છે. શું તમે મેસેજ મોકલવાનું ચાલુ રાખવા માટે આ એપને મંજૂરી આપવા માગો છો?"</string>
     <string name="sms_control_yes" msgid="4858845109269524622">"મંજૂરી આપો"</string>
     <string name="sms_control_no" msgid="4845717880040355570">"નકારો"</string>
-    <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; તમને &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; પર સંદેશ મોકલવા માગે છે."</string>
+    <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;, &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; પર મેસેજ મોકલવા માગે છે."</string>
     <string name="sms_short_code_details" msgid="2723725738333388351">"આનાથી તમારા મોબાઇલ એકાઉન્ટ પર "<b>"શુલ્ક લાગી શકે છે"</b>"."</string>
     <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"આનાથી તમારા મોબાઇલ એકાઉન્ટ પર શુલ્ક લાગશે."</b></string>
     <string name="sms_short_code_confirm_allow" msgid="920477594325526691">"મોકલો"</string>
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"કોઈ ઍપ પરવાનગીની વિનંતીને ઢાંકી રહી છે, તેથી તમારા પ્રતિસાદની ચકાસણી કરી શકાતી નથી."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"સુવિધાનો ઉપયોગ શરૂ કરવા તેના પર ટૅપ કરો:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ઍક્સેસિબિલિટી બટન વડે તમે ઉપયોગમાં લેવા માગો છો તે સુવિધાઓ પસંદ કરો"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"વૉલ્યૂમ કી શૉર્ટકટ વડે તમે ઉપયોગમાં લેવા માગો છો તે સુવિધાઓ પસંદ કરો"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> બંધ કરવામાં આવ્યું છે"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"શૉર્ટકટમાં ફેરફાર કરો"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"થઈ ગયું"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 02369f9..700e91a 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ऐप्लिकेशन की वजह से, अनुमति का अनुरोध समझने में परेशानी हो रही है. इसलिए, आपके जवाब की पुष्टि नहीं की जा सकी."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"किसी सुविधा का इस्तेमाल करने के लिए, उस पर टैप करें:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"सुलभता बटन पर टैप करके, इस्तेमाल करने के लिए सुविधाएं चुनें"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"चुनें कि आवाज़ कम या ज़्यादा करने वाले बटन के शॉर्टकट से आप किन सुविधाओं का इस्तेमाल करना चाहते हैं"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> को बंद कर दिया गया है"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"शॉर्टकट में बदलाव करें"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"हो गया"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 487d9e7..2596de2 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacija prekriva upit za dopuštenje pa se vaš odgovor ne može potvrditi."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Dodirnite značajku da biste je počeli koristiti:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Odabir značajki za upotrebu pomoću gumba za Pristupačnost"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Odabir značajki za upotrebu pomoću prečaca tipki za glasnoću"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usluga <xliff:g id="SERVICE_NAME">%s</xliff:g> je isključena"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredite prečace"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gotovo"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index ca8787d..09af506 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Az egyik alkalmazás eltakarja az engedélykérelmet, így az Ön válasza nem ellenőrizhető."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Koppintson valamelyik funkcióra a használatához:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Kiválaszthatja a Kisegítő lehetőségek gombbal használni kívánt funkciókat"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Kiválaszthatja a hangerőgombbal használni kívánt funkciókat"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kikapcsolva"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Gyorsparancsszerkesztés"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Kész"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 273e7745..a28f413 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Հավելվածը թաքցնում է թույլտվության հայտը, ուստի ձեր պատասխանը հնարավոր չէ ստուգել։"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Ընտրեք՝ որ գործառույթն օգտագործել"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Ընտրեք գործառույթները, որոնք կբացվեն «Հատուկ գործառույթներ» կոճակի միջոցով"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Ընտրեք գործառույթները, որոնք կբացվեն ձայնի կարգավորման կոճակի միջոցով"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ծառայությունն անջատված է"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Փոփոխել դյուրանցումները"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Պատրաստ է"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 47588ff..76c89ea 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikasi menghalangi permintaan izin sehingga respons Anda tidak dapat diverifikasi."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Ketuk fitur untuk mulai menggunakannya:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Pilih fitur yang akan digunakan dengan tombol aksesibilitas"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Pilih fitur yang akan digunakan dengan pintasan tombol volume"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> telah dinonaktifkan"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit pintasan"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Selesai"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index a833c8d..3eb2e4b 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Forrit er að fela heimildarbeiðnina svo ekki er hægt að staðfesta svarið þitt."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Ýttu á eiginleika til að byrja að nota hann:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Veldu eiginleika sem á að nota með aðgengishnappinum"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Veldu eiginleika sem á að nota með flýtileið hljóðstyrkstakka"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Slökkt hefur verið á <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Breyta flýtileiðum"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Lokið"</string>
diff --git a/core/res/res/values-it-feminine/strings.xml b/core/res/res/values-it-feminine/strings.xml
index 141b467..1a69a63 100644
--- a/core/res/res/values-it-feminine/strings.xml
+++ b/core/res/res/values-it-feminine/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="relationTypeFriend" msgid="3192092625893980574">"Amica"</string>
     <string name="relationTypeSpouse" msgid="6916682664436031703">"Moglie"</string>
 </resources>
diff --git a/core/res/res/values-it-masculine/strings.xml b/core/res/res/values-it-masculine/strings.xml
index 7310eb8..86c4408 100644
--- a/core/res/res/values-it-masculine/strings.xml
+++ b/core/res/res/values-it-masculine/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="relationTypeFriend" msgid="3192092625893980574">"Amico"</string>
     <string name="relationTypeSpouse" msgid="6916682664436031703">"Marito"</string>
 </resources>
diff --git a/core/res/res/values-it-neuter/strings.xml b/core/res/res/values-it-neuter/strings.xml
index ce433d7..7c33e91 100644
--- a/core/res/res/values-it-neuter/strings.xml
+++ b/core/res/res/values-it-neuter/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="relationTypeFriend" msgid="3192092625893980574">"Amicə"</string>
     <string name="relationTypeSpouse" msgid="6916682664436031703">"Coniuge"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 662a9c0..29533d5 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -969,7 +969,7 @@
     <string name="relationTypeChild" msgid="9076258911292693601">"Figlio"</string>
     <string name="relationTypeDomesticPartner" msgid="7825306887697559238">"Convivente"</string>
     <string name="relationTypeFather" msgid="3856225062864790596">"Padre"</string>
-    <string name="relationTypeFriend" msgid="3192092625893980574">"Persona amica"</string>
+    <string name="relationTypeFriend" msgid="3192092625893980574">"Amico"</string>
     <string name="relationTypeManager" msgid="2272860813153171857">"Dirigente"</string>
     <string name="relationTypeMother" msgid="2331762740982699460">"Madre"</string>
     <string name="relationTypeParent" msgid="4177920938333039882">"Genitore"</string>
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Un\'app nasconde la tua richiesta di autorizzazione, per cui non abbiamo potuto verificare la tua risposta."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tocca una funzionalità per iniziare a usarla:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Scegli le funzionalità da usare con il pulsante Accessibilità"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Scegli le funzionalità da usare con la scorciatoia dei tasti del volume"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Il servizio <xliff:g id="SERVICE_NAME">%s</xliff:g> è stato disattivato"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifica scorciatoie"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fine"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 37bffa4..52b6173 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"אפליקציה מסתירה את בקשת ההרשאה כך שלא ניתן לאמת את התשובה שלך."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"יש להקיש על תכונה כדי להתחיל להשתמש בה:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"בחירת תכונה לשימוש עם לחצן הנגישות"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"בחירת תכונות לשימוש עם מקש הקיצור לעוצמת הקול"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"שירות <xliff:g id="SERVICE_NAME">%s</xliff:g> כבוי"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"עריכת קיצורי הדרך"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"סיום"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index cce4abe..bcff813 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"権限のリクエストを遮っているアプリがあるため、同意の回答を確認できません。"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"使用を開始する機能をタップ:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ユーザー補助機能ボタンで使用する機能の選択"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"音量ボタンのショートカットで使用する機能の選択"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> はオフになっています"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ショートカットの編集"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完了"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 0d8b047..0adebb0 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"აპი მალავს ნებართვის მოთხოვნას, ასე რომ, თქვენი პასუხი ვერ დადასტურდება."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"შეეხეთ ფუნქციას მისი გამოყენების დასაწყებად:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"აირჩიეთ ფუნქციები, რომელთა გამოყენებაც გსურთ მარტივი წვდომის ღილაკით"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"აირჩიეთ ფუნქციები, რომელთა გამოყენებაც გსურთ ხმის ღილაკის მალსახმობით"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> გამორთულია"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"მალსახმობების რედაქტირება"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"მზადაა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 72a2a3b..d9ee240 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Қолданба рұқсат сұрауын жасырып тұрғандықтан, жауабыңыз расталмайды."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Функцияны пайдалана бастау үшін түртіңіз:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"\"Арнайы мүмкіндіктер\" түймесімен қолданылатын функцияларды таңдаңыз"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Дыбыс деңгейі пернелері тіркесімімен қолданылатын функцияларды таңдаңыз"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> қызметі өшірулі."</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Жылдам пәрмендерді өзгерту"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Дайын"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 2e5589e..f3dd775 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"កម្មវិធីមួយកំពុងបិទបាំងសំណើសុំការអនុញ្ញាត ដូច្នេះមិនអាចផ្ទៀងផ្ទាត់ការឆ្លើយតបរបស់អ្នកបានទេ។"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ចុចមុខងារណាមួយ ដើម្បចាប់ផ្ដើមប្រើ៖"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ជ្រើសរើស​មុខងារ ដើម្បីប្រើ​ជាមួយ​ប៊ូតុង​ភាពងាយស្រួល"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ជ្រើសរើស​មុខងារ ដើម្បីប្រើ​ជាមួយផ្លូវកាត់គ្រាប់ចុច​កម្រិតសំឡេង"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"បានបិទ <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"កែ​ផ្លូវកាត់"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"រួចរាល់"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index e5a5092..a772e32 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1403,7 +1403,7 @@
     <string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB ಪರಿಕರವನ್ನು ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
     <string name="usb_notification_message" msgid="4715163067192110676">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="usb_power_notification_message" msgid="7284765627437897702">"ಸಂಪರ್ಕಗೊಂಡಿರುವ ಸಾಧನವನ್ನು ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ. ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
-    <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"ಅನ್‌ಲಾಗ್ ಆಡಿಯೋ ಪರಿಕರ ಪತ್ತೆಯಾಗಿದೆ"</string>
+    <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"ಅನ್‌ಲಾಗ್ ಆಡಿಯೋ ಆ್ಯಕ್ಸೆಸರಿ ಪತ್ತೆಯಾಗಿದೆ"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"ಲಗತ್ತಿಸಲಾದ ಸಾಧನವು ಈ ಫೋನಿನೊಂದಿಗೆ ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ. ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="adb_active_notification_title" msgid="408390247354560331">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆ ಕನೆಕ್ಟ್‌ ಆಗಿದೆ"</string>
     <string name="adb_active_notification_message" msgid="5617264033476778211">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆ ಆಫ್‌ ಮಾಡಲು ಟ್ಯಾಪ್‌ ಮಾಡಿ"</string>
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ಆ್ಯಪ್‌ವೊಂದು ಅನುಮತಿ ವಿನಂತಿಯನ್ನು ಮರೆಮಾಚುತ್ತಿರುವ ಕಾರಣ ನಿಮ್ಮ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ವೈಶಿಷ್ಟ್ದ ಬಳಸುವುದನ್ನು ಪ್ರಾರಂಭಿಸಲು ಅದನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ಬಟನ್ ಜೊತೆಗೆ ಬಳಸಲು ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ವಾಲ್ಯೂಮ್ ಕೀ ಶಾರ್ಟ್‌ಕಟ್ ಜೊತೆಗೆ ಬಳಸಲು ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ಅನ್ನು ಆಫ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ಶಾರ್ಟ್‌ಕಟ್‌‍ಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
@@ -2152,7 +2153,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="1388718452788985481">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯನ್ನು ವಿಸ್ತರಿಸಲು ಬ್ಯಾಟರಿ ಬಳಕೆಯನ್ನು ಕಡಿಮೆ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 1413170..0e47e59 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"앱에서 권한 요청을 가려서 응답을 확인할 수 없습니다."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"기능을 사용하려면 탭하세요"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"접근성 버튼으로 사용할 기능 선택"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"볼륨 키 단축키로 사용할 기능 선택"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g>이(가) 사용 중지됨"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"단축키 수정"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"완료"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 112bf0a..4c2ee5f 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Колдонмо уруксат суроону жашырып койгондуктан, жообуңузду ырастоо мүмкүн эмес."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Функцияны колдонуп баштоо үчүн аны таптап коюңуз:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Атайын мүмкүнчүлүктөр баскычы менен колдонгуңуз келген функцияларды тандаңыз"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Үндү катуулатуу/акырындатуу баскычтары менен кайсы функцияларды иштеткиңиз келет?"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> өчүрүлдү"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Кыска жолдорду түзөтүү"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Бүттү"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index ba43481..b627503 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ແອັບໜຶ່ງກຳລັງປິດບັງຄຳຮ້ອງຂໍການອະນຸຍາດ ດັ່ງນັ້ນຈຶ່ງບໍ່ສາມາດຢັ້ງຢືນຄຳຕອບຂອງທ່ານໄດ້."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ແຕະໃສ່ຄຸນສົມບັດໃດໜຶ່ງເພື່ອເລີ່ມການນຳໃຊ້ມັນ:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ເລືອກຄຸນສົມບັດເພື່ອໃຊ້ກັບປຸ່ມການຊ່ວຍເຂົ້າເຖິງ"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ເລືອກຄຸນສົມບັດເພື່ອໃຊ້ກັບທາງລັດປຸ່ມລະດັບສຽງ"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"ປິດ <xliff:g id="SERVICE_NAME">%s</xliff:g> ໄວ້ແລ້ວ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ແກ້ໄຂທາງລັດ"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ແລ້ວໆ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index ad30d80..8eace89 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1748,7 +1748,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Programa užstoja leidimo užklausą, todėl negalima patvirtinti jūsų atsakymo."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Norėdami naudoti funkciją, palieskite ją:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Funkcijų, kurioms bus naudojamas pritaikomumo mygtukas, pasirinkimas"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Funkcijų, kurioms bus naudojamas garsumo spartusis klavišas, pasirinkimas"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Paslauga „<xliff:g id="SERVICE_NAME">%s</xliff:g>“ išjungta"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redaguoti sparčiuosius klavišus"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Atlikta"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 329bbc3..01fb9da 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Kāda lietotne padara atļaujas pieprasījumu nesaprotamu, tāpēc nevar verificēt jūsu atbildi."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Pieskarieties funkcijai, lai sāktu to izmantot"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Izvēlieties funkcijas, ko izmantot ar pieejamības pogu"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Izvēlieties funkcijas, ko izmantot ar skaļuma pogu saīsni"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Pakalpojums <xliff:g id="SERVICE_NAME">%s</xliff:g> ir izslēgts."</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Rediģēt īsinājumtaustiņus"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gatavs"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 4bb0340..dbc4b75 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Апликација го прикрива барањето за дозвола, па вашиот одговор не може да се потврди."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Допрете на функција за да почнете да ја користите:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Изберете ги функциите што ќе ги користите со копчето за пристапност"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Изберете ги функциите што ќе ги користите со кратенката за копчето за јачина на звук"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> е исклучена"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Изменете ги кратенките"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 72e522d..2b1c52f 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ഒരു ആപ്പ്, അനുമതി അഭ്യർത്ഥന മറയ്‌ക്കുന്നതിനാൽ നിങ്ങളുടെ പ്രതികരണം പരിശോധിച്ചുറപ്പിക്കാനാകില്ല."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ഉപയോഗിച്ച് തുടങ്ങാൻ ഫീച്ചർ ടാപ്പ് ചെയ്യുക:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ഉപയോഗസഹായി ബട്ടണിന്റെ സഹായത്തോടെ, ഉപയോഗിക്കാൻ ഫീച്ചറുകൾ തിരഞ്ഞെടുക്കുക"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"വോളിയം കീ കുറുക്കുവഴിയിലൂടെ ഉപയോഗിക്കാൻ ഫീച്ചറുകൾ തിരഞ്ഞെടുക്കുക"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ഓഫാക്കിയിരിക്കുന്നു"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"കുറുക്കുവഴികൾ തിരുത്തുക"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"പൂർത്തിയാക്കി"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 4398975..bf2f78c 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Апп зөвшөөрлийн хүсэлтийг хааж байгаа тул таны хариултыг баталгаажуулах боломжгүй."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Үүнийг ашиглаж эхлэхийн тулд онцлог дээр товшино уу:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Хандалтын товчлуурын тусламжтай ашиглах онцлогуудыг сонгоно уу"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Дууны түвшний түлхүүрийн товчлолын тусламжтай ашиглах онцлогуудыг сонгоно уу"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g>-г унтраалаа"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Товчлолуудыг засах"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Болсон"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index ac39d55..67c3b98 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"परवानगी मागणारी विनंती अ‍ॅपमुळे अस्पष्‍ट होत असल्‍याने, तुमच्या प्रतिसादाची पडताळणी केली जाऊ शकत नाही."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"वैशिष्ट्य वापरणे सुरू करण्यासाठी त्यावर टॅप करा:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"अ‍ॅक्सेसिबिलिटी बटणासोबत वापरायची असलेली ॲप्स निवडा"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"व्‍हॉल्‍यूम की शॉर्टकटसोबत वापरायची असलेली ॲप्स निवडा"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> बंद केले आहे"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"शॉर्टकट संपादित करा"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"पूर्ण झाले"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 88eef46..5eac793 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Apl menghalang permintaan kebenaran, maka jawapan anda tidak dapat disahkan."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Ketik ciri untuk mula menggunakan ciri itu:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Pilih ciri untuk digunakan dengan butang kebolehaksesan"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Pilih ciri untuk digunakan dengan pintasan kekunci kelantangan"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> telah dimatikan"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit pintasan"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Selesai"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index d5c1fbd..b09539c 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"အက်ပ်တစ်ခုသည် ခွင့်ပြုချက်တောင်းဆိုမှုကို ပိတ်နေသဖြင့် သင့်တုံ့ပြန်မှုကို စိစစ်၍မရပါ။"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ဝန်ဆောင်မှုကို စတင်အသုံးပြုရန် တို့ပါ−"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"အများသုံးနိုင်မှု ခလုတ်ဖြင့် အသုံးပြုရန် ဝန်ဆောင်မှုများကို ရွေးပါ"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"အသံခလုတ် ဖြတ်လမ်းလင့်ခ်ဖြင့် အသုံးပြုရန် ဝန်ဆောင်မှုများကို ရွေးပါ"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ကို ပိတ်ထားသည်"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ဖြတ်လမ်းများကို တည်းဖြတ်ရန်"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ပြီးပြီ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 53b6ad5..8feb6e9 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"En app dekker forespørselen om tillatelse, så svaret ditt kan ikke bekreftes."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Trykk på en funksjon for å begynne å bruke den:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Velg funksjonene du vil bruke med Tilgjengelighet-knappen"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Velg funksjonene du vil bruke med volumtastsnarveien"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> er slått av"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Endre snarveier"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Ferdig"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 2a23e87..9f3530a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1097,7 +1097,7 @@
     <string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"यस पृष्ठलाई छोड्नुहोस्"</string>
     <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="autofill_window_title" msgid="4379134104008111961">"<xliff:g id="SERVICENAME">%1$s</xliff:g> मार्फत स्वतः भरण गर्नुहोस्‌"</string>
+    <string name="autofill_window_title" msgid="4379134104008111961">"<xliff:g id="SERVICENAME">%1$s</xliff:g> मार्फत अटोफिल गर्नुहोस्‌"</string>
     <string name="permlab_setAlarm" msgid="1158001610254173567">"एउटा आलर्म सेट गर्नुहोस्"</string>
     <string name="permdesc_setAlarm" msgid="2185033720060109640">"स्थापना गरिएको सङ्केत घडी एपमा सङ्केत समय मिलाउन एपलाई अनुमति दिन्छ। केही सङ्केत घडी एपहरूले यो सुविधा कार्यान्वयन नगर्न सक्छन्।"</string>
     <string name="permlab_addVoicemail" msgid="4770245808840814471">"भ्वाइसमेल थप गर्नुहोस्"</string>
@@ -1184,7 +1184,7 @@
     <string name="selectTextMode" msgid="3225108910999318778">"पाठ चयन गर्नुहोस्"</string>
     <string name="undo" msgid="3175318090002654673">"अन्डू गर्नुहोस्"</string>
     <string name="redo" msgid="7231448494008532233">"रिडू गर्नुहोस्"</string>
-    <string name="autofill" msgid="511224882647795296">"स्वतः भरण"</string>
+    <string name="autofill" msgid="511224882647795296">"अटोफिल"</string>
     <string name="textSelectionCABTitle" msgid="5151441579532476940">"पाठ चयनता"</string>
     <string name="addToDictionary" msgid="8041821113480950096">"शब्दकोशमा थप्नुहोस्"</string>
     <string name="deleteText" msgid="4200807474529938112">"मेट्नुहोस्"</string>
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"कुनै एपका कारण अनुमतिसम्बन्धी अनुरोध बुझ्न कठिनाइ भइरहेकाले तपाईंको जवाफको पुष्टि गर्न सकिएन।"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"कुनै सुविधा प्रयोग गर्न थाल्न उक्त सुविधामा ट्याप गर्नुहोस्:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"पहुँचको बटनमार्फत प्रयोग गर्न चाहेका सुविधाहरू छनौट गर्नुहोस्"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"भोल्युम कुञ्जीको सर्टकटमार्फत प्रयोग गर्न चाहेका सुविधाहरू छनौट गर्नुहोस्"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> निष्क्रिय पारिएको छ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"सर्टकटहरू सम्पादन गर्नुहोस्"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"सम्पन्न भयो"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5593f41..8209504 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Een app dekt het verzoek om rechten af, waardoor je reactie niet kan worden geverifieerd."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tik op een functie om deze te gebruiken:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Functies kiezen voor gebruik met de knop Toegankelijkheid"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Functies kiezen voor gebruik met de sneltoets via de volumeknop"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> is uitgezet"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Snelkoppelingen bewerken"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klaar"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index f9e9374..45b6e9a 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ଏକ ଆପ ଅନୁମତି ଅନୁରୋଧକୁ ଅସ୍ପଷ୍ଟ କରୁଛି ତେଣୁ ଆପଣଙ୍କ ଉତ୍ତରକୁ ଯାଞ୍ଚ କରାଯାଇପାରିବ ନାହିଁ।"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ଏକ ଫିଚର୍ ବ୍ୟବହାର କରିବା ଆରମ୍ଭ କରିବାକୁ ଏହାକୁ ଟାପ୍ କରନ୍ତୁ:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ଆକ୍ସେସିବିଲିଟୀ ବଟନ୍ ସହିତ ବ୍ୟବହାର କରିବାକୁ ଫିଚରଗୁଡ଼ିକ ବାଛନ୍ତୁ"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ଭଲ୍ୟୁମ୍ କୀ ସର୍ଟକଟ୍ ସହିତ ବ୍ୟବହାର କରିବାକୁ ଫିଚରଗୁଡ଼ିକ ବାଛନ୍ତୁ"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ବନ୍ଦ ହୋଇଯାଇଛି"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ସର୍ଟକଟଗୁଡ଼ିକୁ ଏଡିଟ କରନ୍ତୁ"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ହୋଇଗଲା"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index e309832..c6d0b9f 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ਕੋਈ ਐਪ ਇਜਾਜ਼ਤ ਸੰਬੰਧੀ ਬੇਨਤੀ ਨੂੰ ਅਸਪਸ਼ਟ ਕਰ ਰਹੀ ਹੈ, ਇਸ ਲਈ ਤੁਹਾਡੇ ਜਵਾਬ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ਕਿਸੇ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਵਰਤਣਾ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਉਸ \'ਤੇ ਟੈਪ ਕਰੋ:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਨਾਲ ਵਰਤਣ ਲਈ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚੁਣੋ"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ਅਵਾਜ਼ ਕੁੰਜੀ ਸ਼ਾਰਟਕੱਟ ਨਾਲ ਵਰਤਣ ਲਈ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚੁਣੋ"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ਨੂੰ ਬੰਦ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ਸ਼ਾਰਟਕੱਟਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ਹੋ ਗਿਆ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index b6f70d6..0ae3bbf 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1748,7 +1748,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacja zasłania prośbę o uprawnienia, więc nie można zweryfikować Twojej odpowiedzi."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Wybierz funkcję, aby zacząć z niej korzystać:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Wybierz funkcje, których chcesz używać z przyciskiem ułatwień dostępu"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Wybierz funkcje, do których chcesz używać skrótu z klawiszami głośności"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usługa <xliff:g id="SERVICE_NAME">%s</xliff:g> została wyłączona"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edytuj skróty"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index d5035e0..e025d19 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Um app está ocultando a solicitação de permissão e impedindo a verificação da sua resposta."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toque em um recurso para começar a usá-lo:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escolha recursos para usar com o botão de acessibilidade"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Escolha recursos para usar com o atalho da tecla de volume"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"O <xliff:g id="SERVICE_NAME">%s</xliff:g> foi desativado"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index a9ba018..71940ef 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Uma app está a ocultar o pedido de autorização e, por isso, não é possível validar a sua resposta."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toque numa funcionalidade para começar a utilizá-la:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escolha funcionalidades para utilizar com o botão Acessibilidade"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Escolha funcionalidades para usar com o atalho das teclas de volume"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"O serviço <xliff:g id="SERVICE_NAME">%s</xliff:g> foi desativado."</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index d5035e0..e025d19 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Um app está ocultando a solicitação de permissão e impedindo a verificação da sua resposta."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toque em um recurso para começar a usá-lo:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escolha recursos para usar com o botão de acessibilidade"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Escolha recursos para usar com o atalho da tecla de volume"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"O <xliff:g id="SERVICE_NAME">%s</xliff:g> foi desativado"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 444dbd4..7e5e7c0 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"O aplicație blochează solicitarea de permisiune, așa că răspunsul nu se poate verifica."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Atinge o funcție ca să începi să o folosești:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Alege funcțiile pe care să le folosești cu butonul de accesibilitate"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Alege funcțiile pentru comanda rapidă a butonului de volum"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> a fost dezactivat"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editează comenzile rapide"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gata"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 46e7b9d..22501f2 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1748,7 +1748,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Невозможно принять ваш ответ, поскольку запрос разрешения скрыт другим приложением."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Выберите, какую функцию использовать:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Выберите функции, которые будут запускаться с помощью кнопки специальных возможностей"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Выберите функции, которые будут запускаться с помощью кнопки регулировки громкости"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Сервис \"<xliff:g id="SERVICE_NAME">%s</xliff:g>\" отключен."</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Изменить ярлыки"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index fb03569..af835d9 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"යෙදුමක් අවසර ඉල්ලීම අඳුරු කරන බැවින්, ඔබේ ප්‍රතිචාරය සත්‍යාපනය කළ නොහැක."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"එය භාවිත කිරීම ආරම්භ කිරීමට විශේෂාංගයක් තට්ටු කරන්න:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ප්‍රවේශ්‍යතා බොත්තම සමග භාවිත කිරීමට විශේෂාංග තෝරා ගන්න"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"හඬ පරිමා යතුරු කෙටිමග සමග භාවිත කිරීමට විශේෂාංග තෝරා ගන්න"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ක්‍රියාවිරහිත කර ඇත"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"කෙටිමං සංස්කරණ කරන්න"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"නිමයි"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index bde470e..3289bbc 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1748,7 +1748,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikácia zakrýva žiadosť o povolenie, takže vaša odpoveď sa nedá overiť."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Klepnutím na funkciu ju začnite používať:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Výber funkcií, ktoré chcete používať tlačidlom dostupnosti"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Výber funkcií, ktoré chcete používať klávesovou skratkou"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Služba <xliff:g id="SERVICE_NAME">%s</xliff:g> bola vypnutá"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Upraviť skratky"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hotovo"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index b70322b..99ce046 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1748,7 +1748,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacija zakriva zahtevo za dovoljenje, zato ni mogoče potrditi vašega odgovora."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Če želite začeti uporabljati funkcijo, se je dotaknite:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Izberite funkcije, ki jih želite uporabljati z gumbom za dostopnost"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Izberite funkcije, ki jih želite uporabljati z bližnjico na tipki za glasnost"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Storitev <xliff:g id="SERVICE_NAME">%s</xliff:g> je izklopljena"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi bližnjice"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Končano"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 3040597..d8fe109 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Një aplikacion po fsheh kërkesën për leje, prandaj përgjigja jote nuk mund të verifikohet."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Trokit te një veçori për të filluar ta përdorësh atë:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Zgjidh veçoritë që do të përdorësh me butonin e qasshmërisë"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Zgjidh veçoritë që do të përdorësh me shkurtoren e tastit të volumit"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> është çaktivizuar"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redakto shkurtoret"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"U krye"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index f8e5a79..0451b56 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1747,7 +1747,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Апликација крије захтев за дозволу, па одговор не може да се верификује."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Додирните неку функцију да бисте почели да је користите:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Одаберите функције које ћете користити са дугметом Приступачност"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Одаберите функције за пречицу тастером јачине звука"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Услуга <xliff:g id="SERVICE_NAME">%s</xliff:g> је искључена"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Измените пречице"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 8e08c6b..9bde6af 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"En app döljer behörighetsbegäran så det går inte att verifiera svaret."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tryck på funktioner som du vill aktivera:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Välj vilka funktioner du vill använda med hjälp av tillgänglighetsknappen"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Välj att funktioner att använda med hjälp av volymknappskortkommandot"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> har inaktiverats"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redigera genvägar"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klar"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index a9385c1..c286eeb 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Programu inazuia ombi la ruhusa kwa hivyo jibu lako haliwezi kuthibitishwa."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Gusa kipengele ili uanze kukitumia:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Chagua vipengele vya kutumia na kitufe cha zana za ufikivu"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Chagua vipengele vya kutumia na njia ya mkato ya kitufe cha sauti"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Huduma ya <xliff:g id="SERVICE_NAME">%s</xliff:g> imezimwa"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kubadilisha njia za mkato"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Nimemaliza"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 6ba7a54..b1ce514 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"அணுகல் கோரிக்கையை ஓர் ஆப்ஸ் மறைப்பதால் உங்கள் பதிலைச் சரிபார்க்க முடியாது."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ஒரு அம்சத்தைப் பயன்படுத்த அதைத் தட்டவும்:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"அணுகல்தன்மை பட்டன் மூலம் பயன்படுத்த விரும்பும் அம்சங்களைத் தேர்வுசெய்யுங்கள்"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ஒலியளவு விசை ஷார்ட்கட் மூலம் பயன்படுத்த விரும்பும் அம்சங்களைத் தேர்வுசெய்யுங்கள்"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ஆஃப் செய்யப்பட்டுள்ளது"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ஷார்ட்கட்களை மாற்று"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"முடிந்தது"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index ae1a2c3..4b655d1 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ఒక యాప్ అనుమతి రిక్వెస్ట్‌కు అడ్డు తగులుతోంది కాబట్టి మీ సమాధానం వెరిఫై చేయడం సాధ్యం కాదు."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ఫీచర్‌ని ఉపయోగించడం ప్రారంభించడానికి, దాన్ని ట్యాప్ చేయండి:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"యాక్సెసిబిలిటీ బటన్‌తో ఉపయోగించడానికి ఫీచర్లను ఎంచుకోండి"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"వాల్యూమ్ కీ షార్ట్‌కట్‌తో ఉపయోగించడానికి ఫీచర్లను ఎంచుకోండి"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ఆఫ్ చేయబడింది"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"షార్ట్‌కట్‌లను ఎడిట్ చేయండి"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"పూర్తయింది"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 655cf4c..d979c34 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"มีแอปหนึ่งบดบังคำขอสิทธิ์ เราจึงยืนยันการตอบกลับของคุณไม่ได้"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"แตะฟีเจอร์เพื่อเริ่มใช้"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"เลือกฟีเจอร์ที่จะใช้กับปุ่มการช่วยเหลือพิเศษ"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"เลือกฟีเจอร์ที่จะใช้กับทางลัดปุ่มปรับระดับเสียง"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"ปิด <xliff:g id="SERVICE_NAME">%s</xliff:g> แล้ว"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"แก้ไขทางลัด"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"เสร็จ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 805dce5..fbbb32c 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"May app na pumipigil sa kahilingan sa pahintulot kaya hindi ma-verify ang iyong sagot."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"I-tap ang isang feature para simulan itong gamitin:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Pumili ng mga feature na gagana sa pamamagitan ng button ng accessibility"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Pumili ng mga feature na gagana sa pamamagitan ng shortcut ng volume key"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Na-off ang <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"I-edit ang mga shortcut"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Tapos na"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index a5d064e..a015a8f 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Bir uygulama, izin isteğini gizlediğinden yanıtınız doğrulanamıyor."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Kullanmaya başlamak için bir özelliğe dokunun:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Erişilebilirlik düğmesiyle kullanılacak özellikleri seçin"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Ses tuşu kısayoluyla kullanılacak özellikleri seçin"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kapatıldı"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kısayolları düzenle"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Bitti"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 5514ba4..e41d3ce 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1748,7 +1748,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Інший додаток перекриває запит на доступ, тому вашу відповідь не вдається підтвердити."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Натисніть функцію, щоб почати використовувати її:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Виберіть функції для кнопки спеціальних можливостей"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Виберіть функції для комбінації з клавішами гучності"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Сервіс <xliff:g id="SERVICE_NAME">%s</xliff:g> вимкнено"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Змінити"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 7c6317c..d2f0898 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ایپ اجازت کی درخواست کو مبہم کر رہی ہے لہذا آپ کے جواب کی تصدیق نہیں کی جا سکتی۔"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ایک خصوصیت کا استعمال شروع کرنے کیلئے اسے تھپتھپائیں:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ایکسیسبیلٹی بٹن کے ساتھ استعمال کرنے کیلئے خصوصیات منتخب کریں"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"والیوم کلید کے شارٹ کٹ کے ساتھ استعمال کرنے کیلئے خصوصیات منتخب کریں"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> کو آف کر دیا گیا ہے"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"شارٹ کٹس میں ترمیم کریں"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ہو گیا"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 868a927..e9bc805 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Ilova ruxsat olish talabini berkitmoqda, shu sababdan javobingizni tasdiqlash imkonsiz."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Kerakli funksiyani tanlang"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Qulayliklar tugmasi bilan foydalanish uchun funksiyalarni tanlang"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Tovush tugmasi bilan ishga tushiriladigan funksiyalarni tanlang"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> faolsizlantirildi"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Tezkor tugmalarni tahrirlash"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index c7337ef..510edab 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Một ứng dụng đang che khuất yêu cầu quyền này nên chúng tôi không thể xác minh phản hồi của bạn."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Nhấn vào một tính năng để bắt đầu sử dụng:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Chọn các tính năng để dùng với nút hỗ trợ tiếp cận"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Chọn các tính năng để dùng với phím tắt là phím âm lượng"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> đã bị tắt"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Chỉnh sửa phím tắt"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Xong"</string>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index 5266214..e28b646 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -96,4 +96,8 @@
 
     <!-- True if the device supports system decorations on secondary displays. -->
     <bool name="config_supportsSystemDecorsOnSecondaryDisplays">false</bool>
+
+    <!-- Whether to enable scaling and fading animation to scrollviews while scrolling.
+         P.S this is a change only intended for wear devices. -->
+    <bool name="config_enableViewGroupScalingFading">true</bool>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 378e548..bcb54dc 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"应用遮挡了权限请求,因此我们无法验证您的回复。"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"点按相应功能即可开始使用:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"选择可通过“无障碍”按钮使用的功能"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"选择可通过音量键快捷方式使用的功能"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"已关闭<xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"修改快捷方式"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 5a9db4f..875eec0 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"有應用程式阻擋權限要求,因此系統無法驗證你的回應。"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"輕按即可開始使用所需功能:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"選擇要配搭無障礙功能按鈕使用的功能"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"選擇要用音量快速鍵的功能"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> 已關閉"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"編輯捷徑"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5cfca16..efa4c51 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"應用程式遮擋了權限要求,因此系統無法驗證你的回覆。"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"輕觸即可開始使用所需功能:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"選擇要搭配無障礙工具按鈕使用的功能"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"選擇要搭配音量快速鍵使用的功能"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"「<xliff:g id="SERVICE_NAME">%s</xliff:g>」已關閉"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"編輯捷徑"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index c8e49a1..67a4361 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1746,7 +1746,8 @@
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"I-app ifihla isicelo semvume ngakho impendulo yakho ayikwazi ukuqinisekiswa."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Thepha isici ukuqala ukusisebenzisa:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Khetha izici ongazisebenzisa nenkinobho yokufinyeleleka"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Khetha izici ongazisebenzisa nesinqamuleli sokhiye wevolumu"</string>
+    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+    <skip />
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"I-<xliff:g id="SERVICE_NAME">%s</xliff:g> ivaliwe"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Hlela izinqamuleli"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Kwenziwe"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 38aff75..f6267f6 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -7121,4 +7121,8 @@
     <!-- The maximum number of call log entries for each sim card that can be stored in the call log
          provider on the device. -->
     <integer name="config_maximumCallLogEntriesPerSim">500</integer>
+
+    <!-- Whether to enable scaling and fading animation to scrollviews while scrolling.
+         P.S this is a change only intended for wear devices. -->
+    <bool name="config_enableViewGroupScalingFading">false</bool>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4693894..3c8c04e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5601,4 +5601,6 @@
 
   <!-- Fingerprint loe notification string -->
   <java-symbol type="string" name="fingerprint_loe_notification_msg" />
+
+  <java-symbol type="bool" name="config_enableViewGroupScalingFading"/>
 </resources>
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index 10aed8d..1429272 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -16,8 +16,6 @@
 
 package android.graphics;
 
-import static com.android.text.flags.Flags.FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -32,7 +30,6 @@
 import android.graphics.fonts.SystemFonts;
 import android.graphics.text.PositionedGlyphs;
 import android.graphics.text.TextRunShaper;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.text.FontConfig;
@@ -931,7 +928,6 @@
         return String.format(xml, op, lang, font);
     }
 
-    @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
     @Test
     public void testBuildSystemFallback__Customization_locale_prepend() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
@@ -947,7 +943,6 @@
         assertB3emFontIsUsed(typeface);
     }
 
-    @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
     @Test
     public void testBuildSystemFallback__Customization_locale_replace() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
@@ -963,7 +958,6 @@
         assertB3emFontIsUsed(typeface);
     }
 
-    @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
     @Test
     public void testBuildSystemFallback__Customization_locale_append() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
@@ -979,7 +973,6 @@
         assertA3emFontIsUsed(typeface);
     }
 
-    @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
     @Test
     public void testBuildSystemFallback__Customization_locale_ScriptMismatch() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
@@ -995,7 +988,6 @@
         assertA3emFontIsUsed(typeface);
     }
 
-    @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
     @Test
     public void testBuildSystemFallback__Customization_locale_SubscriptMatch() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
diff --git a/core/tests/coretests/src/com/android/internal/widget/ViewGroupFaderTest.java b/core/tests/coretests/src/com/android/internal/widget/ViewGroupFaderTest.java
new file mode 100644
index 0000000..eeabc2f
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/widget/ViewGroupFaderTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.test.AndroidTestCase;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.flags.Flags;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link ViewGroupFader}.
+ */
+public class ViewGroupFaderTest extends AndroidTestCase {
+
+    private Context mContext;
+    private ViewGroupFader mViewGroupFader;
+    private Resources mResources;
+
+    @Mock
+    private ViewGroup mViewGroup,mViewGroup1;
+
+    @Mock
+    private ViewGroupFader mockViewGroupFader;
+
+    @Mock
+    private ViewGroupFader.AnimationCallback mAnimationCallback;
+
+    @Mock
+    private ViewGroupFader.ChildViewBoundsProvider mChildViewBoundsProvider;
+
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        final Context mContext = getInstrumentation().getContext();
+        mResources = spy(mContext.getResources());
+        when(mResources.getBoolean(com.android.internal.R.bool.config_enableViewGroupScalingFading))
+                .thenReturn(true);
+        when(mViewGroup.getResources()).thenReturn(mResources);
+
+        mViewGroupFader = new ViewGroupFader(
+                mViewGroup,
+                mAnimationCallback,
+                mChildViewBoundsProvider);
+    }
+
+    /** This test checks that for each child of the parent viewgroup,
+     * updateListElementFades is called for each of its child, when the Flag is set to true
+     */
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_FADING_VIEW_GROUP)
+    public void testFadingAndScrollingAnimationWorking_FlagOn() {
+        mViewGroup.addView(mViewGroup1);
+        mViewGroupFader.updateFade();
+
+        for (int i = 0; i < mViewGroup.getChildCount(); i++) {
+            View child = mViewGroup.getChildAt(i);
+            verify(mockViewGroupFader).updateListElementFades((ViewGroup)child,true);
+        }
+    }
+
+    /** This test checks that for each child of the parent viewgroup,
+     * updateListElementFades is never called for each of its child, when the Flag is set to false
+     */
+    @Test
+    public void testFadingAndScrollingAnimationNotWorking_FlagOff() {
+        mViewGroup.addView(mViewGroup1);
+        mViewGroupFader.updateFade();
+
+        for (int i = 0; i < mViewGroup.getChildCount(); i++) {
+            View child = mViewGroup.getChildAt(i);
+            verify(mockViewGroupFader,never()).updateListElementFades((ViewGroup)child,true);
+        }
+    }
+}
\ No newline at end of file
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 9a55b80..880f30c 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -580,6 +580,11 @@
         <permission name="android.permission.PREPARE_FACTORY_RESET" />
         <!-- Permission required for CTS test - FileIntegrityManagerTest -->
         <permission name="android.permission.SETUP_FSVERITY" />
+        <!-- Permissions required for CTS test - AppFunctionManagerTest -->
+        <permission name="android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED" />
+        <permission name="android.permission.EXECUTE_APP_FUNCTIONS" />
+        <!-- Permission required for CTS test - CtsNfcTestCases -->
+        <permission name="android.permission.NFC_SET_CONTROLLER_ALWAYS_ON" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/fonts/FontCustomizationParser.java b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
index ba5628c..b7bf055 100644
--- a/graphics/java/android/graphics/fonts/FontCustomizationParser.java
+++ b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
@@ -182,10 +182,8 @@
 
             // For ignoring the customization, consume the new-locale-family element but don't
             // register any customizations.
-            if (com.android.text.flags.Flags.vendorCustomLocaleFallback()) {
-                outCustomization.add(new FontConfig.Customization.LocaleFallback(
-                        Locale.forLanguageTag(lang), intOp, family));
-            }
+            outCustomization.add(new FontConfig.Customization.LocaleFallback(
+                    Locale.forLanguageTag(lang), intOp, family));
         } else {
             throw new IllegalArgumentException("Unknown customizationType=" + customizationType);
         }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
index 4ce2942..bfccb29 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
@@ -16,16 +16,26 @@
 
 package androidx.window.extensions.embedding;
 
+import static android.window.TaskFragmentOrganizer.KEY_RESTORE_TASK_FRAGMENTS_INFO;
+import static android.window.TaskFragmentOrganizer.KEY_RESTORE_TASK_FRAGMENT_PARENT_INFO;
+
 import android.os.Build;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.MessageQueue;
+import android.util.ArrayMap;
 import android.util.Log;
+import android.util.SparseArray;
+import android.window.TaskFragmentInfo;
+import android.window.TaskFragmentParentInfo;
+import android.window.WindowContainerTransaction;
 
 import androidx.annotation.NonNull;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Helper class to back up and restore the TaskFragmentOrganizer state, in order to resume
@@ -40,11 +50,21 @@
     @NonNull
     private final SplitController mController;
     @NonNull
+    private final SplitPresenter mPresenter;
+    @NonNull
     private final BackupIdler mBackupIdler = new BackupIdler();
     private boolean mBackupIdlerScheduled;
 
-    BackupHelper(@NonNull SplitController splitController, @NonNull Bundle savedState) {
+    private final List<ParcelableTaskContainerData> mParcelableTaskContainerDataList =
+            new ArrayList<>();
+    private final ArrayMap<IBinder, TaskFragmentInfo> mTaskFragmentInfos = new ArrayMap<>();
+    private final SparseArray<TaskFragmentParentInfo> mTaskFragmentParentInfos =
+            new SparseArray<>();
+
+    BackupHelper(@NonNull SplitController splitController, @NonNull SplitPresenter splitPresenter,
+            @NonNull Bundle savedState) {
         mController = splitController;
+        mPresenter = splitPresenter;
 
         if (!savedState.isEmpty()) {
             restoreState(savedState);
@@ -67,13 +87,13 @@
         public boolean queueIdle() {
             synchronized (mController.mLock) {
                 mBackupIdlerScheduled = false;
-                startBackup();
+                saveState();
             }
             return false;
         }
     }
 
-    private void startBackup() {
+    private void saveState() {
         final List<TaskContainer> taskContainers = mController.getTaskContainers();
         if (taskContainers.isEmpty()) {
             Log.w(TAG, "No task-container to back up");
@@ -97,13 +117,92 @@
             return;
         }
 
-        final List<ParcelableTaskContainerData> parcelableTaskContainerDataList =
-                savedState.getParcelableArrayList(KEY_TASK_CONTAINERS,
-                        ParcelableTaskContainerData.class);
-        for (ParcelableTaskContainerData data : parcelableTaskContainerDataList) {
-            final TaskContainer taskContainer = new TaskContainer(data, mController);
-            if (DEBUG) Log.d(TAG, "Restoring task " + taskContainer.getTaskId());
-            // TODO(b/289875940): implement the TaskContainer restoration.
+        if (DEBUG) Log.d(TAG, "Start restoring saved-state");
+        mParcelableTaskContainerDataList.addAll(savedState.getParcelableArrayList(
+                KEY_TASK_CONTAINERS, ParcelableTaskContainerData.class));
+        if (DEBUG) Log.d(TAG, "Retrieved tasks : " + mParcelableTaskContainerDataList.size());
+        if (mParcelableTaskContainerDataList.isEmpty()) {
+            return;
+        }
+
+        final List<TaskFragmentInfo> infos = savedState.getParcelableArrayList(
+                KEY_RESTORE_TASK_FRAGMENTS_INFO, TaskFragmentInfo.class);
+        for (TaskFragmentInfo info : infos) {
+            if (DEBUG) Log.d(TAG, "Retrieved: " + info);
+            mTaskFragmentInfos.put(info.getFragmentToken(), info);
+            mPresenter.updateTaskFragmentInfo(info);
+        }
+
+        final List<TaskFragmentParentInfo> parentInfos = savedState.getParcelableArrayList(
+                KEY_RESTORE_TASK_FRAGMENT_PARENT_INFO,
+                TaskFragmentParentInfo.class);
+        for (TaskFragmentParentInfo info : parentInfos) {
+            if (DEBUG) Log.d(TAG, "Retrieved: " + info);
+            mTaskFragmentParentInfos.put(info.getTaskId(), info);
         }
     }
-}
+
+    boolean hasPendingStateToRestore() {
+        return !mParcelableTaskContainerDataList.isEmpty();
+    }
+
+    /**
+     * Returns {@code true} if any of the {@link TaskContainer} is restored.
+     * Otherwise, returns {@code false}.
+     */
+    boolean rebuildTaskContainers(@NonNull WindowContainerTransaction wct,
+            @NonNull Set<EmbeddingRule> rules) {
+        if (mParcelableTaskContainerDataList.isEmpty()) {
+            return false;
+        }
+
+        if (DEBUG) Log.d(TAG, "Rebuilding TaskContainers.");
+        final ArrayMap<String, EmbeddingRule> embeddingRuleMap = new ArrayMap<>();
+        for (EmbeddingRule rule : rules) {
+            embeddingRuleMap.put(rule.getTag(), rule);
+        }
+
+        boolean restoredAny = false;
+        for (int i = mParcelableTaskContainerDataList.size() - 1; i >= 0; i--) {
+            final ParcelableTaskContainerData parcelableTaskContainerData =
+                    mParcelableTaskContainerDataList.get(i);
+            final List<String> tags = parcelableTaskContainerData.getSplitRuleTags();
+            if (!embeddingRuleMap.containsAll(tags)) {
+                // has unknown tag, unable to restore.
+                if (DEBUG) {
+                    Log.d(TAG, "Rebuilding TaskContainer abort! Unknown Tag. Task#"
+                            + parcelableTaskContainerData.mTaskId);
+                }
+                continue;
+            }
+
+            mParcelableTaskContainerDataList.remove(parcelableTaskContainerData);
+            final TaskContainer taskContainer = new TaskContainer(parcelableTaskContainerData,
+                    mController, mTaskFragmentInfos);
+            if (DEBUG) Log.d(TAG, "Created TaskContainer " + taskContainer);
+            mController.addTaskContainer(taskContainer.getTaskId(), taskContainer);
+
+            for (ParcelableSplitContainerData splitData :
+                    parcelableTaskContainerData.getParcelableSplitContainerDataList()) {
+                final SplitRule rule = (SplitRule) embeddingRuleMap.get(splitData.mSplitRuleTag);
+                assert rule != null;
+                if (mController.getContainer(splitData.getPrimaryContainerToken()) != null
+                        && mController.getContainer(splitData.getSecondaryContainerToken())
+                        != null) {
+                    taskContainer.addSplitContainer(
+                            new SplitContainer(splitData, mController, rule));
+                }
+            }
+
+            mController.onTaskFragmentParentRestored(wct, taskContainer.getTaskId(),
+                    mTaskFragmentParentInfos.get(taskContainer.getTaskId()));
+            restoredAny = true;
+        }
+
+        if (mParcelableTaskContainerDataList.isEmpty()) {
+            mTaskFragmentParentInfos.clear();
+            mTaskFragmentInfos.clear();
+        }
+        return restoredAny;
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableSplitContainerData.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableSplitContainerData.java
index 817cfce..cb280c5 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableSplitContainerData.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableSplitContainerData.java
@@ -89,13 +89,13 @@
     };
 
     @NonNull
-    private IBinder getPrimaryContainerToken() {
+    IBinder getPrimaryContainerToken() {
         return mSplitContainer != null ? mSplitContainer.getPrimaryContainer().getToken()
                 : mPrimaryContainerToken;
     }
 
     @NonNull
-    private IBinder getSecondaryContainerToken() {
+    IBinder getSecondaryContainerToken() {
         return mSplitContainer != null ? mSplitContainer.getSecondaryContainer().getToken()
                 : mSecondaryContainerToken;
     }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableTaskContainerData.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableTaskContainerData.java
index 7377d00..97aa699 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableTaskContainerData.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableTaskContainerData.java
@@ -108,6 +108,15 @@
                 : mParcelableSplitContainerDataList;
     }
 
+    @NonNull
+    List<String> getSplitRuleTags() {
+        final List<String> tags = new ArrayList<>();
+        for (ParcelableSplitContainerData data : getParcelableSplitContainerDataList()) {
+            tags.add(data.mSplitRuleTag);
+        }
+        return tags;
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
index 6d436ec..faf73c2 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
@@ -86,6 +86,25 @@
         }
     }
 
+    /** This is only used when restoring it from a {@link ParcelableSplitContainerData}. */
+    SplitContainer(@NonNull ParcelableSplitContainerData parcelableData,
+            @NonNull SplitController splitController, @NonNull SplitRule splitRule) {
+        mParcelableData = parcelableData;
+        mPrimaryContainer = splitController.getContainer(parcelableData.getPrimaryContainerToken());
+        mSecondaryContainer = splitController.getContainer(
+                parcelableData.getSecondaryContainerToken());
+        mSplitRule = splitRule;
+        mDefaultSplitAttributes = splitRule.getDefaultSplitAttributes();
+        mCurrentSplitAttributes = mDefaultSplitAttributes;
+
+        if (shouldFinishPrimaryWithSecondary(splitRule)) {
+            mSecondaryContainer.addContainerToFinishOnExit(mPrimaryContainer);
+        }
+        if (shouldFinishSecondaryWithPrimary(splitRule)) {
+            mPrimaryContainer.addContainerToFinishOnExit(mSecondaryContainer);
+        }
+    }
+
     void setPrimaryContainer(@NonNull TaskFragmentContainer primaryContainer) {
         if (!mParcelableData.mIsPrimaryContainerMutable) {
             throw new IllegalStateException("Cannot update primary TaskFragmentContainer");
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 f2f2b7ea..db4bb0e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -279,6 +279,26 @@
             Log.i(TAG, "Setting embedding rules. Size: " + rules.size());
             mSplitRules.clear();
             mSplitRules.addAll(rules);
+
+            if (!Flags.aeBackStackRestore() || !mPresenter.isRebuildTaskContainersNeeded()) {
+                return;
+            }
+
+            try {
+                final TransactionRecord transactionRecord =
+                        mTransactionManager.startNewTransaction();
+                final WindowContainerTransaction wct = transactionRecord.getTransaction();
+                if (mPresenter.rebuildTaskContainers(wct, rules)) {
+                    transactionRecord.apply(false /* shouldApplyIndependently */);
+                    updateCallbackIfNecessary();
+                } else {
+                    transactionRecord.abort();
+                }
+            } catch (IllegalStateException ex) {
+                Log.e(TAG, "Having an existing transaction while running restoration with"
+                        + "new rules!! It is likely too late to perform the restoration "
+                        + "already!?", ex);
+            }
         }
     }
 
@@ -903,6 +923,12 @@
     }
 
     @GuardedBy("mLock")
+    void onTaskFragmentParentRestored(@NonNull WindowContainerTransaction wct, int taskId,
+            @NonNull TaskFragmentParentInfo parentInfo) {
+        onTaskFragmentParentInfoChanged(wct, taskId, parentInfo);
+    }
+
+    @GuardedBy("mLock")
     void updateContainersInTaskIfVisible(@NonNull WindowContainerTransaction wct, int taskId) {
         final TaskContainer taskContainer = getTaskContainer(taskId);
         if (taskContainer == null) {
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 abc7b29..0c0ded9 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -24,6 +24,7 @@
 import static androidx.window.extensions.embedding.WindowAttributes.DIM_AREA_ON_TASK;
 
 import android.annotation.AnimRes;
+import android.annotation.NonNull;
 import android.app.Activity;
 import android.app.ActivityThread;
 import android.app.WindowConfiguration;
@@ -47,7 +48,6 @@
 import android.window.WindowContainerTransaction;
 
 import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.window.extensions.core.util.function.Function;
 import androidx.window.extensions.embedding.SplitAttributes.SplitType;
@@ -67,6 +67,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.Executor;
 
 /**
@@ -174,7 +175,7 @@
         } else {
             registerOrganizer();
         }
-        mBackupHelper = new BackupHelper(controller, outSavedState);
+        mBackupHelper = new BackupHelper(controller, this, outSavedState);
         if (!SplitController.ENABLE_SHELL_TRANSITIONS) {
             // TODO(b/207070762): cleanup with legacy app transition
             // Animation will be handled by WM Shell when Shell transition is enabled.
@@ -186,6 +187,15 @@
         mBackupHelper.scheduleBackup();
     }
 
+    boolean isRebuildTaskContainersNeeded() {
+        return mBackupHelper.hasPendingStateToRestore();
+    }
+
+    boolean rebuildTaskContainers(@NonNull WindowContainerTransaction wct,
+            @NonNull Set<EmbeddingRule> rules) {
+        return mBackupHelper.rebuildTaskContainers(wct, rules);
+    }
+
     /**
      * Deletes the specified container and all other associated and dependent containers in the same
      * transaction.
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 608a3be..74cce68 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -31,6 +31,7 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.IBinder;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -147,14 +148,23 @@
 
     /** This is only used when restoring it from a {@link ParcelableTaskContainerData}. */
     TaskContainer(@NonNull ParcelableTaskContainerData data,
-            @NonNull SplitController splitController) {
+            @NonNull SplitController splitController,
+            @NonNull ArrayMap<IBinder, TaskFragmentInfo> taskFragmentInfoMap) {
         mParcelableTaskContainerData = new ParcelableTaskContainerData(data, this);
+        mInfo = new TaskFragmentParentInfo(new Configuration(), 0 /* displayId */, -1 /* taskId */,
+                false /* visible */, false /* hasDirectActivity */, null /* decorSurface */);
         mSplitController = splitController;
         for (ParcelableTaskFragmentContainerData tfData :
                 data.getParcelableTaskFragmentContainerDataList()) {
-            final TaskFragmentContainer container =
-                    new TaskFragmentContainer(tfData, splitController, this);
-            mContainers.add(container);
+            final TaskFragmentInfo info = taskFragmentInfoMap.get(tfData.mToken);
+            if (info != null && !info.isEmpty()) {
+                final TaskFragmentContainer container =
+                        new TaskFragmentContainer(tfData, splitController, this);
+                container.setInfo(new WindowContainerTransaction(), info);
+                mContainers.add(container);
+            } else {
+                Log.d(TAG, "Drop " + tfData + " while restoring Task " + data.mTaskId);
+            }
         }
     }
 
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt
new file mode 100644
index 0000000..35d459f
--- /dev/null
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2024 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.bubbles.bar
+
+import android.app.ActivityManager
+import android.content.Context
+import android.graphics.Insets
+import android.graphics.Rect
+import android.view.LayoutInflater
+import android.view.View
+import android.view.WindowManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import com.android.internal.protolog.ProtoLog
+import com.android.wm.shell.R
+import com.android.wm.shell.bubbles.Bubble
+import com.android.wm.shell.bubbles.BubbleData
+import com.android.wm.shell.bubbles.BubbleExpandedViewManager
+import com.android.wm.shell.bubbles.BubblePositioner
+import com.android.wm.shell.bubbles.BubbleTaskView
+import com.android.wm.shell.bubbles.BubbleTaskViewFactory
+import com.android.wm.shell.bubbles.DeviceConfig
+import com.android.wm.shell.bubbles.RegionSamplingProvider
+import com.android.wm.shell.common.ShellExecutor
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation
+import com.android.wm.shell.shared.handles.RegionSamplingHelper
+import com.android.wm.shell.taskview.TaskView
+import com.android.wm.shell.taskview.TaskViewTaskController
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+import java.util.Collections
+import java.util.concurrent.Executor
+
+/** Tests for [BubbleBarExpandedViewTest] */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class BubbleBarExpandedViewTest {
+    companion object {
+        const val SCREEN_WIDTH = 2000
+        const val SCREEN_HEIGHT = 1000
+    }
+
+    private val context = ApplicationProvider.getApplicationContext<Context>()
+    private val windowManager = context.getSystemService(WindowManager::class.java)
+
+    private lateinit var mainExecutor: TestExecutor
+    private lateinit var bgExecutor: TestExecutor
+
+    private lateinit var expandedViewManager: BubbleExpandedViewManager
+    private lateinit var positioner: BubblePositioner
+    private lateinit var bubbleTaskView: BubbleTaskView
+
+    private lateinit var bubbleExpandedView: BubbleBarExpandedView
+    private var testableRegionSamplingHelper: TestableRegionSamplingHelper? = null
+    private var regionSamplingProvider: TestRegionSamplingProvider? = null
+
+    @Before
+    fun setUp() {
+        ProtoLog.REQUIRE_PROTOLOGTOOL = false
+        mainExecutor = TestExecutor()
+        bgExecutor = TestExecutor()
+        positioner = BubblePositioner(context, windowManager)
+        positioner.setShowingInBubbleBar(true)
+        val deviceConfig =
+            DeviceConfig(
+                windowBounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT),
+                isLargeScreen = true,
+                isSmallTablet = false,
+                isLandscape = true,
+                isRtl = false,
+                insets = Insets.of(10, 20, 30, 40)
+            )
+        positioner.update(deviceConfig)
+
+        expandedViewManager = createExpandedViewManager()
+        bubbleTaskView = FakeBubbleTaskViewFactory().create()
+
+        val inflater = LayoutInflater.from(context)
+
+        regionSamplingProvider = TestRegionSamplingProvider()
+
+        bubbleExpandedView = (inflater.inflate(
+            R.layout.bubble_bar_expanded_view, null, false /* attachToRoot */
+        ) as BubbleBarExpandedView)
+        bubbleExpandedView.initialize(
+            expandedViewManager,
+            positioner,
+            false /* isOverflow */,
+            bubbleTaskView,
+            mainExecutor,
+            bgExecutor,
+            regionSamplingProvider
+        )
+
+        getInstrumentation().runOnMainSync(Runnable {
+            bubbleExpandedView.onAttachedToWindow()
+            // Helper should be created once attached to window
+            testableRegionSamplingHelper = regionSamplingProvider!!.helper
+        })
+    }
+
+    @After
+    fun tearDown() {
+        testableRegionSamplingHelper?.stopAndDestroy()
+    }
+
+    @Test
+    fun testCreateSamplingHelper_onAttach() {
+        assertThat(testableRegionSamplingHelper).isNotNull()
+    }
+
+    @Test
+    fun testDestroySamplingHelper_onDetach() {
+        bubbleExpandedView.onDetachedFromWindow()
+        assertThat(testableRegionSamplingHelper!!.isDestroyed).isTrue()
+    }
+
+    @Test
+    fun testStopSampling_onDragStart() {
+        bubbleExpandedView.setContentVisibility(true)
+        assertThat(testableRegionSamplingHelper!!.isStarted).isTrue()
+
+        bubbleExpandedView.setDragging(true)
+        assertThat(testableRegionSamplingHelper!!.isStopped).isTrue()
+    }
+
+    @Test
+    fun testStartSampling_onDragEnd() {
+        bubbleExpandedView.setDragging(true)
+        bubbleExpandedView.setContentVisibility(true)
+        assertThat(testableRegionSamplingHelper!!.isStopped).isTrue()
+
+        bubbleExpandedView.setDragging(false)
+        assertThat(testableRegionSamplingHelper!!.isStarted).isTrue()
+    }
+
+    @Test
+    fun testStartSampling_onContentVisible() {
+        bubbleExpandedView.setContentVisibility(true)
+        assertThat(testableRegionSamplingHelper!!.setWindowVisible).isTrue()
+        assertThat(testableRegionSamplingHelper!!.isStarted).isTrue()
+    }
+
+    @Test
+    fun testStopSampling_onContentInvisible() {
+        bubbleExpandedView.setContentVisibility(false)
+
+        assertThat(testableRegionSamplingHelper!!.setWindowInvisible).isTrue()
+        assertThat(testableRegionSamplingHelper!!.isStopped).isTrue()
+    }
+
+    @Test
+    fun testSampling_startStopAnimating_visible() {
+        bubbleExpandedView.isAnimating = true
+        bubbleExpandedView.setContentVisibility(true)
+        assertThat(testableRegionSamplingHelper!!.isStopped).isTrue()
+
+        bubbleExpandedView.isAnimating = false
+        assertThat(testableRegionSamplingHelper!!.isStarted).isTrue()
+    }
+
+    @Test
+    fun testSampling_startStopAnimating_invisible() {
+        bubbleExpandedView.isAnimating = true
+        bubbleExpandedView.setContentVisibility(false)
+        assertThat(testableRegionSamplingHelper!!.isStopped).isTrue()
+        testableRegionSamplingHelper!!.reset()
+
+        bubbleExpandedView.isAnimating = false
+        assertThat(testableRegionSamplingHelper!!.isStopped).isTrue()
+    }
+
+    private inner class FakeBubbleTaskViewFactory : BubbleTaskViewFactory {
+        override fun create(): BubbleTaskView {
+            val taskViewTaskController = mock<TaskViewTaskController>()
+            val taskView = TaskView(context, taskViewTaskController)
+            val taskInfo = mock<ActivityManager.RunningTaskInfo>()
+            whenever(taskViewTaskController.taskInfo).thenReturn(taskInfo)
+            return BubbleTaskView(taskView, mainExecutor)
+        }
+    }
+
+    private inner class TestRegionSamplingProvider : RegionSamplingProvider {
+
+        lateinit var helper: TestableRegionSamplingHelper
+
+        override fun createHelper(
+            sampledView: View?,
+            callback: RegionSamplingHelper.SamplingCallback?,
+            backgroundExecutor: Executor?,
+            mainExecutor: Executor?
+        ): RegionSamplingHelper {
+            helper = TestableRegionSamplingHelper(sampledView, callback, backgroundExecutor,
+                mainExecutor)
+            return helper
+        }
+    }
+
+    private inner class TestableRegionSamplingHelper(
+        sampledView: View?,
+        samplingCallback: SamplingCallback?,
+        backgroundExecutor: Executor?,
+        mainExecutor: Executor?
+    ) : RegionSamplingHelper(sampledView, samplingCallback, backgroundExecutor, mainExecutor) {
+
+        var isStarted = false
+        var isStopped = false
+        var isDestroyed = false
+        var setWindowVisible = false
+        var setWindowInvisible = false
+
+        override fun start(initialSamplingBounds: Rect) {
+            super.start(initialSamplingBounds)
+            isStarted = true
+        }
+
+        override fun stop() {
+            super.stop()
+            isStopped = true
+        }
+
+        override fun stopAndDestroy() {
+            super.stopAndDestroy()
+            isDestroyed = true
+        }
+
+        override fun setWindowVisible(visible: Boolean) {
+            super.setWindowVisible(visible)
+            if (visible) {
+                setWindowVisible = true
+            } else {
+                setWindowInvisible = true
+            }
+        }
+
+        fun reset() {
+            isStarted = false
+            isStopped = false
+            isDestroyed = false
+            setWindowVisible = false
+            setWindowInvisible = false
+        }
+    }
+
+    private fun createExpandedViewManager(): BubbleExpandedViewManager {
+        return object : BubbleExpandedViewManager {
+            override val overflowBubbles: List<Bubble>
+                get() = Collections.emptyList()
+
+            override fun setOverflowListener(listener: BubbleData.Listener) {
+            }
+
+            override fun collapseStack() {
+            }
+
+            override fun updateWindowFlagsForBackpress(intercept: Boolean) {
+            }
+
+            override fun promoteBubbleFromOverflow(bubble: Bubble) {
+            }
+
+            override fun removeBubble(key: String, reason: Int) {
+            }
+
+            override fun dismissBubble(bubble: Bubble, reason: Int) {
+            }
+
+            override fun setAppBubbleTaskId(key: String, taskId: Int) {
+            }
+
+            override fun isStackExpanded(): Boolean {
+                return true
+            }
+
+            override fun isShowingAsBubbleBar(): Boolean {
+                return true
+            }
+
+            override fun hideCurrentInputMethod() {
+            }
+
+            override fun updateBubbleBarLocation(location: BubbleBarLocation) {
+            }
+        }
+    }
+
+    private class TestExecutor : ShellExecutor {
+
+        private val runnables: MutableList<Runnable> = mutableListOf()
+
+        override fun execute(runnable: Runnable) {
+            runnables.add(runnable)
+        }
+
+        override fun executeDelayed(runnable: Runnable, delayMillis: Long) {
+            execute(runnable)
+        }
+
+        override fun removeCallbacks(runnable: Runnable?) {}
+
+        override fun hasCallback(runnable: Runnable?): Boolean = false
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index d1b98a6..0ed5a72 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"vou <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> in"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>-instellings"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Maak borrel toe"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Moenie dat gesprek \'n borrel word nie"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Klets met borrels"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Nuwe gesprekke verskyn as swerwende ikone, of borrels Tik op borrel om dit oop te maak. Sleep om dit te skuif."</string>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index 8044719..c4d9158 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>ን ሰብስብ"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"የ<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ቅንብሮች"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"አረፋን አሰናብት"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"ውይይቶችን በአረፋ አታሳይ"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"አረፋዎችን በመጠቀም ይወያዩ"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"አዲስ ውይይቶች እንደ ተንሳፋፊ አዶዎች ወይም አረፋዎች ሆነው ይታያሉ። አረፋን ለመክፈት መታ ያድርጉ። ለመውሰድ ይጎትቱት።"</string>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 21aa34e..ced9ee9 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"تصغير <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"إعدادات <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"إغلاق فقاعة المحادثة"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"عدم عرض المحادثة كفقاعة محادثة"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"الدردشة باستخدام فقاعات المحادثات"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"تظهر المحادثات الجديدة كرموز عائمة أو كفقاعات. انقر لفتح فقاعة المحادثة، واسحبها لتحريكها."</string>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index c59f470..273d043 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> সংকোচন কৰক"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ছেটিং"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"বাবল অগ্ৰাহ্য কৰক"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"বাৰ্তালাপ বাবল নকৰিব"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Bubbles ব্যৱহাৰ কৰি চাট কৰক"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"নতুন বাৰ্তালাপ উপঙি থকা চিহ্নসমূহ অথবা bubbles হিচাপে প্ৰদর্শিত হয়। Bubbles খুলিবলৈ টিপক। এইটো স্থানান্তৰ কৰিবলৈ টানি নিয়ক।"</string>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index 841323e..81bb544 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"yığcamlaşdırın: <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ayarları"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Yumrucuğu ləğv edin"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Söhbəti yumrucuqda göstərmə"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Yumrucuqlardan istifadə edərək söhbət edin"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Yeni söhbətlər üzən nişanlar və ya yumrucuqlar kimi görünür. Yumrucuğu açmaq üçün toxunun. Hərəkət etdirmək üçün sürüşdürün."</string>
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 86ab548..898b844 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"skupite oblačić <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Podešavanja za <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Odbaci oblačić"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ne koristi oblačiće za konverzaciju"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Ćaskajte u oblačićima"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Nove konverzacije se prikazuju kao plutajuće ikone ili oblačići. Dodirnite da biste otvorili oblačić. Prevucite da biste ga premestili."</string>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index bcbc1ae..c340729 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>: згарнуць"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Налады \"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>\""</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Адхіліць апавяшчэнне"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Не паказваць размову ў выглядзе ўсплывальных апавяшчэнняў"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Усплывальныя чаты"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Новыя размовы будуць паказвацца як рухомыя значкі ці ўсплывальныя чаты. Націсніце, каб адкрыць усплывальны чат. Перацягніце яго, каб перамясціць."</string>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index 4d1208b..076a815 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"свиване на <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Настройки за <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Отхвърляне на балончетата"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Без балончета за разговора"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Чат с балончета"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Новите разговори се показват като плаващи икони, или балончета. Докоснете балонче, за да го отворите, или го плъзнете, за да го преместите."</string>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index bf8bc99..b0d6696 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> আড়াল করুন"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> সেটিংস"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"বাবল খারিজ করুন"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"কথোপকথন বাবল হিসেবে দেখাবে না"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"বাবল ব্যবহার করে চ্যাট করুন"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"নতুন কথোপকথন ভেসে থাকা আইকন বা বাবল হিসেবে দেখানো হয়। বাবল খুলতে ট্যাপ করুন। সেটি সরাতে ধরে টেনে আনুন।"</string>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index cf53d25..0196e5e 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"sužavanje oblačića <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Postavke aplikacije <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Odbaci oblačić"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nemoj prikazivati razgovor u oblačićima"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatajte koristeći oblačiće"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Novi razgovori se prikazuju kao plutajuće ikone ili oblačići. Dodirnite da otvorite oblačić. Prevucite da ga premjestite."</string>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index 87ea62e..fa4b627 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"replega <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Configuració de l\'aplicació <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignora la bombolla"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"No mostris la conversa com a bombolla"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Xateja amb bombolles"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Les converses noves es mostren com a icones flotants o bombolles. Toca per obrir una bombolla. Arrossega-la per moure-la."</string>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index e21213b..3956fca 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"sbalit <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Nastavení <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Zavřít bublinu"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nezobrazovat konverzaci v bublinách"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatujte pomocí bublin"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Nové konverzace se zobrazují jako plovoucí ikony, neboli bubliny. Klepnutím bublinu otevřete. Přetažením ji posunete."</string>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index 1c4647f..afe4a1ab 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"skjul <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Indstillinger for <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Afvis boble"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Vis ikke samtaler i bobler"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat ved hjælp af bobler"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Nye samtaler vises som svævende ikoner eller bobler. Tryk for at åbne boblen. Træk for at flytte den."</string>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index 88a5789..1e50339 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> minimieren"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Einstellungen für <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Bubble schließen"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Unterhaltung nicht als Bubble anzeigen"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Bubbles zum Chatten verwenden"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Neue Unterhaltungen erscheinen als unverankerte Symbole, „Bubbles“ genannt. Wenn du eine Bubble öffnen möchtest, tippe sie an. Wenn du sie verschieben möchtest, zieh an ihr."</string>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index beeefee..5c3c6de 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"σύμπτυξη <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Ρυθμίσεις <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Παράβλ. για συννεφ."</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Να μην γίνει προβολή της συζήτησης σε συννεφάκια."</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Συζητήστε χρησιμοποιώντας συννεφάκια."</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Οι νέες συζητήσεις εμφανίζονται ως κινούμενα εικονίδια ή συννεφάκια. Πατήστε για να ανοίξετε το συννεφάκι. Σύρετε για να το μετακινήσετε."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
index 72f4070..51c69e5 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"collapse <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> settings"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Dismiss bubble"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Don’t bubble conversation"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat using bubbles"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
index d11f521..f5b0a27 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
@@ -73,6 +73,7 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"collapse <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> settings"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Dismiss bubble"</string>
+    <string name="bubble_fullscreen_text" msgid="1006758103218086231">"Move to fullscreen"</string>
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Don’t bubble conversation"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat using bubbles"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
index 72f4070..51c69e5 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"collapse <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> settings"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Dismiss bubble"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Don’t bubble conversation"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat using bubbles"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
index 72f4070..51c69e5 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"collapse <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> settings"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Dismiss bubble"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Don’t bubble conversation"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat using bubbles"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
index 8002468..6292be5 100644
--- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
@@ -73,6 +73,7 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‏‏‎‎‎‏‎‎‏‎collapse ‎‏‎‎‏‏‎<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ settings‎‏‎‎‏‎"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‎‏‎‏‎‏‏‎‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‎‎Dismiss bubble‎‏‎‎‏‎"</string>
+    <string name="bubble_fullscreen_text" msgid="1006758103218086231">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‏‎‎‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎Move to fullscreen‎‏‎‎‏‎"</string>
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‎‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‎‏‎Don’t bubble conversation‎‏‎‎‏‎"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎Chat using bubbles‎‏‎‎‏‎"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‎‏‎‎‏‎‏‎‏‏‏‏‎New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it.‎‏‎‎‏‎"</string>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index 5756aae..8644780 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"contraer <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Configuración de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Descartar burbuja"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"No mostrar la conversación en burbuja"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat con burbujas"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Las conversaciones nuevas aparecen como elementos flotantes o burbujas. Presiona para abrir la burbuja. Arrástrala para moverla."</string>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index 3c55bf6..9718bf1 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"contraer <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Ajustes de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Cerrar burbuja"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"No mostrar conversación en burbuja"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatea con burbujas"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Las conversaciones nuevas aparecen como iconos flotantes llamados \"burbujas\". Toca una burbuja para abrirla. Arrástrala para moverla."</string>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index d921967..d36a8d1 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"ahenda <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Rakenduse <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> seaded"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Sule mull"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ära kuva vestlust mullina"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Vestelge mullide abil"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Uued vestlused kuvatakse hõljuvate ikoonidena ehk mullidena. Puudutage mulli avamiseks. Lohistage mulli, et seda liigutada."</string>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index f319af1..2ee086e 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"tolestu <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> aplikazioaren ezarpenak"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Baztertu burbuila"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ez erakutsi elkarrizketak burbuila gisa"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Txateatu burbuilen bidez"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Elkarrizketa berriak ikono gainerakor edo burbuila gisa agertzen dira. Sakatu burbuila irekitzeko. Arrasta ezazu mugitzeko."</string>
@@ -80,7 +82,7 @@
     <string name="bubbles_user_education_manage" msgid="3460756219946517198">"Aplikazioaren burbuilak desaktibatzeko, sakatu Kudeatu"</string>
     <string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Ados"</string>
     <string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Ez dago azkenaldiko burbuilarik"</string>
-    <string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Azken burbuilak eta baztertutakoak agertuko dira hemen"</string>
+    <string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Azkenaldiko burbuilak eta baztertutakoak agertuko dira hemen"</string>
     <string name="bubble_bar_education_stack_title" msgid="2486903590422497245">"Txateatu burbuilak erabilita"</string>
     <string name="bubble_bar_education_stack_text" msgid="2446934610817409820">"Elkarrizketa berriak ikono gisa agertzen dira pantailaren beheko izkinan. Zabaltzeko, saka itzazu. Baztertzeko, aldiz, arrasta itzazu."</string>
     <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Kontrolatu burbuilak edonoiz"</string>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index 44a0929..f4cdd5f 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"جمع کردن <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"تنظیمات <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"رد کردن حبابک"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"مکالمه در حباب نشان داده نشود"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"گپ بااستفاده از حبابک‌ها"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"مکالمه‌های جدید به‌صورت نمادهای شناور یا حبابک‌ها نشان داده می‌شوند. برای باز کردن حبابک‌ها تک‌ضرب بزنید. برای جابه‌جایی، آن را بکشید."</string>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index 59cd6e0..6be2ee2 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"tiivistä <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>: asetukset"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Ohita kupla"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Älä näytä kuplia keskusteluista"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chattaile kuplien avulla"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Uudet keskustelut näkyvät kelluvina kuvakkeina tai kuplina. Avaa kupla napauttamalla. Siirrä sitä vetämällä."</string>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index 02f832b..5470099 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"réduire <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Paramètres <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignorer la bulle"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ne pas afficher les conversations dans des bulles"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Clavarder en utilisant des bulles"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Les nouvelles conversations s\'affichent sous forme d\'icônes flottantes (de bulles). Touchez une bulle pour l\'ouvrir. Faites-la glisser pour la déplacer."</string>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index 5d916f4..63b5994 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"Réduire <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Paramètres <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Fermer la bulle"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ne pas afficher la conversation dans une bulle"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatter en utilisant des bulles"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Les nouvelles conversations s\'affichent sous forme d\'icônes flottantes ou de bulles. Appuyez sur la bulle pour l\'ouvrir. Faites-la glisser pour la déplacer."</string>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index e1b2a7e..36ad521 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"contraer <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Configuración de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignorar burbulla"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Non mostrar a conversa como burbulla"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatear usando burbullas"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"As conversas novas aparecen como iconas flotantes ou burbullas. Toca para abrir a burbulla e arrastra para movela."</string>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index fecce73..868ef5b 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> નાનું કરો"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> સેટિંગ"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"બબલને છોડી દો"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"વાતચીતને બબલ કરશો નહીં"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"બબલનો ઉપયોગ કરીને ચૅટ કરો"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"નવી વાતચીત ફ્લોટિંગ આઇકન અથવા બબલ જેવી દેખાશે. બબલને ખોલવા માટે ટૅપ કરો. તેને ખસેડવા માટે ખેંચો."</string>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index f889f20..31c7307 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> को छोटा करें"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> की सेटिंग"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"बबल खारिज करें"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"बातचीत को बबल न करें"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"बबल्स का इस्तेमाल करके चैट करें"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"नई बातचीत फ़्लोटिंग आइकॉन या बबल्स की तरह दिखेंगी. बबल को खोलने के लिए टैप करें. इसे एक जगह से दूसरी जगह ले जाने के लिए खींचें और छोड़ें."</string>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index 04053c8..d99a65d8 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"sažmite oblačić <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Postavke za <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Odbaci oblačić"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Zaustavi razgovor u oblačićima"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Oblačići u chatu"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Novi razgovori pojavljuju se kao pomične ikone ili oblačići. Dodirnite za otvaranje oblačića. Povucite da biste ga premjestili."</string>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index bb52649..bed760e 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> összecsukása"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> beállításai"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Buborék elvetése"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ne jelenjen meg a beszélgetés buborékban"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Buborékokat használó csevegés"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Az új beszélgetések lebegő ikonként, vagyis buborékként jelennek meg. A buborék megnyitásához koppintson rá. Áthelyezéshez húzza a kívánt helyre."</string>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index fff5a10..fcb7254 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>. ծալել"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> – կարգավորումներ"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Փակել ամպիկը"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Զրույցը չցուցադրել ամպիկի տեսքով"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Զրույցի ամպիկներ"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Նոր զրույցները կհայտնվեն լողացող պատկերակների կամ ամպիկների տեսքով։ Հպեք՝ ամպիկը բացելու համար։ Քաշեք՝ այն տեղափոխելու համար։"</string>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index a957754..85a9bbf 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"ciutkan <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Setelan <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Tutup balon"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Jangan gunakan percakapan balon"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat dalam tampilan balon"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Percakapan baru muncul sebagai ikon mengambang, atau balon. Ketuk untuk membuka balon. Tarik untuk memindahkannya."</string>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index 7b91768..8041162 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"minnka <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Stillingar <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Loka blöðru"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ekki setja samtal í blöðru"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Spjalla með blöðrum"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Ný samtöl birtast sem fljótandi tákn eða blöðrur. Ýttu til að opna blöðru. Dragðu hana til að færa."</string>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index 4ae4b36..3ba6873 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"comprimi <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Impostazioni <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignora bolla"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Non mettere la conversazione nella bolla"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatta utilizzando le bolle"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Le nuove conversazioni vengono mostrate come icone mobili o bolle. Tocca per aprire la bolla. Trascinala per spostarla."</string>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index ea73653..e1854fa1 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"כיווץ של <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"הגדרות <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"סגירת בועה"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"אין להציג בועות לשיחה"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"לדבר בבועות"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"שיחות חדשות מופיעות כסמלים צפים, או בועות. יש להקיש כדי לפתוח בועה. יש לגרור כדי להזיז אותה."</string>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index 0cb921c..1f1ddc7 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>を閉じます"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> の設定"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"バブルを閉じる"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"会話をバブルで表示しない"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"チャットでバブルを使う"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"新しい会話はフローティング アイコン(バブル)として表示されます。タップするとバブルが開きます。ドラッグしてバブルを移動できます。"</string>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index 16e99ba..e201a20 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>-ის ჩაკეცვა"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>-ის პარამეტრები"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"ბუშტის დახურვა"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"აიკრძალოს საუბრის ბუშტები"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"ჩეთი ბუშტების გამოყენებით"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"ახალი საუბრები გამოჩნდება როგორც მოტივტივე ხატულები ან ბუშტები. შეეხეთ ბუშტის გასახსნელად. გადაიტანეთ ჩავლებით."</string>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index c6f558f..1c335dd 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>: жию"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> параметрлері"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Қалқымалы хабарды жабу"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Әңгіменің қалқыма хабары көрсетілмесін"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Қалқыма хабарлар арқылы сөйлесу"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Жаңа әңгімелер қалқыма белгішелер немесе хабарлар түрінде көрсетіледі. Қалқыма хабарды ашу үшін түртіңіз. Жылжыту үшін сүйреңіз."</string>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index 508ea48..d0cceee 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"បង្រួម <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"ការកំណត់ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"ច្រានចោល​ពពុះ"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"កុំបង្ហាញ​ការសន្ទនា​ជាពពុះ"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"ជជែក​ដោយប្រើ​ពពុះ"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"ការសន្ទនាថ្មីៗ​បង្ហាញជា​​ពពុះ ឬរូបអណ្ដែត។ ចុច ដើម្បីបើក​ពពុះ។ អូស ដើម្បី​ផ្លាស់ទី​ពពុះនេះ។"</string>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index 1fc627b..63b5c68 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ಅನ್ನು ಕುಗ್ಗಿಸಿ"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"ಬಬಲ್ ವಜಾಗೊಳಿಸಿ"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"ಸಂಭಾಷಣೆಯನ್ನು ಬಬಲ್ ಮಾಡಬೇಡಿ"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"ಬಬಲ್ಸ್ ಬಳಸಿ ಚಾಟ್ ಮಾಡಿ"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"ಹೊಸ ಸಂಭಾಷಣೆಗಳು ತೇಲುವ ಐಕಾನ್‌ಗಳು ಅಥವಾ ಬಬಲ್ಸ್ ಆಗಿ ಗೋಚರಿಸುತ್ತವೆ. ಬಬಲ್ ತೆರೆಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಅದನ್ನು ಡ್ರ್ಯಾಗ್ ಮಾಡಲು ಎಳೆಯಿರಿ."</string>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index 96d360e..b5efd10 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> 접기"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> 설정"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"대화창 닫기"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"대화를 대화창으로 표시하지 않기"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"대화창으로 채팅하기"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"새로운 대화가 플로팅 아이콘인 대화창으로 표시됩니다. 대화창을 열려면 탭하세요. 드래그하여 이동할 수 있습니다."</string>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index 662c2eae..e001efe 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> жыйыштыруу"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> параметрлери"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Калкып чыкма билдирмени жабуу"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Жазышууда калкып чыкма билдирмелер көрүнбөсүн"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Калкып чыкма билдирмелер аркылуу маектешүү"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Жаңы жазышуулар калкыма сүрөтчөлөр же калкып чыкма билдирмелер түрүндө көрүнөт. Калкып чыкма билдирмелерди ачуу үчүн тийип коюңуз. Жылдыруу үчүн сүйрөңүз."</string>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index ed6b378..029c95b 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"ຫຍໍ້ <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ລົງ"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"ການຕັ້ງຄ່າ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"ປິດຟອງໄວ້"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"ຢ່າໃຊ້ຟອງໃນການສົນທະນາ"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"ສົນທະນາໂດຍໃຊ້ຟອງ"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"ການສົນທະນາໃໝ່ຈະປາກົດເປັນໄອຄອນ ຫຼື ຟອງແບບລອຍ. ແຕະເພື່ອເປີດຟອງ. ລາກເພື່ອຍ້າຍມັນ."</string>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index f71d650..791ddcd 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"sutraukti „<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>“"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"„<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>“ nustatymai"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Atsisakyti burbulo"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nerodyti pokalbio burbule"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Pokalbis naudojant burbulus"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Nauji pokalbiai rodomi kaip slankiosios piktogramos arba burbulai. Palieskite, kad atidarytumėte burbulą. Vilkite, kad perkeltumėte."</string>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index abadef7..8a86687 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"Sakļaut “<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>”"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Lietotnes <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> iestatījumi"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Nerādīt burbuli"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nerādīt sarunu burbuļos"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Tērzēšana, izmantojot burbuļus"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Jaunas sarunas tiek rādītas kā peldošas ikonas vai burbuļi. Pieskarieties, lai atvērtu burbuli. Velciet, lai to pārvietotu."</string>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index 0576fc0..3a6b2f0 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"собери <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Поставки за <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Отфрли балонче"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Не прикажувај го разговорот во балончиња"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Разговор во балончиња"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Новите разговори ќе се појавуваат како лебдечки икони или балончиња. Допрете за отворање на балончето. Повлечете за да го преместите."</string>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index 6e7ea08..26e4a46 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ചുരുക്കുക"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ക്രമീകരണം"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"ബബിൾ ഡിസ്മിസ് ചെയ്യൂ"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"സംഭാഷണം ബബിൾ ചെയ്യരുത്"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"ബബിളുകൾ ഉപയോഗിച്ച് ചാറ്റ് ചെയ്യുക"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"പുതിയ സംഭാഷണങ്ങൾ ഫ്ലോട്ടിംഗ് ഐക്കണുകളോ ബബിളുകളോ ആയി ദൃശ്യമാവുന്നു. ബബിൾ തുറക്കാൻ ടാപ്പ് ചെയ്യൂ. ഇത് നീക്കാൻ വലിച്ചിടുക."</string>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index d69ec05..505a4ad 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>-г хураах"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>-н тохиргоо"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Бөмбөлгийг хаах"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Харилцан яриаг бүү бөмбөлөг болго"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Бөмбөлөг ашиглан чатлаарай"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Шинэ харилцан яриа нь хөвөгч дүрс тэмдэг эсвэл бөмбөлөг хэлбэрээр харагддаг. Бөмбөлгийг нээхийн тулд товшино уу. Түүнийг зөөхийн тулд чирнэ үү."</string>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index 33ba1c2..cc35f11 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> कोलॅप्स करा"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> सेटिंग्ज"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"बबल डिसमिस करा"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"संभाषणाला बबल करू नका"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"बबल वापरून चॅट करा"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"नवीन संभाषणे फ्लोटिंग आयकन किंवा बबल म्हणून दिसतात. बबल उघडण्यासाठी टॅप करा. हे हलवण्यासाठी ड्रॅग करा."</string>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index e024e4b..61d6614 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"kuncupkan <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Tetapan <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Ketepikan gelembung"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Jangan jadikan perbualan dalam bentuk gelembung"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Bersembang menggunakan gelembung"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Perbualan baharu muncul sebagai ikon terapung atau gelembung. Ketik untuk membuka gelembung. Seret untuk mengalihkan gelembung tersebut."</string>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index bd680b4..7841e07 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ကို ချုံ့ရန်"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ဆက်တင်များ"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"ပူဖောင်းကွက် ပယ်ရန်"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"စကားဝိုင်းကို ပူဖောင်းကွက် မပြုလုပ်ပါနှင့်"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"ပူဖောင်းကွက် သုံး၍ ချတ်လုပ်ခြင်း"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"စကားဝိုင်းအသစ်များကို မျောနေသည့် သင်္ကေတများ သို့မဟုတ် ပူဖောင်းကွက်များအဖြစ် မြင်ရပါမည်။ ပူဖောင်းကွက်ကိုဖွင့်ရန် တို့ပါ။ ရွှေ့ရန် ၎င်းကို ဖိဆွဲပါ။"</string>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index 896d9fd..ea2ae1b 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"skjul <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>-innstillinger"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Lukk boblen"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ikke vis samtaler i bobler"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat med bobler"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Nye samtaler vises som flytende ikoner eller bobler. Trykk for å åpne en boble. Dra for å flytte den."</string>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index 113085e..a3bd5ee 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> कोल्याप्स गर्नुहोस्"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> का सेटिङहरू"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"बबल खारेज गर्नुहोस्"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"वार्तालाप बबलको रूपमा नदेखाउनुहोस्"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"बबलहरू प्रयोग गरी कुराकानी गर्नुहोस्"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"नयाँ वार्तालापहरू तैरने आइकन वा बबलका रूपमा देखिन्छन्। बबल खोल्न ट्याप गर्नुहोस्। बबल सार्न सो बबललाई ड्र्याग गर्नुहोस्।"</string>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index a9c06fb..ad2c60f 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> samenvouwen"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Instellingen voor <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Bubbel sluiten"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Gesprekken niet in bubbels tonen"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatten met bubbels"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Nieuwe gesprekken worden als zwevende iconen of bubbels getoond. Tik om een bubbel te openen. Sleep om een bubbel te verplaatsen."</string>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index a80cfc2..76f2715 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ସଙ୍କୁଚିତ କରନ୍ତୁ"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ସେଟିଂସ୍"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"ବବଲ୍ ଖାରଜ କରନ୍ତୁ"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"ବାର୍ତ୍ତାଳାପକୁ ବବଲ୍ କରନ୍ତୁ ନାହିଁ"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"ବବଲଗୁଡ଼ିକୁ ବ୍ୟବହାର କରି ଚାଟ୍ କରନ୍ତୁ"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"ନୂଆ ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ ଫ୍ଲୋଟିଂ ଆଇକନ୍ କିମ୍ବା ବବଲ୍ ଭାବେ ଦେଖାଯିବ। ବବଲ୍ ଖୋଲିବାକୁ ଟାପ୍ କରନ୍ତୁ। ଏହାକୁ ମୁଭ୍ କରିବାକୁ ଟାଣନ୍ତୁ।"</string>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index 7257161..cd7fd47 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ਨੂੰ ਸਮੇਟੋ"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ਸੈਟਿੰਗਾਂ"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"ਬਬਲ ਨੂੰ ਖਾਰਜ ਕਰੋ"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"ਗੱਲਬਾਤ \'ਤੇ ਬਬਲ ਨਾ ਲਾਓ"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"ਬਬਲ ਵਰਤਦੇ ਹੋਏ ਚੈਟ ਕਰੋ"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"ਨਵੀਆਂ ਗੱਲਾਂਬਾਤਾਂ ਫਲੋਟਿੰਗ ਪ੍ਰਤੀਕਾਂ ਜਾਂ ਬਬਲ ਦੇ ਰੂਪ ਵਿੱਚ ਦਿਸਦੀਆਂ ਹਨ। ਬਬਲ ਨੂੰ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ। ਇਸਨੂੰ ਲਿਜਾਣ ਲਈ ਘਸੀਟੋ।"</string>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index 7600db0..d33b6f1 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"zwiń dymek <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> – ustawienia"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Zamknij dymek"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nie wyświetlaj rozmowy jako dymka"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Czatuj, korzystając z dymków"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Nowe rozmowy będą wyświetlane jako pływające ikony lub dymki. Kliknij, by otworzyć dymek. Przeciągnij, by go przenieść."</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index 58c78f3..c7a00ff 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"fechar <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Configurações de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Dispensar balão"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Não criar balões de conversa"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Converse usando balões"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Novas conversas aparecerão como ícones flutuantes, ou balões. Toque para abrir o balão. Arraste para movê-lo."</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index f433413..d141447 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"reduzir <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Definições de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignorar balão"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Não apresentar a conversa em balões"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Converse no chat através de balões"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"As novas conversas aparecem como ícones flutuantes ou balões. Toque para abrir o balão. Arraste para o mover."</string>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index 58c78f3..c7a00ff 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"fechar <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Configurações de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Dispensar balão"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Não criar balões de conversa"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Converse usando balões"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Novas conversas aparecerão como ícones flutuantes, ou balões. Toque para abrir o balão. Arraste para movê-lo."</string>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index 077503a..9bc7660 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"restrânge <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Setări <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Închide balonul"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nu afișa conversația în balon"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat cu baloane"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Conversațiile noi apar ca pictograme flotante sau baloane. Atinge pentru a deschide balonul. Trage pentru a-l muta."</string>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index 5471027..044e3b02 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"Свернуть <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>: настройки"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Скрыть всплывающий чат"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Не показывать всплывающий чат для разговора"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Всплывающие чаты"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Новые разговоры будут появляться в виде плавающих значков, или всплывающих чатов. Чтобы открыть чат, нажмите на него, а чтобы переместить – перетащите."</string>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index 3f015f6..da2541e 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> හකුළන්න"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> සැකසීම්"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"බුබුලු ඉවත ලන්න"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"සංවාදය බුබුලු නොදමන්න"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"බුබුලු භාවිතයෙන් කතාබහ කරන්න"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"නව සංවාද පාවෙන අයිකන හෝ බුබුලු ලෙස දිස් වේ. බුබුල විවෘත කිරීමට තට්ටු කරන්න. එය ගෙන යාමට අදින්න."</string>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index fa376e7..394a4ca 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"zbaliť <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Nastavenia aplikácie <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Zavrieť bublinu"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nezobrazovať konverzáciu ako bublinu"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Čet pomocou bublín"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Nové konverzácie sa zobrazujú ako plávajúce ikony či bubliny. Bublinu otvoríte klepnutím. Premiestnite ju presunutím."</string>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index 8538668..a90c2c2 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"strnitev oblačka <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Nastavitve za <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Opusti oblaček"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Pogovora ne prikaži v oblačku"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Klepet z oblački"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Novi pogovori so prikazani kot lebdeče ikone ali oblački. Če želite odpreti oblaček, se ga dotaknite. Če ga želite premakniti, ga povlecite."</string>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index f77a43d..706e75f 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"palos <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Cilësimet e <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Hiqe flluskën"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Mos e vendos bisedën në flluskë"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Bisedo duke përdorur flluskat"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Bisedat e reja shfaqen si ikona pluskuese ose flluska. Trokit për të hapur flluskën. Zvarrit për ta zhvendosur."</string>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index af7686a..539a00a2 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"скупите облачић <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Подешавања за <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Одбаци облачић"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Не користи облачиће за конверзацију"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Ћаскајте у облачићима"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Нове конверзације се приказују као плутајуће иконе или облачићи. Додирните да бисте отворили облачић. Превуците да бисте га преместили."</string>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index 0d08d8d..549eb10 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"komprimera <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Inställningar för <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Stäng bubbla"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Visa inte konversationen i bubblor"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatta med bubblor"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Nya konversationer visas som flytande ikoner, så kallade bubblor. Tryck på bubblan om du vill öppna den. Dra den om du vill flytta den."</string>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index 448f6249..9c34690 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"kunja <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Mipangilio ya <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Ondoa kiputo"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Usiweke viputo kwenye mazungumzo"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Piga gumzo ukitumia viputo"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Mazungumzo mapya huonekena kama aikoni au viputo vinavyoelea. Gusa ili ufungue kiputo. Buruta ili ukisogeze."</string>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index 1268929..7e996f3 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ஐச் சுருக்கும்"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> அமைப்புகள்"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"குமிழை அகற்று"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"உரையாடலைக் குமிழாக்காதே"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"குமிழ்களைப் பயன்படுத்தி அரட்டையடியுங்கள்"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"புதிய உரையாடல்கள் மிதக்கும் ஐகான்களாகவோ குமிழ்களாகவோ தோன்றும். குமிழைத் திறக்க தட்டவும். நகர்த்த இழுக்கவும்."</string>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index 524e558..984cea8 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>‌ను కుదించండి"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> సెట్టింగ్‌లు"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"బబుల్‌ను విస్మరించు"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"సంభాషణను బబుల్ చేయవద్దు"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"బబుల్స్‌ను ఉపయోగించి చాట్ చేయండి"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"కొత్త సంభాషణలు తేలియాడే చిహ్నాలుగా లేదా బబుల్స్ లాగా కనిపిస్తాయి. బబుల్‌ని తెరవడానికి నొక్కండి. తరలించడానికి లాగండి."</string>
diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml
index 00a395f..3460b07 100644
--- a/libs/WindowManager/Shell/res/values-th/strings.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"ยุบ <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"การตั้งค่า <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"ปิดบับเบิล"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"ไม่ต้องแสดงการสนทนาเป็นบับเบิล"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"แชทโดยใช้บับเบิล"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"การสนทนาใหม่ๆ จะปรากฏเป็นไอคอนแบบลอยหรือบับเบิล แตะเพื่อเปิดบับเบิล ลากเพื่อย้ายที่"</string>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index 50a9211..dc30912 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"i-collapse ang <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Mga setting ng <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"I-dismiss ang bubble"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Huwag ipakita sa bubble ang mga pag-uusap"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Mag-chat gamit ang bubbles"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Lumalabas bilang mga nakalutang na icon o bubble ang mga bagong pag-uusap. I-tap para buksan ang bubble. I-drag para ilipat ito."</string>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index ddd4206..e9e2173 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"daralt: <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ayarları"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Baloncuğu kapat"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Görüşmeyi baloncuk olarak görüntüleme"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Baloncukları kullanarak sohbet edin"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Yeni görüşmeler kayan simgeler veya baloncuk olarak görünür. Açmak için baloncuğa dokunun. Baloncuğu taşımak için sürükleyin."</string>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index 1dcdfe6..e1b6e35 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"згорнути \"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>\""</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Налаштування параметра \"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>\""</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Закрити підказку"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Не показувати спливаючі чати для розмов"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Спливаючий чат"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Нові повідомлення чату з\'являються у вигляді спливаючих значків. Щоб відкрити чат, натисніть його, а щоб перемістити – перетягніть."</string>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index 26ece5c..0508e6d 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> کو سکیڑیں"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ترتیبات"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"بلبلہ برخاست کریں"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"گفتگو بلبلہ نہ کریں"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"بلبلے کے ذریعے چیٹ کریں"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"نئی گفتگوئیں فلوٹنگ آئیکن یا بلبلے کے طور پر ظاہر ہوں گی۔ بلبلہ کھولنے کے لیے تھپتھپائیں۔ اسے منتقل کرنے کے لیے گھسیٹیں۔"</string>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index 90b9a3f..5de3b7b 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>ni yopish"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> sozlamalari"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Bulutchani yopish"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Suhbatlar bulutchalar shaklida chiqmasin"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Bulutchalar yordamida subhatlashish"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Yangi xabarlar qalqib chiquvchi belgilar yoki bulutchalar kabi chiqadi. Xabarni ochish uchun bildirishnoma ustiga bosing. Xabarni qayta joylash uchun bildirishnomani suring."</string>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index 90471f9..9b2f898 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"thu gọn <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Cài đặt <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Đóng bong bóng"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Dừng sử dụng bong bóng cho cuộc trò chuyện"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Trò chuyện bằng bong bóng trò chuyện"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Các cuộc trò chuyện mới sẽ xuất hiện dưới dạng biểu tượng nổi hoặc bong bóng trò chuyện. Nhấn để mở bong bóng trò chuyện. Kéo để di chuyển bong bóng trò chuyện."</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index 0aa52ac..b45b76e 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"收起“<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>”"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>设置"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"关闭消息气泡"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"不以消息气泡形式显示对话"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"使用消息气泡聊天"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"新对话会以浮动图标或消息气泡形式显示。点按即可打开消息气泡。拖动即可移动消息气泡。"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index 8a5be6a..ae776b8 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"收埋<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"「<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>」設定"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"關閉小視窗氣泡"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"不要透過小視窗顯示對話"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"使用小視窗進行即時通訊"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"新對話會以浮動圖示 (小視窗) 顯示。輕按即可開啟小視窗。拖曳即可移動小視窗。"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index d1cc4bb..5bfc6b8 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"收合「<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>」"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"「<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>」設定"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"關閉對話框"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"不要以對話框形式顯示對話"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"透過對話框來聊天"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"新的對話會以浮動圖示或對話框形式顯示。輕觸即可開啟對話框,拖曳則可移動對話框。"</string>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index 6163a97..0598d62 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -73,6 +73,8 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"goqa <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> izilungiselelo"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"Cashisa ibhamuza"</string>
+    <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+    <skip />
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ungayibhamuzi ingxoxo"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Xoxa usebenzisa amabhamuza"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Izingxoxo ezintsha zivela njengezithonjana ezintantayo, noma amabhamuza. Thepha ukuze uvule ibhamuza. Hudula ukuze ulihambise."</string>
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/handles/RegionSamplingHelper.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/handles/RegionSamplingHelper.java
index b92b8ef..a06cf78 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/handles/RegionSamplingHelper.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/handles/RegionSamplingHelper.java
@@ -329,7 +329,7 @@
         /**
          * Get the sampled region of interest from the sampled view
          * @param sampledView The view that this helper is attached to for convenience
-         * @return the region to be sampled in sceen coordinates. Return {@code null} to avoid
+         * @return the region to be sampled in screen coordinates. Return {@code null} to avoid
          * sampling in this frame
          */
         Rect getSampledRegion(View sampledView);
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java
index cf39415..6c83d88 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java
@@ -29,7 +29,6 @@
 import android.graphics.drawable.Drawable;
 import android.util.TypedValue;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.window.TaskSnapshot;
 
 /**
@@ -75,7 +74,7 @@
 
         public PipColorOverlay(Context context) {
             mContext = context;
-            mLeash = new SurfaceControl.Builder(new SurfaceSession())
+            mLeash = new SurfaceControl.Builder()
                     .setCallsite(TAG)
                     .setName(LAYER_NAME)
                     .setColorLayer()
@@ -123,7 +122,7 @@
         public PipSnapshotOverlay(TaskSnapshot snapshot, Rect sourceRectHint) {
             mSnapshot = snapshot;
             mSourceRectHint = new Rect(sourceRectHint);
-            mLeash = new SurfaceControl.Builder(new SurfaceSession())
+            mLeash = new SurfaceControl.Builder()
                     .setCallsite(TAG)
                     .setName(LAYER_NAME)
                     .build();
@@ -183,7 +182,7 @@
 
             mBitmap = Bitmap.createBitmap(overlaySize, overlaySize, Bitmap.Config.ARGB_8888);
             prepareAppIconOverlay(appIcon);
-            mLeash = new SurfaceControl.Builder(new SurfaceSession())
+            mLeash = new SurfaceControl.Builder()
                     .setCallsite(TAG)
                     .setName(LAYER_NAME)
                     .build();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/AppToWebUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/AppToWebUtils.kt
new file mode 100644
index 0000000..05ce361
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/AppToWebUtils.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+@file:JvmName("AppToWebUtils")
+
+package com.android.wm.shell.apptoweb
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+
+private val browserIntent = Intent()
+    .setAction(Intent.ACTION_VIEW)
+    .addCategory(Intent.CATEGORY_BROWSABLE)
+    .setData(Uri.parse("http:"))
+
+/**
+ * Returns a boolean indicating whether a given package is a browser app.
+ */
+fun isBrowserApp(context: Context, packageName: String, userId: Int): Boolean {
+    browserIntent.setPackage(packageName)
+    val list = context.packageManager.queryIntentActivitiesAsUser(
+        browserIntent, PackageManager.MATCH_ALL, userId
+    )
+
+    list.forEach {
+        if (it.activityInfo != null && it.handleAllWebDataURI) {
+            return true
+        }
+    }
+    return false
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/AssistContentRequester.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/AssistContentRequester.kt
new file mode 100644
index 0000000..249185e
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/AssistContentRequester.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2024 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.apptoweb
+
+import android.app.ActivityTaskManager
+import android.app.IActivityTaskManager
+import android.app.IAssistDataReceiver
+import android.app.assist.AssistContent
+import android.content.Context
+import android.graphics.Bitmap
+import android.os.Bundle
+import android.os.RemoteException
+import android.util.Slog
+import java.lang.ref.WeakReference
+import java.util.Collections
+import java.util.WeakHashMap
+import java.util.concurrent.Executor
+
+/**
+ * Can be used to request the AssistContent from a provided task id, useful for getting the web uri
+ * if provided from the task.
+ */
+class AssistContentRequester(
+    context: Context,
+    private val callBackExecutor: Executor,
+    private val systemInteractionExecutor: Executor
+) {
+    interface Callback {
+        // Called when the [AssistContent] of the requested task is available.
+        fun onAssistContentAvailable(assistContent: AssistContent?)
+    }
+
+    private val activityTaskManager: IActivityTaskManager = ActivityTaskManager.getService()
+    private val attributionTag: String? = context.attributionTag
+    private val packageName: String = context.applicationContext.packageName
+
+    // If system loses the callback, our internal cache of original callback will also get cleared.
+    private val pendingCallbacks = Collections.synchronizedMap(WeakHashMap<Any, Callback>())
+
+    /**
+     * Request the [AssistContent] from the task with the provided id.
+     *
+     * @param taskId to query for the content.
+     * @param callback to call when the content is available, called on the main thread.
+     */
+    fun requestAssistContent(taskId: Int, callback: Callback) {
+        // ActivityTaskManager interaction here is synchronous, so call off the main thread.
+        systemInteractionExecutor.execute {
+            try {
+                val success = activityTaskManager.requestAssistDataForTask(
+                    AssistDataReceiver(callback, this),
+                    taskId,
+                    packageName,
+                    attributionTag,
+                    false /* fetchStructure */
+                )
+                if (!success) {
+                    executeOnMainExecutor { callback.onAssistContentAvailable(null) }
+                }
+            } catch (e: RemoteException) {
+                Slog.e(TAG, "Requesting assist content failed for task: $taskId", e)
+            }
+        }
+    }
+
+    private fun executeOnMainExecutor(callback: Runnable) {
+        callBackExecutor.execute(callback)
+    }
+
+    private class AssistDataReceiver(
+            callback: Callback,
+            parent: AssistContentRequester
+    ) : IAssistDataReceiver.Stub() {
+        // The AssistDataReceiver binder callback object is passed to a system server, that may
+        // keep hold of it for longer than the lifetime of the AssistContentRequester object,
+        // potentially causing a memory leak. In the callback passed to the system server, only
+        // keep a weak reference to the parent object and lookup its callback if it still exists.
+        private val parentRef: WeakReference<AssistContentRequester>
+        private val callbackKey = Any()
+
+        init {
+            parent.pendingCallbacks[callbackKey] = callback
+            parentRef = WeakReference(parent)
+        }
+
+        override fun onHandleAssistData(data: Bundle?) {
+            val content = data?.getParcelable(ASSIST_KEY_CONTENT, AssistContent::class.java)
+            if (content == null) {
+                Slog.d(TAG, "Received AssistData, but no AssistContent found")
+                return
+            }
+            val requester = parentRef.get()
+            if (requester != null) {
+                val callback = requester.pendingCallbacks[callbackKey]
+                if (callback != null) {
+                    requester.executeOnMainExecutor { callback.onAssistContentAvailable(content) }
+                } else {
+                    Slog.d(TAG, "Callback received after calling UI was disposed of")
+                }
+            } else {
+                Slog.d(TAG, "Callback received after Requester was collected")
+            }
+        }
+
+        override fun onHandleAssistScreenshot(screenshot: Bitmap) {}
+    }
+
+    companion object {
+        private const val TAG = "AssistContentRequester"
+        private const val ASSIST_KEY_CONTENT = "content"
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS
index bfe1306a..6207e5b0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS
@@ -1,6 +1,8 @@
 atsjenk@google.com
 jorgegil@google.com
 madym@google.com
+mattsziklay@google.com
+mdehaini@google.com
 pbdr@google.com
 tkachenkoi@google.com
 vaniadesmonda@google.com
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 7b3b207..1563994 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
@@ -982,7 +982,6 @@
         mShellBackAnimationRegistry.resetDefaultCrossActivity();
         cancelLatencyTracking();
         mReceivedNullNavigationInfo = false;
-        mBackTransitionHandler.mLastTrigger = triggerBack;
         if (mBackNavigationInfo != null) {
             mPreviousNavigationType = mBackNavigationInfo.getType();
             mBackNavigationInfo.onBackNavigationFinished(triggerBack);
@@ -1103,7 +1102,6 @@
                                     endLatencyTracking();
                                     if (!validateAnimationTargets(apps)) {
                                         Log.e(TAG, "Invalid animation targets!");
-                                        mBackTransitionHandler.consumeQueuedTransitionIfNeeded();
                                         return;
                                     }
                                     mBackAnimationFinishedCallback = finishedCallback;
@@ -1113,7 +1111,6 @@
                                         return;
                                     }
                                     kickStartAnimation();
-                                    mBackTransitionHandler.consumeQueuedTransitionIfNeeded();
                                 });
                     }
 
@@ -1121,7 +1118,6 @@
                     public void onAnimationCancelled() {
                         mShellExecutor.execute(
                                 () -> {
-                                    mBackTransitionHandler.consumeQueuedTransitionIfNeeded();
                                     if (!mShellBackAnimationRegistry.cancel(
                                             mBackNavigationInfo != null
                                                     ? mBackNavigationInfo.getType()
@@ -1160,8 +1156,6 @@
         boolean mCloseTransitionRequested;
         SurfaceControl.Transaction mFinishOpenTransaction;
         Transitions.TransitionFinishCallback mFinishOpenTransitionCallback;
-        QueuedTransition mQueuedTransition = null;
-        boolean mLastTrigger;
         // The Transition to make behindActivity become visible
         IBinder mPrepareOpenTransition;
         // The Transition to make behindActivity become invisible, if prepare open exist and
@@ -1178,13 +1172,6 @@
             }
         }
 
-        void consumeQueuedTransitionIfNeeded() {
-            if (mQueuedTransition != null) {
-                mQueuedTransition.consume();
-                mQueuedTransition = null;
-            }
-        }
-
         private void applyFinishOpenTransition() {
             mOpenTransitionInfo = null;
             mPrepareOpenTransition = null;
@@ -1215,7 +1202,9 @@
                 @NonNull SurfaceControl.Transaction st,
                 @NonNull SurfaceControl.Transaction ft,
                 @NonNull Transitions.TransitionFinishCallback finishCallback) {
-            if (info.getType() == WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION) {
+            final boolean isPrepareTransition =
+                    info.getType() == WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION;
+            if (isPrepareTransition) {
                 kickStartAnimation();
             }
             // Both mShellExecutor and Transitions#mMainExecutor are ShellMainThread, so we don't
@@ -1240,21 +1229,14 @@
             }
 
             if (mApps == null || mApps.length == 0) {
-                if (mBackNavigationInfo != null && mShellBackAnimationRegistry
-                        .isWaitingAnimation(mBackNavigationInfo.getType())) {
-                    // Waiting for animation? Queue update to wait for animation start.
-                    consumeQueuedTransitionIfNeeded();
-                    mQueuedTransition = new QueuedTransition(info, st, ft, finishCallback);
-                    return true;
-                } else if (mLastTrigger) {
-                    // animation was done, consume directly
+                if (mCloseTransitionRequested) {
+                    // animation never start, consume directly
                     applyAndFinish(st, ft, finishCallback);
                     return true;
-                } else {
-                    // animation was cancelled but transition haven't happen, we must handle it
-                    if (mClosePrepareTransition == null && mCurrentTracker.isFinished()) {
-                        createClosePrepareTransition();
-                    }
+                } else if (mClosePrepareTransition == null && isPrepareTransition) {
+                    // Gesture animation was cancelled before prepare transition ready, create the
+                    // the close prepare transition
+                    createClosePrepareTransition();
                 }
             }
 
@@ -1413,9 +1395,6 @@
                 if (mPrepareOpenTransition != null) {
                     applyFinishOpenTransition();
                 }
-                if (mQueuedTransition != null) {
-                    consumeQueuedTransitionIfNeeded();
-                }
                 return;
             }
             // Handle the commit transition if this handler is running the open transition.
@@ -1423,11 +1402,9 @@
             t.apply();
             if (mCloseTransitionRequested) {
                 if (mApps == null || mApps.length == 0) {
-                    if (mQueuedTransition == null) {
-                        // animation was done
-                        applyFinishOpenTransition();
-                        mCloseTransitionRequested = false;
-                    } // let queued transition finish.
+                    // animation was done
+                    applyFinishOpenTransition();
+                    mCloseTransitionRequested = false;
                 } else {
                     // we are animating, wait until animation finish
                     mOnAnimationFinishCallback = () -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 0c95934..169361a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -609,7 +609,8 @@
                             callback.onBubbleViewsReady(bubble);
                         }
                     },
-                    mMainExecutor);
+                    mMainExecutor,
+                    mBgExecutor);
             if (mInflateSynchronously) {
                 mInflationTaskLegacy.onPostExecute(mInflationTaskLegacy.doInBackground());
             } else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
index f32974e..68c4657 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
@@ -80,7 +80,10 @@
                 expandedViewManager,
                 positioner,
                 /* isOverflow= */ true,
-                /* bubbleTaskView= */ null
+                /* bubbleTaskView= */ null,
+                /* mainExecutor= */ null,
+                /* backgroundExecutor= */ null,
+                /* regionSamplingProvider= */ null
             )
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
index 5f8f0fd..0c0fd7b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
@@ -60,6 +60,9 @@
 
         /** Called when back is pressed on the task root. */
         void onBackPressed();
+
+        /** Called when task removal has started. */
+        void onTaskRemovalStarted();
     }
 
     private final Context mContext;
@@ -190,6 +193,7 @@
                 ((ViewGroup) mParentView).removeView(mTaskView);
                 mTaskView = null;
             }
+            mListener.onTaskRemovalStarted();
         }
 
         @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
index 13855f7..3982a23 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
@@ -38,6 +38,7 @@
 import android.util.Log;
 import android.util.PathParser;
 import android.view.LayoutInflater;
+import android.view.View;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.ColorUtils;
@@ -47,6 +48,7 @@
 import com.android.wm.shell.R;
 import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView;
 import com.android.wm.shell.bubbles.bar.BubbleBarLayerView;
+import com.android.wm.shell.shared.handles.RegionSamplingHelper;
 
 import java.lang.ref.WeakReference;
 import java.util.Objects;
@@ -222,7 +224,16 @@
                 ProtoLog.v(WM_SHELL_BUBBLES, "Task initializing bubble bar expanded view key=%s",
                         mBubble.getKey());
                 viewInfo.bubbleBarExpandedView.initialize(mExpandedViewManager.get(),
-                        mPositioner.get(), false /* isOverflow */, viewInfo.taskView);
+                        mPositioner.get(), false /* isOverflow */, viewInfo.taskView,
+                        mMainExecutor, mBgExecutor, new RegionSamplingProvider() {
+                            @Override
+                            public RegionSamplingHelper createHelper(View sampledView,
+                                    RegionSamplingHelper.SamplingCallback callback,
+                                    Executor backgroundExecutor, Executor mainExecutor) {
+                                return RegionSamplingProvider.super.createHelper(sampledView,
+                                        callback, backgroundExecutor, mainExecutor);
+                            }
+                        });
             }
         }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java
index 5cfebf8..1b7bb0d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java
@@ -38,6 +38,7 @@
 import android.util.Log;
 import android.util.PathParser;
 import android.view.LayoutInflater;
+import android.view.View;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.ColorUtils;
@@ -46,6 +47,7 @@
 import com.android.wm.shell.R;
 import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView;
 import com.android.wm.shell.bubbles.bar.BubbleBarLayerView;
+import com.android.wm.shell.shared.handles.RegionSamplingHelper;
 
 import java.lang.ref.WeakReference;
 import java.util.Objects;
@@ -85,6 +87,7 @@
     private boolean mSkipInflation;
     private Callback mCallback;
     private Executor mMainExecutor;
+    private Executor mBackgroundExecutor;
 
     /**
      * Creates a task to load information for the provided {@link Bubble}. Once all info
@@ -100,7 +103,8 @@
             BubbleIconFactory factory,
             boolean skipInflation,
             Callback c,
-            Executor mainExecutor) {
+            Executor mainExecutor,
+            Executor backgroundExecutor) {
         mBubble = b;
         mContext = new WeakReference<>(context);
         mExpandedViewManager = new WeakReference<>(expandedViewManager);
@@ -112,6 +116,7 @@
         mSkipInflation = skipInflation;
         mCallback = c;
         mMainExecutor = mainExecutor;
+        mBackgroundExecutor = backgroundExecutor;
     }
 
     @Override
@@ -123,7 +128,7 @@
         if (mLayerView.get() != null) {
             return BubbleViewInfo.populateForBubbleBar(mContext.get(), mExpandedViewManager.get(),
                     mTaskViewFactory.get(), mPositioner.get(), mLayerView.get(), mIconFactory,
-                    mBubble, mSkipInflation);
+                    mBubble, mSkipInflation, mMainExecutor, mBackgroundExecutor);
         } else {
             return BubbleViewInfo.populate(mContext.get(), mExpandedViewManager.get(),
                     mTaskViewFactory.get(), mPositioner.get(), mStackView.get(), mIconFactory,
@@ -188,7 +193,9 @@
                 BubbleBarLayerView layerView,
                 BubbleIconFactory iconFactory,
                 Bubble b,
-                boolean skipInflation) {
+                boolean skipInflation,
+                Executor mainExecutor,
+                Executor backgroundExecutor) {
             BubbleViewInfo info = new BubbleViewInfo();
 
             if (!skipInflation && !b.isInflated()) {
@@ -197,7 +204,16 @@
                 info.bubbleBarExpandedView = (BubbleBarExpandedView) inflater.inflate(
                         R.layout.bubble_bar_expanded_view, layerView, false /* attachToRoot */);
                 info.bubbleBarExpandedView.initialize(
-                        expandedViewManager, positioner, false /* isOverflow */, bubbleTaskView);
+                        expandedViewManager, positioner, false /* isOverflow */, bubbleTaskView,
+                        mainExecutor, backgroundExecutor, new RegionSamplingProvider() {
+                            @Override
+                            public RegionSamplingHelper createHelper(View sampledView,
+                                    RegionSamplingHelper.SamplingCallback callback,
+                                    Executor backgroundExecutor, Executor mainExecutor) {
+                                return RegionSamplingProvider.super.createHelper(sampledView,
+                                        callback, backgroundExecutor, mainExecutor);
+                            }
+                        });
             }
 
             if (!populateCommonInfo(info, c, b, iconFactory)) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/RegionSamplingProvider.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/RegionSamplingProvider.java
new file mode 100644
index 0000000..30f5c8fd
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/RegionSamplingProvider.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 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.bubbles;
+
+import android.view.View;
+
+import com.android.wm.shell.shared.handles.RegionSamplingHelper;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Wrapper to provide a {@link com.android.wm.shell.shared.handles.RegionSamplingHelper} to allow
+ * testing it.
+ */
+public interface RegionSamplingProvider {
+
+    /** Creates and returns the region sampling helper */
+    default RegionSamplingHelper createHelper(View sampledView,
+            RegionSamplingHelper.SamplingCallback callback,
+            Executor backgroundExecutor,
+            Executor mainExecutor) {
+        return new RegionSamplingHelper(sampledView,
+                callback, backgroundExecutor, mainExecutor);
+    }
+
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
index 565fde0..74c3748 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
@@ -253,6 +253,7 @@
             return;
         }
         setDragPivot(bbev);
+        bbev.setDragging(true);
         // Corner radius gets scaled, apply the reverse scale to ensure we have the desired radius
         final float cornerRadius = bbev.getDraggedCornerRadius() / EXPANDED_VIEW_DRAG_SCALE;
 
@@ -329,6 +330,7 @@
             public void onAnimationEnd(Animator animation) {
                 super.onAnimationEnd(animation);
                 bbev.resetPivot();
+                bbev.setDragging(false);
             }
         });
         startNewDragAnimation(animatorSet);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
index f90b2aa..ec235a5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
@@ -19,10 +19,7 @@
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Color;
 import android.graphics.Insets;
 import android.graphics.Outline;
 import android.graphics.Rect;
@@ -37,6 +34,7 @@
 import android.widget.FrameLayout;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
 
 import com.android.wm.shell.R;
 import com.android.wm.shell.bubbles.Bubble;
@@ -46,9 +44,12 @@
 import com.android.wm.shell.bubbles.BubbleTaskView;
 import com.android.wm.shell.bubbles.BubbleTaskViewHelper;
 import com.android.wm.shell.bubbles.Bubbles;
+import com.android.wm.shell.bubbles.RegionSamplingProvider;
 import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
+import com.android.wm.shell.shared.handles.RegionSamplingHelper;
 import com.android.wm.shell.taskview.TaskView;
 
+import java.util.concurrent.Executor;
 import java.util.function.Supplier;
 
 /** Expanded view of a bubble when it's part of the bubble bar. */
@@ -92,16 +93,35 @@
     private boolean mIsOverflow;
     private BubbleTaskViewHelper mBubbleTaskViewHelper;
     private BubbleBarMenuViewController mMenuViewController;
-    private @Nullable Supplier<Rect> mLayerBoundsSupplier;
-    private @Nullable Listener mListener;
+    @Nullable
+    private Supplier<Rect> mLayerBoundsSupplier;
+    @Nullable
+    private Listener mListener;
 
     private BubbleBarHandleView mHandleView;
-    private @Nullable TaskView mTaskView;
-    private @Nullable BubbleOverflowContainerView mOverflowView;
+    @Nullable
+    private TaskView mTaskView;
+    @Nullable
+    private BubbleOverflowContainerView mOverflowView;
 
+    /**
+     * The handle shown in the caption area is tinted based on the background color of the area.
+     * This can vary so we sample the caption region and update the handle color based on that.
+     * If we're showing the overflow, the helper and executors will be null.
+     */
+    @Nullable
+    private RegionSamplingHelper mRegionSamplingHelper;
+    @Nullable
+    private RegionSamplingProvider mRegionSamplingProvider;
+    @Nullable
+    private Executor mMainExecutor;
+    @Nullable
+    private Executor mBackgroundExecutor;
+    private final Rect mSampleRect = new Rect();
+    private final int[] mLoc = new int[2];
+
+    /** Height of the caption inset at the top of the TaskView */
     private int mCaptionHeight;
-
-    private int mBackgroundColor;
     /** Corner radius used when view is resting */
     private float mRestingCornerRadius = 0f;
     /** Corner radius applied while dragging */
@@ -116,6 +136,7 @@
      */
     private boolean mIsContentVisible = false;
     private boolean mIsAnimating;
+    private boolean mIsDragging;
 
     public BubbleBarExpandedView(Context context) {
         this(context, null);
@@ -154,21 +175,20 @@
         setOnTouchListener((v, event) -> true);
     }
 
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        // Hide manage menu when view disappears
-        mMenuViewController.hideMenu(false /* animated */);
-    }
-
     /** Initializes the view, must be called before doing anything else. */
     public void initialize(BubbleExpandedViewManager expandedViewManager,
             BubblePositioner positioner,
             boolean isOverflow,
-            @Nullable BubbleTaskView bubbleTaskView) {
+            @Nullable BubbleTaskView bubbleTaskView,
+            @Nullable Executor mainExecutor,
+            @Nullable Executor backgroundExecutor,
+            @Nullable RegionSamplingProvider regionSamplingProvider) {
         mManager = expandedViewManager;
         mPositioner = positioner;
         mIsOverflow = isOverflow;
+        mMainExecutor = mainExecutor;
+        mBackgroundExecutor = backgroundExecutor;
+        mRegionSamplingProvider = regionSamplingProvider;
 
         if (mIsOverflow) {
             mOverflowView = (BubbleOverflowContainerView) LayoutInflater.from(getContext()).inflate(
@@ -191,6 +211,7 @@
             mTaskView.setEnableSurfaceClipping(true);
             mTaskView.setCornerRadius(mCurrentCornerRadius);
             mTaskView.setVisibility(VISIBLE);
+            mTaskView.setCaptionInsets(Insets.of(0, mCaptionHeight, 0, 0));
 
             // Handle view needs to draw on top of task view.
             bringChildToFront(mHandleView);
@@ -245,32 +266,40 @@
         return mHandleView;
     }
 
-    // TODO (b/275087636): call this when theme/config changes
     /** Updates the view based on the current theme. */
     public void applyThemeAttrs() {
+        mCaptionHeight = getResources().getDimensionPixelSize(
+                R.dimen.bubble_bar_expanded_view_caption_height);
         mRestingCornerRadius = getResources().getDimensionPixelSize(
-                R.dimen.bubble_bar_expanded_view_corner_radius
-        );
+                R.dimen.bubble_bar_expanded_view_corner_radius);
         mDraggedCornerRadius = getResources().getDimensionPixelSize(
-                R.dimen.bubble_bar_expanded_view_corner_radius_dragged
-        );
+                R.dimen.bubble_bar_expanded_view_corner_radius_dragged);
 
         mCurrentCornerRadius = mRestingCornerRadius;
 
-        final TypedArray ta = mContext.obtainStyledAttributes(new int[]{
-                android.R.attr.colorBackgroundFloating});
-        mBackgroundColor = ta.getColor(0, Color.WHITE);
-        ta.recycle();
-        mCaptionHeight = getResources().getDimensionPixelSize(
-                R.dimen.bubble_bar_expanded_view_caption_height);
-
         if (mTaskView != null) {
             mTaskView.setCornerRadius(mCurrentCornerRadius);
-            updateHandleColor(true /* animated */);
+            mTaskView.setCaptionInsets(Insets.of(0, mCaptionHeight, 0, 0));
         }
     }
 
     @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        // Hide manage menu when view disappears
+        mMenuViewController.hideMenu(false /* animated */);
+        if (mRegionSamplingHelper != null) {
+            mRegionSamplingHelper.stopAndDestroy();
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        recreateRegionSamplingHelper();
+    }
+
+    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         if (mTaskView != null) {
@@ -284,16 +313,13 @@
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
         if (mTaskView != null) {
-            mTaskView.layout(l, t, r,
-                    t + mTaskView.getMeasuredHeight());
-            mTaskView.setCaptionInsets(Insets.of(0, mCaptionHeight, 0, 0));
+            mTaskView.layout(l, t, r, t + mTaskView.getMeasuredHeight());
         }
     }
 
     @Override
     public void onTaskCreated() {
         setContentVisibility(true);
-        updateHandleColor(false /* animated */);
         if (mListener != null) {
             mListener.onTaskCreated();
         }
@@ -305,11 +331,70 @@
     }
 
     @Override
+    public void onTaskRemovalStarted() {
+        if (mRegionSamplingHelper != null) {
+            mRegionSamplingHelper.stopAndDestroy();
+        }
+    }
+
+    @Override
     public void onBackPressed() {
         if (mListener == null) return;
         mListener.onBackPressed();
     }
 
+    /**
+     * Set whether this view is currently being dragged.
+     *
+     * When dragging, the handle is hidden and content shouldn't be sampled. When dragging has
+     * ended we should start again.
+     */
+    public void setDragging(boolean isDragging) {
+        if (isDragging != mIsDragging) {
+            mIsDragging = isDragging;
+            updateSamplingState();
+        }
+    }
+
+    /** Returns whether region sampling should be enabled, i.e. if task view content is visible. */
+    private boolean shouldSampleRegion() {
+        return mTaskView != null
+                && mTaskView.getTaskInfo() != null
+                && !mIsDragging
+                && !mIsAnimating
+                && mIsContentVisible;
+    }
+
+    /**
+     * Handles starting or stopping the region sampling helper based on
+     * {@link #shouldSampleRegion()}.
+     */
+    private void updateSamplingState() {
+        if (mRegionSamplingHelper == null) return;
+        boolean shouldSample = shouldSampleRegion();
+        if (shouldSample) {
+            mRegionSamplingHelper.start(getCaptionSampleRect());
+        } else {
+            mRegionSamplingHelper.stop();
+        }
+    }
+
+    /** Returns the current area of the caption bar, in screen coordinates. */
+    Rect getCaptionSampleRect() {
+        if (mTaskView == null) return null;
+        mTaskView.getLocationOnScreen(mLoc);
+        mSampleRect.set(mLoc[0], mLoc[1],
+                mLoc[0] + mTaskView.getWidth(),
+                mLoc[1] + mCaptionHeight);
+        return mSampleRect;
+    }
+
+    @VisibleForTesting
+    @Nullable
+    public RegionSamplingHelper getRegionSamplingHelper() {
+        return mRegionSamplingHelper;
+    }
+
     /** Cleans up the expanded view, should be called when the bubble is no longer active. */
     public void cleanUpExpandedState() {
         mMenuViewController.hideMenu(false /* animated */);
@@ -394,27 +479,14 @@
 
         if (!mIsAnimating) {
             mTaskView.setAlpha(visible ? 1f : 0f);
+            if (mRegionSamplingHelper != null) {
+                mRegionSamplingHelper.setWindowVisible(visible);
+            }
+            updateSamplingState();
         }
     }
 
     /**
-     * Updates the handle color based on the task view status bar or background color; if those
-     * are transparent it defaults to the background color pulled from system theme attributes.
-     */
-    private void updateHandleColor(boolean animated) {
-        if (mTaskView == null || mTaskView.getTaskInfo() == null) return;
-        int color = mBackgroundColor;
-        ActivityManager.TaskDescription taskDescription = mTaskView.getTaskInfo().taskDescription;
-        if (taskDescription.getStatusBarColor() != Color.TRANSPARENT) {
-            color = taskDescription.getStatusBarColor();
-        } else if (taskDescription.getBackgroundColor() != Color.TRANSPARENT) {
-            color = taskDescription.getBackgroundColor();
-        }
-        final boolean isRegionDark = Color.luminance(color) <= 0.5;
-        mHandleView.updateHandleColor(isRegionDark, animated);
-    }
-
-    /**
      * Sets the alpha of both this view and the task view.
      */
     public void setTaskViewAlpha(float alpha) {
@@ -442,6 +514,11 @@
      */
     public void setAnimating(boolean animating) {
         mIsAnimating = animating;
+        if (mIsAnimating) {
+            // Stop sampling while animating -- when animating is done setContentVisibility will
+            // re-trigger sampling if we're visible.
+            updateSamplingState();
+        }
         // If we're done animating, apply the correct visibility.
         if (!animating) {
             setContentVisibility(mIsContentVisible);
@@ -481,6 +558,37 @@
         }
     }
 
+    private void recreateRegionSamplingHelper() {
+        if (mRegionSamplingHelper != null) {
+            mRegionSamplingHelper.stopAndDestroy();
+        }
+        if (mMainExecutor == null || mBackgroundExecutor == null
+                || mRegionSamplingProvider == null) {
+            // Null when it's the overflow / don't need sampling then.
+            return;
+        }
+        mRegionSamplingHelper = mRegionSamplingProvider.createHelper(this,
+                new RegionSamplingHelper.SamplingCallback() {
+                    @Override
+                    public void onRegionDarknessChanged(boolean isRegionDark) {
+                        if (mHandleView != null) {
+                            mHandleView.updateHandleColor(isRegionDark,
+                                    true /* animated */);
+                        }
+                    }
+
+                    @Override
+                    public Rect getSampledRegion(View sampledView) {
+                        return getCaptionSampleRect();
+                    }
+
+                    @Override
+                    public boolean isSamplingEnabled() {
+                        return shouldSampleRegion();
+                    }
+                }, mMainExecutor, mBackgroundExecutor);
+    }
+
     private class HandleViewAccessibilityDelegate extends AccessibilityDelegate {
         @Override
         public void onInitializeAccessibilityNodeInfo(@NonNull View host,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
index c91567d..e781c07 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
@@ -42,7 +42,9 @@
 
     private final @ColorInt int mHandleLightColor;
     private final @ColorInt int mHandleDarkColor;
-    private @Nullable ObjectAnimator mColorChangeAnim;
+    private @ColorInt int mCurrentColor;
+    @Nullable
+    private ObjectAnimator mColorChangeAnim;
 
     public BubbleBarHandleView(Context context) {
         this(context, null /* attrs */);
@@ -88,13 +90,17 @@
      *
      * @param isRegionDark Whether the background behind the handle is dark, and thus the handle
      *                     should be light (and vice versa).
-     * @param animated      Whether to animate the change, or apply it immediately.
+     * @param animated     Whether to animate the change, or apply it immediately.
      */
     public void updateHandleColor(boolean isRegionDark, boolean animated) {
         int newColor = isRegionDark ? mHandleLightColor : mHandleDarkColor;
+        if (newColor == mCurrentColor) {
+            return;
+        }
         if (mColorChangeAnim != null) {
             mColorChangeAnim.cancel();
         }
+        mCurrentColor = newColor;
         if (animated) {
             mColorChangeAnim = ObjectAnimator.ofArgb(this, "backgroundColor", newColor);
             mColorChangeAnim.addListener(new AnimatorListenerAdapter() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
index 4b138e4..dd17e29 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
@@ -17,7 +17,6 @@
 package com.android.wm.shell.common;
 
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 
 /**
  * Helpers for handling surface.
@@ -25,16 +24,15 @@
 public class SurfaceUtils {
     /** Creates a dim layer above host surface. */
     public static SurfaceControl makeDimLayer(SurfaceControl.Transaction t, SurfaceControl host,
-            String name, SurfaceSession surfaceSession) {
-        final SurfaceControl dimLayer = makeColorLayer(host, name, surfaceSession);
+            String name) {
+        final SurfaceControl dimLayer = makeColorLayer(host, name);
         t.setLayer(dimLayer, Integer.MAX_VALUE).setColor(dimLayer, new float[]{0f, 0f, 0f});
         return dimLayer;
     }
 
     /** Creates a color layer for host surface. */
-    public static SurfaceControl makeColorLayer(SurfaceControl host, String name,
-            SurfaceSession surfaceSession) {
-        return new SurfaceControl.Builder(surfaceSession)
+    public static SurfaceControl makeColorLayer(SurfaceControl host, String name) {
+        return new SurfaceControl.Builder()
                 .setParent(host)
                 .setColorLayer()
                 .setName(name)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index ef33b38..3dc86de 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -42,7 +42,6 @@
 import android.view.ScrollCaptureResponse;
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
@@ -311,7 +310,7 @@
         @Override
         protected SurfaceControl getParentSurface(IWindow window,
                 WindowManager.LayoutParams attrs) {
-            SurfaceControl leash = new SurfaceControl.Builder(new SurfaceSession())
+            SurfaceControl leash = new SurfaceControl.Builder()
                   .setContainerLayer()
                   .setName("SystemWindowLeash")
                   .setHidden(false)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
index 7175e36..de3152a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -43,7 +43,6 @@
 import android.view.LayoutInflater;
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowlessWindowManager;
@@ -74,7 +73,6 @@
     private static final String GAP_BACKGROUND_SURFACE_NAME = "GapBackground";
 
     private final IconProvider mIconProvider;
-    private final SurfaceSession mSurfaceSession;
 
     private Drawable mIcon;
     private ImageView mVeilIconView;
@@ -103,17 +101,15 @@
     private int mOffsetY;
     private int mRunningAnimationCount = 0;
 
-    public SplitDecorManager(Configuration configuration, IconProvider iconProvider,
-            SurfaceSession surfaceSession) {
+    public SplitDecorManager(Configuration configuration, IconProvider iconProvider) {
         super(configuration, null /* rootSurface */, null /* hostInputToken */);
         mIconProvider = iconProvider;
-        mSurfaceSession = surfaceSession;
     }
 
     @Override
     protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
         // Can't set position for the ViewRootImpl SC directly. Create a leash to manipulate later.
-        final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+        final SurfaceControl.Builder builder = new SurfaceControl.Builder()
                 .setContainerLayer()
                 .setName(TAG)
                 .setHidden(true)
@@ -238,7 +234,7 @@
 
         if (mBackgroundLeash == null) {
             mBackgroundLeash = SurfaceUtils.makeColorLayer(mHostLeash,
-                    RESIZING_BACKGROUND_SURFACE_NAME, mSurfaceSession);
+                    RESIZING_BACKGROUND_SURFACE_NAME);
             t.setColor(mBackgroundLeash, getResizingBackgroundColor(resizingTask))
                     .setLayer(mBackgroundLeash, Integer.MAX_VALUE - 1);
         }
@@ -248,7 +244,7 @@
             final int left = isLandscape ? mOldMainBounds.width() : 0;
             final int top = isLandscape ? 0 : mOldMainBounds.height();
             mGapBackgroundLeash = SurfaceUtils.makeColorLayer(mHostLeash,
-                    GAP_BACKGROUND_SURFACE_NAME, mSurfaceSession);
+                    GAP_BACKGROUND_SURFACE_NAME);
             // Fill up another side bounds area.
             t.setColor(mGapBackgroundLeash, getResizingBackgroundColor(resizingTask))
                     .setLayer(mGapBackgroundLeash, Integer.MAX_VALUE - 2)
@@ -405,7 +401,7 @@
         if (mBackgroundLeash == null) {
             // Initialize background
             mBackgroundLeash = SurfaceUtils.makeColorLayer(mHostLeash,
-                    RESIZING_BACKGROUND_SURFACE_NAME, mSurfaceSession);
+                    RESIZING_BACKGROUND_SURFACE_NAME);
             t.setColor(mBackgroundLeash, getResizingBackgroundColor(resizingTask))
                     .setLayer(mBackgroundLeash, Integer.MAX_VALUE - 1);
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 46c1a43..c5f1974 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -36,7 +36,6 @@
 import android.view.LayoutInflater;
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
 import android.view.WindowManager;
 import android.view.WindowlessWindowManager;
 
@@ -98,7 +97,7 @@
     @Override
     protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
         // Can't set position for the ViewRootImpl SC directly. Create a leash to manipulate later.
-        final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+        final SurfaceControl.Builder builder = new SurfaceControl.Builder()
                 .setContainerLayer()
                 .setName(TAG)
                 .setHidden(true)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
index 0564c95..d2b4f1a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
@@ -38,7 +38,6 @@
 import android.view.IWindow;
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowlessWindowManager;
@@ -173,7 +172,7 @@
     @Override
     protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
         String className = getClass().getSimpleName();
-        final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+        final SurfaceControl.Builder builder = new SurfaceControl.Builder()
                 .setContainerLayer()
                 .setName(className + "Leash")
                 .setHidden(false)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt
index 831b331..abc26cf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt
@@ -24,7 +24,6 @@
 import android.view.IWindow
 import android.view.SurfaceControl
 import android.view.SurfaceControlViewHost
-import android.view.SurfaceSession
 import android.view.View
 import android.view.WindowManager
 import android.view.WindowlessWindowManager
@@ -106,7 +105,7 @@
         attrs: WindowManager.LayoutParams
     ): SurfaceControl? {
         val className = javaClass.simpleName
-        val builder = SurfaceControl.Builder(SurfaceSession())
+        val builder = SurfaceControl.Builder()
                 .setContainerLayer()
                 .setName(className + "Leash")
                 .setHidden(false)
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 02ecfd9..7054c17c 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
@@ -38,6 +38,7 @@
 import com.android.wm.shell.WindowManagerShellWrapper;
 import com.android.wm.shell.activityembedding.ActivityEmbeddingController;
 import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
+import com.android.wm.shell.apptoweb.AssistContentRequester;
 import com.android.wm.shell.bubbles.BubbleController;
 import com.android.wm.shell.bubbles.BubbleData;
 import com.android.wm.shell.bubbles.BubbleDataRepository;
@@ -240,6 +241,7 @@
             RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
             InteractionJankMonitor interactionJankMonitor,
             AppToWebGenericLinksParser genericLinksParser,
+            AssistContentRequester assistContentRequester,
             MultiInstanceHelper multiInstanceHelper,
             Optional<DesktopTasksLimiter> desktopTasksLimiter,
             Optional<DesktopActivityOrientationChangeHandler> desktopActivityOrientationHandler) {
@@ -263,6 +265,7 @@
                     rootTaskDisplayAreaOrganizer,
                     interactionJankMonitor,
                     genericLinksParser,
+                    assistContentRequester,
                     multiInstanceHelper,
                     desktopTasksLimiter,
                     desktopActivityOrientationHandler);
@@ -291,6 +294,15 @@
         return new AppToWebGenericLinksParser(context, mainExecutor);
     }
 
+    @Provides
+    static AssistContentRequester provideAssistContentRequester(
+            Context context,
+            @ShellMainThread ShellExecutor shellExecutor,
+            @ShellBackgroundThread ShellExecutor bgExecutor
+    ) {
+        return new AssistContentRequester(context, shellExecutor, bgExecutor);
+    }
+
     //
     // Freeform
     //
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java
index 71cc8df..422656c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java
@@ -38,7 +38,6 @@
 import android.view.LayoutInflater;
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowlessWindowManager;
@@ -105,7 +104,7 @@
 
     @Override
     protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
-        final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+        final SurfaceControl.Builder builder = new SurfaceControl.Builder()
                 .setColorLayer()
                 .setBufferSize(mDisplayBounds.width(), mDisplayBounds.height())
                 .setFormat(PixelFormat.RGB_888)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index 4df649c..f060158 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -497,13 +497,8 @@
             mCurrentValue = value;
         }
 
-        boolean shouldApplyCornerRadius() {
-            return !isOutPipDirection(mTransitionDirection);
-        }
-
         boolean shouldApplyShadowRadius() {
-            return !isOutPipDirection(mTransitionDirection)
-                    && !isRemovePipDirection(mTransitionDirection);
+            return !isRemovePipDirection(mTransitionDirection);
         }
 
         boolean inScaleTransition() {
@@ -556,7 +551,7 @@
                     final float alpha = getStartValue() * (1 - fraction) + getEndValue() * fraction;
                     setCurrentValue(alpha);
                     getSurfaceTransactionHelper().alpha(tx, leash, alpha)
-                            .round(tx, leash, shouldApplyCornerRadius())
+                            .round(tx, leash, true /* applyCornerRadius */)
                             .shadow(tx, leash, shouldApplyShadowRadius());
                     if (!handlePipTransaction(leash, tx, destinationBounds, alpha)) {
                         tx.apply();
@@ -572,7 +567,7 @@
                     getSurfaceTransactionHelper()
                             .resetScale(tx, leash, getDestinationBounds())
                             .crop(tx, leash, getDestinationBounds())
-                            .round(tx, leash, shouldApplyCornerRadius())
+                            .round(tx, leash, true /* applyCornerRadius */)
                             .shadow(tx, leash, shouldApplyShadowRadius());
                     tx.show(leash);
                     tx.apply();
@@ -686,13 +681,11 @@
                         getSurfaceTransactionHelper().scaleAndCrop(tx, leash,
                                 adjustedSourceRectHint, initialSourceValue, bounds, insets,
                                 isInPipDirection, fraction);
-                        if (shouldApplyCornerRadius()) {
-                            final Rect sourceBounds = new Rect(initialContainerRect);
-                            sourceBounds.inset(insets);
-                            getSurfaceTransactionHelper()
-                                    .round(tx, leash, sourceBounds, bounds)
-                                    .shadow(tx, leash, shouldApplyShadowRadius());
-                        }
+                        final Rect sourceBounds = new Rect(initialContainerRect);
+                        sourceBounds.inset(insets);
+                        getSurfaceTransactionHelper()
+                                .round(tx, leash, sourceBounds, bounds)
+                                .shadow(tx, leash, shouldApplyShadowRadius());
                     }
                     if (!handlePipTransaction(leash, tx, bounds, /* alpha= */ 1f)) {
                         tx.apply();
@@ -741,11 +734,9 @@
                             .rotateAndScaleWithCrop(tx, leash, initialContainerRect, bounds,
                                     insets, degree, x, y, isOutPipDirection,
                                     rotationDelta == ROTATION_270 /* clockwise */);
-                    if (shouldApplyCornerRadius()) {
-                        getSurfaceTransactionHelper()
-                                .round(tx, leash, sourceBounds, bounds)
-                                .shadow(tx, leash, shouldApplyShadowRadius());
-                    }
+                    getSurfaceTransactionHelper()
+                            .round(tx, leash, sourceBounds, bounds)
+                            .shadow(tx, leash, shouldApplyShadowRadius());
                     if (!handlePipTransaction(leash, tx, bounds, 1f /* alpha */)) {
                         tx.apply();
                     }
@@ -761,7 +752,7 @@
                 void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
                     getSurfaceTransactionHelper()
                             .alpha(tx, leash, 1f)
-                            .round(tx, leash, shouldApplyCornerRadius())
+                            .round(tx, leash, true /* applyCornerRadius */)
                             .shadow(tx, leash, shouldApplyShadowRadius());
                     tx.show(leash);
                     tx.apply();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
deleted file mode 100644
index 1dad413..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
+++ /dev/null
@@ -1,85 +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.wm.shell.splitscreen;
-
-import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN;
-
-import android.content.Context;
-import android.view.SurfaceSession;
-import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
-
-import com.android.internal.protolog.ProtoLog;
-import com.android.launcher3.icons.IconProvider;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.windowdecor.WindowDecorViewModel;
-
-import java.util.Optional;
-
-/**
- * Main stage for split-screen mode. When split-screen is active all standard activity types launch
- * on the main stage, except for task that are explicitly pinned to the {@link StageTaskListener}.
- * @see StageCoordinator
- */
-class MainStage extends StageTaskListener {
-    private boolean mIsActive = false;
-
-    MainStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
-            StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
-            SurfaceSession surfaceSession, IconProvider iconProvider,
-            Optional<WindowDecorViewModel> windowDecorViewModel) {
-        super(context, taskOrganizer, displayId, callbacks, syncQueue, surfaceSession,
-                iconProvider, windowDecorViewModel);
-    }
-
-    boolean isActive() {
-        return mIsActive;
-    }
-
-    void activate(WindowContainerTransaction wct, boolean includingTopTask) {
-        if (mIsActive) return;
-        ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "activate: main stage includingTopTask=%b",
-                includingTopTask);
-
-        if (includingTopTask) {
-            reparentTopTask(wct);
-        }
-
-        mIsActive = true;
-    }
-
-    void deactivate(WindowContainerTransaction wct) {
-        deactivate(wct, false /* toTop */);
-    }
-
-    void deactivate(WindowContainerTransaction wct, boolean toTop) {
-        if (!mIsActive) return;
-        ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "deactivate: main stage toTop=%b rootTaskInfo=%s",
-                toTop, mRootTaskInfo);
-        mIsActive = false;
-
-        if (mRootTaskInfo == null) return;
-        final WindowContainerToken rootToken = mRootTaskInfo.token;
-        wct.reparentTasks(
-                rootToken,
-                null /* newParent */,
-                null /* windowingModes */,
-                null /* activityTypes */,
-                toTop);
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index 526c1d4..b36b1f8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -44,7 +44,7 @@
     int STAGE_TYPE_UNDEFINED = -1;
     /**
      * The main stage type.
-     * @see MainStage
+     * @see StageTaskListener
      */
     int STAGE_TYPE_MAIN = 0;
 
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 7e165af..793e2aa 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
@@ -61,7 +61,6 @@
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.view.WindowManager;
 import android.widget.Toast;
 import android.window.RemoteTransition;
@@ -897,7 +896,7 @@
 
     private SurfaceControl reparentSplitTasksForAnimation(RemoteAnimationTarget[] apps,
             SurfaceControl.Transaction t, String callsite) {
-        final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+        final SurfaceControl.Builder builder = new SurfaceControl.Builder()
                 .setContainerLayer()
                 .setName("RecentsAnimationSplitTasks")
                 .setHidden(false)
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 f3959cc..dad0d4e 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
@@ -34,6 +34,7 @@
 import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
 
+import static com.android.wm.shell.Flags.enableFlexibleSplit;
 import static com.android.wm.shell.common.split.SplitLayout.PARALLAX_ALIGN_CENTER;
 import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition;
 import static com.android.wm.shell.common.split.SplitScreenUtils.splitFailureMessage;
@@ -103,7 +104,6 @@
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.view.WindowManager;
 import android.widget.Toast;
 import android.window.DisplayAreaInfo;
@@ -154,14 +154,12 @@
 import java.util.concurrent.Executor;
 
 /**
- * Coordinates the staging (visibility, sizing, ...) of the split-screen {@link MainStage} and
- * other stages.
+ * Coordinates the staging (visibility, sizing, ...) of the split-screen stages.
  * Some high-level rules:
  * - The {@link StageCoordinator} is only considered active if the other stages contain at
  * least one child task.
- * - The {@link MainStage} should only have children if the coordinator is active.
- * - The {@link SplitLayout} divider is only visible if both the {@link MainStage}
- * and other stages are visible.
+ * - The {@link SplitLayout} divider is only visible if multiple {@link StageTaskListener}s are
+ * visible
  * - Both stages are put under a single-top root task.
  * This rules are mostly implemented in {@link #onStageVisibilityChanged(StageListenerImpl)} and
  * {@link #onStageHasChildrenChanged(StageListenerImpl).}
@@ -172,9 +170,7 @@
 
     private static final String TAG = StageCoordinator.class.getSimpleName();
 
-    private final SurfaceSession mSurfaceSession = new SurfaceSession();
-
-    private final MainStage mMainStage;
+    private final StageTaskListener mMainStage;
     private final StageListenerImpl mMainStageListener = new StageListenerImpl();
     private final StageTaskListener mSideStage;
     private final StageListenerImpl mSideStageListener = new StageListenerImpl();
@@ -329,13 +325,12 @@
         taskOrganizer.createRootTask(displayId, WINDOWING_MODE_FULLSCREEN, this /* listener */);
 
         ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "Creating main/side root task");
-        mMainStage = new MainStage(
+        mMainStage = new StageTaskListener(
                 mContext,
                 mTaskOrganizer,
                 mDisplayId,
                 mMainStageListener,
                 mSyncQueue,
-                mSurfaceSession,
                 iconProvider,
                 mWindowDecorViewModel);
         mSideStage = new StageTaskListener(
@@ -344,7 +339,6 @@
                 mDisplayId,
                 mSideStageListener,
                 mSyncQueue,
-                mSurfaceSession,
                 iconProvider,
                 mWindowDecorViewModel);
         mDisplayController = displayController;
@@ -367,8 +361,9 @@
 
     @VisibleForTesting
     StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
-            ShellTaskOrganizer taskOrganizer, MainStage mainStage, StageTaskListener sideStage,
-            DisplayController displayController, DisplayImeController displayImeController,
+            ShellTaskOrganizer taskOrganizer, StageTaskListener mainStage,
+            StageTaskListener sideStage, DisplayController displayController,
+            DisplayImeController displayImeController,
             DisplayInsetsController displayInsetsController, SplitLayout splitLayout,
             Transitions transitions, TransactionPool transactionPool, ShellExecutor mainExecutor,
             Handler mainHandler, Optional<RecentTasksController> recentTasks,
@@ -420,6 +415,10 @@
         return mSideStageListener.mVisible && mMainStageListener.mVisible;
     }
 
+    private void activateSplit(WindowContainerTransaction wct, boolean includingTopTask) {
+        mMainStage.activate(wct, includingTopTask);
+    }
+
     public boolean isSplitActive() {
         return mMainStage.isActive();
     }
@@ -505,10 +504,10 @@
         ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "removeFromSideStage: task=%d", taskId);
         final WindowContainerTransaction wct = new WindowContainerTransaction();
 
-        /**
-         * {@link MainStage} will be deactivated in {@link #onStageHasChildrenChanged} if the
-         * other stages no longer have children.
-         */
+
+        // MainStage will be deactivated in onStageHasChildrenChanged() if the other stages
+        // no longer have children.
+
         final boolean result = mSideStage.removeTask(taskId,
                 isSplitActive() ? mMainStage.mRootTaskInfo.token : null,
                 wct);
@@ -805,7 +804,7 @@
         if (!isSplitActive()) {
             // 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 */);
+            activateSplit(wct, false /* reparentToTop */);
         }
         mSplitLayout.setDivideRatio(snapPosition);
         updateWindowBounds(mSplitLayout, wct);
@@ -872,7 +871,7 @@
         if (!isSplitActive()) {
             // 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 */);
+            activateSplit(wct, false /* reparentToTop */);
         }
 
         setSideStagePosition(splitPosition, wct);
@@ -1439,7 +1438,7 @@
             setSideStagePosition(startPosition, wct);
             mSideStage.addTask(taskInfo, wct);
         }
-        mMainStage.activate(wct, true /* includingTopTask */);
+        activateSplit(wct, true /* reparentToTop */);
         prepareSplitLayout(wct, resizeAnim);
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 4593553..d64c0a2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -39,7 +39,6 @@
 import android.util.SparseArray;
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
@@ -72,6 +71,10 @@
 public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
     private static final String TAG = StageTaskListener.class.getSimpleName();
 
+    // No current way to enforce this but if enableFlexibleSplit() is enabled, then only 1 of the
+    // stages should have this be set/being used
+    private boolean mIsActive;
+
     /** Callback interface for listening to changes in a split-screen stage. */
     public interface StageListenerCallbacks {
         void onRootTaskAppeared();
@@ -89,7 +92,6 @@
 
     private final Context mContext;
     private final StageListenerCallbacks mCallbacks;
-    private final SurfaceSession mSurfaceSession;
     private final SyncTransactionQueue mSyncQueue;
     private final IconProvider mIconProvider;
     private final Optional<WindowDecorViewModel> mWindowDecorViewModel;
@@ -104,12 +106,11 @@
 
     StageTaskListener(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
             StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
-            SurfaceSession surfaceSession, IconProvider iconProvider,
+            IconProvider iconProvider,
             Optional<WindowDecorViewModel> windowDecorViewModel) {
         mContext = context;
         mCallbacks = callbacks;
         mSyncQueue = syncQueue;
-        mSurfaceSession = surfaceSession;
         mIconProvider = iconProvider;
         mWindowDecorViewModel = windowDecorViewModel;
         taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this);
@@ -199,12 +200,11 @@
             mRootTaskInfo = taskInfo;
             mSplitDecorManager = new SplitDecorManager(
                     mRootTaskInfo.configuration,
-                    mIconProvider,
-                    mSurfaceSession);
+                    mIconProvider);
             mCallbacks.onRootTaskAppeared();
             sendStatusChanged();
             mSyncQueue.runInSync(t -> mDimLayer =
-                    SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer", mSurfaceSession));
+                    SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer"));
         } else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
             final int taskId = taskInfo.taskId;
             mChildrenLeashes.put(taskId, leash);
@@ -475,6 +475,44 @@
         });
     }
 
+    // ---------
+    // Previously only used in MainStage
+    boolean isActive() {
+        return mIsActive;
+    }
+
+    void activate(WindowContainerTransaction wct, boolean includingTopTask) {
+        if (mIsActive) return;
+        ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "activate: includingTopTask=%b",
+                includingTopTask);
+
+        if (includingTopTask) {
+            reparentTopTask(wct);
+        }
+
+        mIsActive = true;
+    }
+
+    void deactivate(WindowContainerTransaction wct) {
+        deactivate(wct, false /* toTop */);
+    }
+
+    void deactivate(WindowContainerTransaction wct, boolean toTop) {
+        if (!mIsActive) return;
+        ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "deactivate: toTop=%b rootTaskInfo=%s",
+                toTop, mRootTaskInfo);
+        mIsActive = false;
+
+        if (mRootTaskInfo == null) return;
+        final WindowContainerToken rootToken = mRootTaskInfo.token;
+        wct.reparentTasks(
+                rootToken,
+                null /* newParent */,
+                null /* windowingModes */,
+                null /* activityTypes */,
+                toTop);
+    }
+
     // --------
     // Previously only used in SideStage
     boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index fac3592..2e9b53e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -33,7 +33,6 @@
 import android.util.SparseArray;
 import android.view.IWindow;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.view.WindowManager;
 import android.view.WindowlessWindowManager;
 import android.window.SplashScreenView;
@@ -204,7 +203,7 @@
         @Override
         protected SurfaceControl getParentSurface(IWindow window,
                 WindowManager.LayoutParams attrs) {
-            final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+            final SurfaceControl.Builder builder = new SurfaceControl.Builder()
                     .setContainerLayer()
                     .setName("Windowless window")
                     .setHidden(false)
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 4fc6c44..ff4b981 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
@@ -92,7 +92,6 @@
 import android.util.ArrayMap;
 import android.view.Choreographer;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.view.WindowManager;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
@@ -134,8 +133,6 @@
     private final TransitionAnimation mTransitionAnimation;
     private final DevicePolicyManager mDevicePolicyManager;
 
-    private final SurfaceSession mSurfaceSession = new SurfaceSession();
-
     /** Keeps track of the currently-running animations associated with each transition. */
     private final ArrayMap<IBinder, ArrayList<Animator>> mAnimations = new ArrayMap<>();
 
@@ -705,7 +702,7 @@
             TransitionInfo.Change change, TransitionInfo info, int animHint,
             ArrayList<Animator> animations, Runnable onAnimFinish) {
         final int rootIdx = TransitionUtil.rootIndexFor(change, info);
-        final ScreenRotationAnimation anim = new ScreenRotationAnimation(mContext, mSurfaceSession,
+        final ScreenRotationAnimation anim = new ScreenRotationAnimation(mContext,
                 mTransactionPool, startTransaction, change, info.getRoot(rootIdx).getLeash(),
                 animHint);
         // The rotation animation may consist of 3 animations: fade-out screenshot, fade-in real
@@ -918,7 +915,7 @@
         }
 
         final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
-        final WindowThumbnail wt = WindowThumbnail.createAndAttach(mSurfaceSession,
+        final WindowThumbnail wt = WindowThumbnail.createAndAttach(
                 change.getLeash(), thumbnail, transaction);
         final Animation a =
                 mTransitionAnimation.createCrossProfileAppsThumbnailAnimationLocked(bounds);
@@ -943,7 +940,7 @@
             @NonNull Runnable finishCallback, TransitionInfo.Change change,
             TransitionInfo.AnimationOptions options, float cornerRadius) {
         final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
-        final WindowThumbnail wt = WindowThumbnail.createAndAttach(mSurfaceSession,
+        final WindowThumbnail wt = WindowThumbnail.createAndAttach(
                 change.getLeash(), options.getThumbnail(), transaction);
         final Rect bounds = change.getEndAbsBounds();
         final int orientation = mContext.getResources().getConfiguration().orientation;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
index 3d79a1c..c385f9a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
@@ -74,8 +74,12 @@
             final boolean isBackGesture = change.hasFlags(FLAG_BACK_GESTURE_ANIMATED);
             if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) {
                 if (Flags.migratePredictiveBackTransition()) {
-                    if (!isBackGesture && TransitionUtil.isOpenOrCloseMode(mode)) {
-                        notifyHomeVisibilityChanged(TransitionUtil.isOpeningType(mode));
+                    final boolean gestureToHomeTransition = isBackGesture
+                            && TransitionUtil.isClosingType(info.getType());
+                    if (gestureToHomeTransition
+                            || (!isBackGesture && TransitionUtil.isOpenOrCloseMode(mode))) {
+                        notifyHomeVisibilityChanged(gestureToHomeTransition
+                                || TransitionUtil.isOpeningType(mode));
                     }
                 } else {
                     if (TransitionUtil.isOpenOrCloseMode(mode) || isBackGesture) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
index 0bf9d36..5802e2c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
@@ -38,7 +38,6 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
-import android.view.SurfaceSession;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.window.ScreenCapture;
@@ -112,7 +111,7 @@
     /** Intensity of light/whiteness of the layout after rotation occurs. */
     private float mEndLuma;
 
-    ScreenRotationAnimation(Context context, SurfaceSession session, TransactionPool pool,
+    ScreenRotationAnimation(Context context, TransactionPool pool,
             Transaction t, TransitionInfo.Change change, SurfaceControl rootLeash, int animHint) {
         mContext = context;
         mTransactionPool = pool;
@@ -126,7 +125,7 @@
         mStartRotation = change.getStartRotation();
         mEndRotation = change.getEndRotation();
 
-        mAnimLeash = new SurfaceControl.Builder(session)
+        mAnimLeash = new SurfaceControl.Builder()
                 .setParent(rootLeash)
                 .setEffectLayer()
                 .setCallsite("ShellRotationAnimation")
@@ -153,7 +152,7 @@
                     return;
                 }
 
-                mScreenshotLayer = new SurfaceControl.Builder(session)
+                mScreenshotLayer = new SurfaceControl.Builder()
                         .setParent(mAnimLeash)
                         .setBLASTLayer()
                         .setSecure(screenshotBuffer.containsSecureLayers())
@@ -178,7 +177,7 @@
             t.setCrop(mSurfaceControl, new Rect(0, 0, mEndWidth, mEndHeight));
 
             if (!isCustomRotate()) {
-                mBackColorSurface = new SurfaceControl.Builder(session)
+                mBackColorSurface = new SurfaceControl.Builder()
                         .setParent(rootLeash)
                         .setColorLayer()
                         .setOpaque(true)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/WindowThumbnail.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/WindowThumbnail.java
index 2c668ed..341f2bc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/WindowThumbnail.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/WindowThumbnail.java
@@ -21,7 +21,6 @@
 import android.graphics.PixelFormat;
 import android.hardware.HardwareBuffer;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 
 /**
  * Represents a surface that is displayed over a transition surface.
@@ -33,10 +32,10 @@
     private WindowThumbnail() {}
 
     /** Create a thumbnail surface and attach it over a parent surface. */
-    static WindowThumbnail createAndAttach(SurfaceSession surfaceSession, SurfaceControl parent,
+    static WindowThumbnail createAndAttach(SurfaceControl parent,
             HardwareBuffer thumbnailHeader, SurfaceControl.Transaction t) {
         WindowThumbnail windowThumbnail = new WindowThumbnail();
-        windowThumbnail.mSurfaceControl = new SurfaceControl.Builder(surfaceSession)
+        windowThumbnail.mSurfaceControl = new SurfaceControl.Builder()
                 .setParent(parent)
                 .setName("WindowThumanil : " + parent.toString())
                 .setCallsite("WindowThumanil")
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index c88c1e2..7919068 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -90,6 +90,7 @@
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
+import com.android.wm.shell.apptoweb.AssistContentRequester;
 import com.android.wm.shell.common.DisplayChangeController;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayInsetsController;
@@ -182,6 +183,7 @@
     private final Region mExclusionRegion = Region.obtain();
     private boolean mInImmersiveMode;
     private final String mSysUIPackageName;
+    private final AssistContentRequester mAssistContentRequester;
 
     private final DisplayChangeController.OnDisplayChangingListener mOnDisplayChangingListener;
     private final ISystemGestureExclusionListener mGestureExclusionListener =
@@ -217,6 +219,7 @@
             RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
             InteractionJankMonitor interactionJankMonitor,
             AppToWebGenericLinksParser genericLinksParser,
+            AssistContentRequester assistContentRequester,
             MultiInstanceHelper multiInstanceHelper,
             Optional<DesktopTasksLimiter> desktopTasksLimiter,
             Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler
@@ -238,6 +241,7 @@
                 transitions,
                 desktopTasksController,
                 genericLinksParser,
+                assistContentRequester,
                 multiInstanceHelper,
                 new DesktopModeWindowDecoration.Factory(),
                 new InputMonitorFactory(),
@@ -267,6 +271,7 @@
             Transitions transitions,
             Optional<DesktopTasksController> desktopTasksController,
             AppToWebGenericLinksParser genericLinksParser,
+            AssistContentRequester assistContentRequester,
             MultiInstanceHelper multiInstanceHelper,
             DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
             InputMonitorFactory inputMonitorFactory,
@@ -304,6 +309,7 @@
         mInteractionJankMonitor = interactionJankMonitor;
         mDesktopTasksLimiter = desktopTasksLimiter;
         mActivityOrientationChangeHandler = activityOrientationChangeHandler;
+        mAssistContentRequester = assistContentRequester;
         mOnDisplayChangingListener = (displayId, fromRotation, toRotation, displayAreaInfo, t) -> {
             DesktopModeWindowDecoration decoration;
             RunningTaskInfo taskInfo;
@@ -626,7 +632,7 @@
             } else if (id == R.id.caption_handle || id == R.id.open_menu_button) {
                 if (!decoration.isHandleMenuActive()) {
                     moveTaskToFront(decoration.mTaskInfo);
-                    decoration.createHandleMenu(mSplitScreenController);
+                    decoration.createHandleMenu();
                 }
             } else if (id == R.id.maximize_window) {
                 // TODO(b/346441962): move click detection logic into the decor's
@@ -1270,6 +1276,7 @@
                         mSyncQueue,
                         mRootTaskDisplayAreaOrganizer,
                         mGenericLinksParser,
+                        mAssistContentRequester,
                         mMultiInstanceHelper);
         mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index aa43c8d..142be91 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -38,6 +38,7 @@
 import android.annotation.SuppressLint;
 import android.app.ActivityManager;
 import android.app.WindowConfiguration.WindowingMode;
+import android.app.assist.AssistContent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
@@ -75,6 +76,8 @@
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
+import com.android.wm.shell.apptoweb.AppToWebUtils;
+import com.android.wm.shell.apptoweb.AssistContentRequester;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.MultiInstanceHelper;
@@ -150,6 +153,7 @@
     private CharSequence mAppName;
     private CapturedLink mCapturedLink;
     private Uri mGenericLink;
+    private Uri mWebUri;
     private Consumer<Uri> mOpenInBrowserClickListener;
 
     private ExclusionRegionListener mExclusionRegionListener;
@@ -158,6 +162,7 @@
     private final MaximizeMenuFactory mMaximizeMenuFactory;
     private final HandleMenuFactory mHandleMenuFactory;
     private final AppToWebGenericLinksParser mGenericLinksParser;
+    private final AssistContentRequester mAssistContentRequester;
 
     // Hover state for the maximize menu and button. The menu will remain open as long as either of
     // these is true. See {@link #onMaximizeHoverStateChanged()}.
@@ -184,16 +189,16 @@
             SyncTransactionQueue syncQueue,
             RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
             AppToWebGenericLinksParser genericLinksParser,
+            AssistContentRequester assistContentRequester,
             MultiInstanceHelper multiInstanceHelper) {
         this (context, userContext, displayController, splitScreenController, taskOrganizer,
                 taskInfo, taskSurface, handler, bgExecutor, choreographer, syncQueue,
-                rootTaskDisplayAreaOrganizer, genericLinksParser, SurfaceControl.Builder::new,
-                SurfaceControl.Transaction::new,  WindowContainerTransaction::new,
-                SurfaceControl::new, new WindowManagerWrapper(
+                rootTaskDisplayAreaOrganizer, genericLinksParser, assistContentRequester,
+                SurfaceControl.Builder::new, SurfaceControl.Transaction::new,
+                WindowContainerTransaction::new, SurfaceControl::new, new WindowManagerWrapper(
                         context.getSystemService(WindowManager.class)),
-                new SurfaceControlViewHostFactory() {},
-                DefaultMaximizeMenuFactory.INSTANCE, DefaultHandleMenuFactory.INSTANCE,
-                multiInstanceHelper);
+                new SurfaceControlViewHostFactory() {}, DefaultMaximizeMenuFactory.INSTANCE,
+                DefaultHandleMenuFactory.INSTANCE, multiInstanceHelper);
     }
 
     DesktopModeWindowDecoration(
@@ -210,6 +215,7 @@
             SyncTransactionQueue syncQueue,
             RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
             AppToWebGenericLinksParser genericLinksParser,
+            AssistContentRequester assistContentRequester,
             Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
             Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
             Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
@@ -230,6 +236,7 @@
         mSyncQueue = syncQueue;
         mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
         mGenericLinksParser = genericLinksParser;
+        mAssistContentRequester = assistContentRequester;
         mMaximizeMenuFactory = maximizeMenuFactory;
         mHandleMenuFactory = handleMenuFactory;
         mMultiInstanceHelper = multiInstanceHelper;
@@ -478,10 +485,18 @@
 
     @Nullable
     private Uri getBrowserLink() {
+        // Do not show browser link in browser applications
+        final ComponentName baseActivity = mTaskInfo.baseActivity;
+        if (baseActivity != null && AppToWebUtils.isBrowserApp(mContext,
+                baseActivity.getPackageName(), mUserContext.getUserId())) {
+            return null;
+        }
         // If the captured link is available and has not expired, return the captured link.
         // Otherwise, return the generic link which is set to null if a generic link is unavailable.
         if (mCapturedLink != null && !mCapturedLink.mExpired) {
             return mCapturedLink.mUri;
+        } else if (mWebUri != null) {
+            return mWebUri;
         }
         return mGenericLink;
     }
@@ -987,18 +1002,32 @@
     }
 
     /**
-     * Create and display handle menu window.
+     * Updates app info and creates and displays handle menu window.
      */
-    void createHandleMenu(SplitScreenController splitScreenController) {
+    void createHandleMenu() {
+        // Requests assist content. When content is received, calls {@link #onAssistContentReceived}
+        // which sets app info and creates the handle menu.
+        mAssistContentRequester.requestAssistContent(
+                mTaskInfo.taskId, this::onAssistContentReceived);
+    }
+
+    /**
+     * Called when assist content is received. updates the saved links and creates the handle menu.
+     */
+    @VisibleForTesting
+    void onAssistContentReceived(@Nullable AssistContent assistContent) {
+        mWebUri = assistContent == null ? null : assistContent.getWebUri();
         loadAppInfoIfNeeded();
         updateGenericLink();
+
+        // Create and display handle menu
         mHandleMenu = mHandleMenuFactory.create(
                 this,
                 mWindowManagerWrapper,
                 mRelayoutParams.mLayoutResId,
                 mAppIconBitmap,
                 mAppName,
-                splitScreenController,
+                mSplitScreenController,
                 DesktopModeStatus.canEnterDesktopMode(mContext),
                 Flags.enableDesktopWindowingMultiInstanceFeatures()
                         && mMultiInstanceHelper
@@ -1012,6 +1041,7 @@
         mHandleMenu.show(
                 /* onToDesktopClickListener= */ () -> {
                     mOnToDesktopClickListener.accept(APP_HANDLE_MENU_BUTTON);
+                    mOnToDesktopClickListener.accept(APP_HANDLE_MENU_BUTTON);
                     return Unit.INSTANCE;
                 },
                 /* onToFullscreenClickListener= */ mOnToFullscreenClickListener,
@@ -1333,6 +1363,7 @@
                 SyncTransactionQueue syncQueue,
                 RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
                 AppToWebGenericLinksParser genericLinksParser,
+                AssistContentRequester assistContentRequester,
                 MultiInstanceHelper multiInstanceHelper) {
             return new DesktopModeWindowDecoration(
                     context,
@@ -1348,6 +1379,7 @@
                     syncQueue,
                     rootTaskDisplayAreaOrganizer,
                     genericLinksParser,
+                    assistContentRequester,
                     multiInstanceHelper);
         }
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.kt
index fd6c4d8..fb81ed4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.kt
@@ -30,7 +30,6 @@
 import android.view.LayoutInflater
 import android.view.SurfaceControl
 import android.view.SurfaceControlViewHost
-import android.view.SurfaceSession
 import android.view.WindowManager
 import android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL
 import android.view.WindowlessWindowManager
@@ -66,7 +65,6 @@
     private val lightColors = dynamicLightColorScheme(context)
     private val darkColors = dynamicDarkColorScheme(context)
 
-    private val surfaceSession = SurfaceSession()
     private lateinit var iconView: ImageView
     private var iconSize = 0
 
@@ -126,7 +124,7 @@
                 .setCallsite("ResizeVeil#setupResizeVeil")
                 .build()
         backgroundSurface = surfaceControlBuilderFactory
-                .create("Resize veil background of Task=" + taskInfo.taskId, surfaceSession)
+                .create("Resize veil background of Task=" + taskInfo.taskId)
                 .setColorLayer()
                 .setHidden(true)
                 .setParent(veilSurface)
@@ -399,10 +397,6 @@
         fun create(name: String): SurfaceControl.Builder {
             return SurfaceControl.Builder().setName(name)
         }
-
-        fun create(name: String, surfaceSession: SurfaceSession): SurfaceControl.Builder {
-            return SurfaceControl.Builder(surfaceSession).setName(name)
-        }
     }
 
     companion object {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt
index dfa5ab4..9ef4b8c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt
@@ -29,6 +29,7 @@
 import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
 import android.view.WindowManager
 import android.widget.ImageButton
+import com.android.internal.policy.SystemBarUtils
 import com.android.window.flags.Flags
 import com.android.wm.shell.R
 import com.android.wm.shell.shared.animation.Interpolators
@@ -74,7 +75,10 @@
     ) {
         captionHandle.imageTintList = ColorStateList.valueOf(getCaptionHandleBarColor(taskInfo))
         this.taskInfo = taskInfo
-        if (!isCaptionVisible && hasStatusBarInputLayer()) {
+        // If handle is not in status bar region(i.e., bottom stage in vertical split),
+        // do not create an input layer
+        if (position.y >= SystemBarUtils.getStatusBarHeight(context)) return
+        if (!isCaptionVisible && hasStatusBarInputLayer() ) {
             disposeStatusBarInputLayer()
             return
         }
@@ -120,7 +124,7 @@
                 inputManager.pilferPointers(v.viewRootImpl.inputToken)
             }
             captionHandle.dispatchTouchEvent(event)
-            true
+            return@setOnTouchListener true
         }
         windowManagerWrapper.updateViewLayout(view, lp)
     }
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
index ec1d4f7..7640cb1 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
@@ -195,6 +195,25 @@
                             .associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
             )
 
+        val CORNER_RESIZE_TO_MAXIMUM_SIZE =
+            FlickerConfigEntry(
+                scenarioId = ScenarioId("CORNER_RESIZE_TO_MAXIMUM_SIZE"),
+                extractor =
+                TaggedScenarioExtractorBuilder()
+                    .setTargetTag(CujType.CUJ_DESKTOP_MODE_RESIZE_WINDOW)
+                    .setTransitionMatcher(
+                        TaggedCujTransitionMatcher(associatedTransitionRequired = false)
+                    )
+                    .build(),
+                assertions =
+                AssertionTemplates.DESKTOP_MODE_APP_VISIBILITY_ASSERTIONS +
+                        listOf(
+                            AppLayerIncreasesInSize(DESKTOP_MODE_APP),
+                            AppWindowHasMaxDisplayHeight(DESKTOP_MODE_APP),
+                            AppWindowHasMaxDisplayWidth(DESKTOP_MODE_APP)
+                        ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+            )
+
         val SNAP_RESIZE_LEFT_WITH_BUTTON =
             FlickerConfigEntry(
                 scenarioId = ScenarioId("SNAP_RESIZE_LEFT_WITH_BUTTON"),
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizeLandscape.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizeLandscape.kt
new file mode 100644
index 0000000..0b98ba2
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizeLandscape.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 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.flicker
+
+import android.tools.Rotation
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.wm.shell.flicker.DesktopModeFlickerScenarios.Companion.CORNER_RESIZE_TO_MAXIMUM_SIZE
+import com.android.wm.shell.scenarios.ResizeAppWithCornerResize
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Resize app window using corner resize to the greatest possible height and width in
+ * landscape mode.
+ *
+ * Assert that the maximum window size constraint is maintained.
+ */
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class ResizeAppToMaximumWindowSizeLandscape : ResizeAppWithCornerResize(
+    rotation = Rotation.ROTATION_90
+) {
+    @ExpectedScenarios(["CORNER_RESIZE_TO_MAXIMUM_SIZE"])
+    @Test
+    override fun resizeAppWithCornerResizeToMaximumSize() =
+        super.resizeAppWithCornerResizeToMaximumSize()
+
+    companion object {
+        @JvmStatic
+        @FlickerConfigProvider
+        fun flickerConfigProvider(): FlickerConfig =
+            FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(CORNER_RESIZE_TO_MAXIMUM_SIZE)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizePortrait.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizePortrait.kt
new file mode 100644
index 0000000..b1c04d3
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizePortrait.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 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.flicker
+
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.wm.shell.flicker.DesktopModeFlickerScenarios.Companion.CORNER_RESIZE_TO_MAXIMUM_SIZE
+import com.android.wm.shell.scenarios.ResizeAppWithCornerResize
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Resize app window using corner resize to the greatest possible height and width in
+ * portrait mode.
+ *
+ * Assert that the maximum window size constraint is maintained.
+ */
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class ResizeAppToMaximumWindowSizePortrait : ResizeAppWithCornerResize() {
+    @ExpectedScenarios(["CORNER_RESIZE_TO_MAXIMUM_SIZE"])
+    @Test
+    override fun resizeAppWithCornerResizeToMaximumSize() =
+        super.resizeAppWithCornerResizeToMaximumSize()
+
+    companion object {
+        @JvmStatic
+        @FlickerConfigProvider
+        fun flickerConfigProvider(): FlickerConfig =
+            FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(CORNER_RESIZE_TO_MAXIMUM_SIZE)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/CloseAllAppsWithAppHeaderExitTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/CloseAllAppsWithAppHeaderExitTest.kt
new file mode 100644
index 0000000..a4dc52b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/CloseAllAppsWithAppHeaderExitTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.CloseAllAppsWithAppHeaderExit
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [CloseAllAppsWithAppHeaderExit]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class CloseAllAppsWithAppHeaderExitTest() : CloseAllAppsWithAppHeaderExit()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/EnterDesktopWithDragTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/EnterDesktopWithDragTest.kt
new file mode 100644
index 0000000..3d95f97
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/EnterDesktopWithDragTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.EnterDesktopWithDrag
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [EnterDesktopWithDrag]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class EnterDesktopWithDragTest : EnterDesktopWithDrag()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ExitDesktopWithDragToTopDragZoneTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ExitDesktopWithDragToTopDragZoneTest.kt
new file mode 100644
index 0000000..140c5ec
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ExitDesktopWithDragToTopDragZoneTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.ExitDesktopWithDragToTopDragZone
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [ExitDesktopWithDragToTopDragZone]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class ExitDesktopWithDragToTopDragZoneTest : ExitDesktopWithDragToTopDragZone()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/MaximizeAppWindowTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/MaximizeAppWindowTest.kt
new file mode 100644
index 0000000..3d3dcd0
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/MaximizeAppWindowTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.MaximizeAppWindow
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [MaximizeAppWindow]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class MaximizeAppWindowTest : MaximizeAppWindow()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/OpenAppsInDesktopModeTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/OpenAppsInDesktopModeTest.kt
new file mode 100644
index 0000000..263e89f6
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/OpenAppsInDesktopModeTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.OpenAppsInDesktopMode
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [OpenAppsInDesktopMode]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class OpenAppsInDesktopModeTest : OpenAppsInDesktopMode()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppCornerMultiWindowAndPipTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppCornerMultiWindowAndPipTest.kt
new file mode 100644
index 0000000..13f4775
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppCornerMultiWindowAndPipTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.ResizeAppCornerMultiWindowAndPip
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [ResizeAppCornerMultiWindowAndPip]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class ResizeAppCornerMultiWindowAndPipTest : ResizeAppCornerMultiWindowAndPip()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppCornerMultiWindowTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppCornerMultiWindowTest.kt
new file mode 100644
index 0000000..bc9bb41
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppCornerMultiWindowTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.ResizeAppCornerMultiWindow
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [ResizeAppCornerMultiWindow]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class ResizeAppCornerMultiWindowTest : ResizeAppCornerMultiWindow()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppWithCornerResizeTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppWithCornerResizeTest.kt
new file mode 100644
index 0000000..46168eb
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppWithCornerResizeTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.ResizeAppWithCornerResize
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [ResizeAppWithCornerResize]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class ResizeAppWithCornerResizeTest : ResizeAppWithCornerResize()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppWithEdgeResizeTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppWithEdgeResizeTest.kt
new file mode 100644
index 0000000..ee24200
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppWithEdgeResizeTest.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.server.wm.flicker.helpers.MotionEventHelper
+import com.android.wm.shell.scenarios.ResizeAppWithEdgeResize
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [ResizeAppWithEdgeResize]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class ResizeAppWithEdgeResizeTest :
+  ResizeAppWithEdgeResize(MotionEventHelper.InputMethod.TOUCHPAD)
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SnapResizeAppWindowWithButtonTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SnapResizeAppWindowWithButtonTest.kt
new file mode 100644
index 0000000..38e85c7
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SnapResizeAppWindowWithButtonTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.SnapResizeAppWindowWithButton
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [SnapResizeAppWindowWithButton]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class SnapResizeAppWindowWithButtonTest : SnapResizeAppWindowWithButton()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SnapResizeAppWindowWithDragTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SnapResizeAppWindowWithDragTest.kt
new file mode 100644
index 0000000..082a3fb
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SnapResizeAppWindowWithDragTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.SnapResizeAppWindowWithDrag
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [SnapResizeAppWindowWithDrag]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class SnapResizeAppWindowWithDragTest : SnapResizeAppWindowWithDrag()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SwitchToOverviewFromDesktopTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SwitchToOverviewFromDesktopTest.kt
new file mode 100644
index 0000000..fdd0d81
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SwitchToOverviewFromDesktopTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.SwitchToOverviewFromDesktop
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [SwitchToOverviewFromDesktop]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class SwitchToOverviewFromDesktopTest : SwitchToOverviewFromDesktop()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/CloseAllAppsWithAppHeaderExit.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/CloseAllAppsWithAppHeaderExit.kt
index e9056f3..351a700 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/CloseAllAppsWithAppHeaderExit.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/CloseAllAppsWithAppHeaderExit.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.scenarios
 
-import android.platform.test.annotations.Postsubmit
 import android.app.Instrumentation
 import android.tools.NavBar
 import android.tools.Rotation
@@ -33,15 +32,12 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class CloseAllAppsWithAppHeaderExit
-@JvmOverloads
+@Ignore("Base Test Class")
+abstract class CloseAllAppsWithAppHeaderExit
 constructor(val rotation: Rotation = Rotation.ROTATION_0) {
 
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindow.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindow.kt
index ca1dc1a..3f9927f 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindow.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindow.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.scenarios
 
-import android.platform.test.annotations.Postsubmit
 import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
 import com.android.server.wm.flicker.helpers.ImeAppHelper
 import com.android.server.wm.flicker.helpers.MailAppHelper
@@ -26,13 +25,11 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class DragAppWindowMultiWindow : DragAppWindowScenarioTestBase()
+@Ignore("Test Base Class")
+abstract class DragAppWindowMultiWindow : DragAppWindowScenarioTestBase()
 {
     private val imeAppHelper = ImeAppHelper(instrumentation)
     private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopWithDrag.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopWithDrag.kt
index f4d6414..967bd29 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopWithDrag.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopWithDrag.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.scenarios
 
-import android.platform.test.annotations.Postsubmit
 import android.tools.NavBar
 import android.tools.Rotation
 import android.tools.flicker.rules.ChangeDisplayOrientationRule
@@ -25,19 +24,16 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class EnterDesktopWithDrag
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class EnterDesktopWithDrag
 constructor(
     val rotation: Rotation = Rotation.ROTATION_0,
     isResizeable: Boolean = true,
-    isLandscapeApp: Boolean = true
+    isLandscapeApp: Boolean = true,
 ) : DesktopScenarioCustomAppTestBase(isResizeable, isLandscapeApp) {
 
     @Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ExitDesktopWithDragToTopDragZone.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ExitDesktopWithDragToTopDragZone.kt
index b616e53..824c448 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ExitDesktopWithDragToTopDragZone.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ExitDesktopWithDragToTopDragZone.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.scenarios
 
-import android.platform.test.annotations.Postsubmit
 import android.tools.NavBar
 import android.tools.Rotation
 import com.android.window.flags.Flags
@@ -24,19 +23,16 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class ExitDesktopWithDragToTopDragZone
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class ExitDesktopWithDragToTopDragZone
 constructor(
     val rotation: Rotation = Rotation.ROTATION_0,
     isResizeable: Boolean = true,
-    isLandscapeApp: Boolean = true
+    isLandscapeApp: Boolean = true,
 ) : DesktopScenarioCustomAppTestBase(isResizeable, isLandscapeApp) {
 
     @Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindow.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindow.kt
index 426f40b..a54d497 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindow.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindow.kt
@@ -17,7 +17,6 @@
 package com.android.wm.shell.scenarios
 
 import android.app.Instrumentation
-import android.platform.test.annotations.Postsubmit
 import android.tools.NavBar
 import android.tools.Rotation
 import android.tools.flicker.rules.ChangeDisplayOrientationRule
@@ -33,15 +32,12 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class MaximizeAppWindow
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class MaximizeAppWindow
 constructor(private val rotation: Rotation = Rotation.ROTATION_0, isResizable: Boolean = true) {
 
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/OpenAppsInDesktopMode.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/OpenAppsInDesktopMode.kt
index a5c794b..aad266f 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/OpenAppsInDesktopMode.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/OpenAppsInDesktopMode.kt
@@ -17,7 +17,6 @@
 package com.android.wm.shell.scenarios
 
 import android.app.Instrumentation
-import android.platform.test.annotations.Postsubmit
 import android.tools.flicker.rules.ChangeDisplayOrientationRule
 import android.tools.NavBar
 import android.tools.Rotation
@@ -36,14 +35,12 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class OpenAppsInDesktopMode(val rotation: Rotation = Rotation.ROTATION_0) {
+@Ignore("Test Base Class")
+abstract class OpenAppsInDesktopMode(val rotation: Rotation = Rotation.ROTATION_0) {
 
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
     private val tapl = LauncherInstrumentation()
@@ -83,4 +80,4 @@
         secondApp.exit(wmHelper)
         firstApp.exit(wmHelper)
     }
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt
index b6bca7a..bfee318 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.scenarios
 
-import android.platform.test.annotations.Postsubmit
 import android.app.Instrumentation
 import android.tools.NavBar
 import android.tools.Rotation
@@ -34,15 +33,12 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class ResizeAppCornerMultiWindow
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class ResizeAppCornerMultiWindow
 constructor(val rotation: Rotation = Rotation.ROTATION_0,
     val horizontalChange: Int = 50,
     val verticalChange: Int = -50) {
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt
index 285ea13..5b1b64e 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.scenarios
 
-import android.platform.test.annotations.Postsubmit
 import android.app.Instrumentation
 import android.tools.NavBar
 import android.tools.Rotation
@@ -35,15 +34,12 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class ResizeAppCornerMultiWindowAndPip
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class ResizeAppCornerMultiWindowAndPip
 constructor(val rotation: Rotation = Rotation.ROTATION_0,
     val horizontalChange: Int = 50,
     val verticalChange: Int = -50) {
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt
index 42940a9..bd25639 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.scenarios
 
-import android.platform.test.annotations.Postsubmit
 import android.app.Instrumentation
 import android.tools.NavBar
 import android.tools.Rotation
@@ -32,16 +31,12 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class ResizeAppWithCornerResize
-@JvmOverloads
-constructor(
+@Ignore("Test Base Class")
+abstract class ResizeAppWithCornerResize(
     val rotation: Rotation = Rotation.ROTATION_0,
     val horizontalChange: Int = 200,
     val verticalChange: Int = -200,
@@ -83,6 +78,25 @@
         )
     }
 
+    @Test
+    open fun resizeAppWithCornerResizeToMaximumSize() {
+        val maxResizeChange = 3000
+        testApp.cornerResize(
+            wmHelper,
+            device,
+            DesktopModeAppHelper.Corners.RIGHT_TOP,
+            maxResizeChange,
+            -maxResizeChange
+        )
+        testApp.cornerResize(
+            wmHelper,
+            device,
+            DesktopModeAppHelper.Corners.LEFT_BOTTOM,
+            -maxResizeChange,
+            maxResizeChange
+        )
+    }
+
     @After
     fun teardown() {
         testApp.exit(wmHelper)
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt
index d094967..6780238 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.scenarios
 
-import android.platform.test.annotations.Postsubmit
 import android.app.Instrumentation
 import android.tools.NavBar
 import android.tools.Rotation
@@ -32,15 +31,12 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class ResizeAppWithEdgeResize
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class ResizeAppWithEdgeResize
 constructor(
     val inputMethod: MotionEventHelper.InputMethod,
     val rotation: Rotation = Rotation.ROTATION_90
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithButton.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithButton.kt
index 33242db..2b40497 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithButton.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithButton.kt
@@ -17,7 +17,6 @@
 package com.android.wm.shell.scenarios
 
 import android.app.Instrumentation
-import android.platform.test.annotations.Postsubmit
 import android.tools.NavBar
 import android.tools.Rotation
 import android.tools.traces.parsers.WindowManagerStateHelper
@@ -32,15 +31,12 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class SnapResizeAppWindowWithButton
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class SnapResizeAppWindowWithButton
 constructor(private val toLeft: Boolean = true, isResizable: Boolean = true) {
 
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithDrag.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithDrag.kt
index 14eb779..b4bd7e1 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithDrag.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithDrag.kt
@@ -17,7 +17,6 @@
 package com.android.wm.shell.scenarios
 
 import android.app.Instrumentation
-import android.platform.test.annotations.Postsubmit
 import android.tools.NavBar
 import android.tools.Rotation
 import android.tools.traces.parsers.WindowManagerStateHelper
@@ -32,15 +31,12 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class SnapResizeAppWindowWithDrag
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class SnapResizeAppWindowWithDrag
 constructor(private val toLeft: Boolean = true, isResizable: Boolean = true) {
 
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
@@ -72,4 +68,4 @@
     fun teardown() {
         testApp.exit(wmHelper)
     }
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SwitchToOverviewFromDesktop.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SwitchToOverviewFromDesktop.kt
index 53e36e23..dad2eb6 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SwitchToOverviewFromDesktop.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SwitchToOverviewFromDesktop.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.scenarios
 
-import android.platform.test.annotations.Postsubmit
 import android.app.Instrumentation
 import android.tools.NavBar
 import android.tools.Rotation
@@ -31,20 +30,17 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
 
 /**
 * Base test for opening recent apps overview from desktop mode.
 *
 * Navigation mode can be passed as a constructor parameter, by default it is set to gesture navigation.
 */
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class SwitchToOverviewFromDesktop
-@JvmOverloads
+@Ignore("Base Test Class")
+abstract class SwitchToOverviewFromDesktop
 constructor(val navigationMode: NavBar = NavBar.MODE_GESTURAL) {
 
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index 413e495..e514dc3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -49,7 +49,6 @@
 import android.os.RemoteException;
 import android.util.SparseArray;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.window.ITaskOrganizer;
 import android.window.ITaskOrganizerController;
 import android.window.TaskAppearedInfo;
@@ -169,7 +168,7 @@
     public void testTaskLeashReleasedAfterVanished() throws RemoteException {
         assumeFalse(ENABLE_SHELL_TRANSITIONS);
         RunningTaskInfo taskInfo = createTaskInfo(/* taskId= */ 1, WINDOWING_MODE_MULTI_WINDOW);
-        SurfaceControl taskLeash = new SurfaceControl.Builder(new SurfaceSession())
+        SurfaceControl taskLeash = new SurfaceControl.Builder()
                 .setName("task").build();
         mOrganizer.registerOrganizer();
         mOrganizer.onTaskAppeared(taskInfo, taskLeash);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
deleted file mode 100644
index b1befc4..0000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
+++ /dev/null
@@ -1,78 +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.wm.shell.splitscreen;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.ActivityManager;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
-import android.window.WindowContainerTransaction;
-
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.launcher3.icons.IconProvider;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.ShellTestCase;
-import com.android.wm.shell.TestRunningTaskInfoBuilder;
-import com.android.wm.shell.common.SyncTransactionQueue;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.Optional;
-
-/** Tests for {@link MainStage} */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class MainStageTests extends ShellTestCase {
-    @Mock private ShellTaskOrganizer mTaskOrganizer;
-    @Mock private StageTaskListener.StageListenerCallbacks mCallbacks;
-    @Mock private SyncTransactionQueue mSyncQueue;
-    @Mock private ActivityManager.RunningTaskInfo mRootTaskInfo;
-    @Mock private SurfaceControl mRootLeash;
-    @Mock private IconProvider mIconProvider;
-    private WindowContainerTransaction mWct = new WindowContainerTransaction();
-    private SurfaceSession mSurfaceSession = new SurfaceSession();
-    private MainStage mMainStage;
-
-    @Before
-    @UiThreadTest
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
-        mMainStage = new MainStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks,
-                mSyncQueue, mSurfaceSession, mIconProvider, Optional.empty());
-        mMainStage.onTaskAppeared(mRootTaskInfo, mRootLeash);
-    }
-
-    @Test
-    public void testActiveDeactivate() {
-        mMainStage.activate(mWct, true /* reparent */);
-        assertThat(mMainStage.isActive()).isTrue();
-
-        mMainStage.deactivate(mWct);
-        assertThat(mMainStage.isActive()).isFalse();
-    }
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
index 4de2278..66dcef6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
@@ -24,7 +24,6 @@
 import android.graphics.Rect;
 import android.os.Handler;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.wm.shell.ShellTaskOrganizer;
@@ -74,10 +73,10 @@
         final SurfaceControl mRootLeash;
 
         TestStageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
-                ShellTaskOrganizer taskOrganizer, MainStage mainStage, StageTaskListener sideStage,
-                DisplayController displayController, DisplayImeController imeController,
-                DisplayInsetsController insetsController, SplitLayout splitLayout,
-                Transitions transitions, TransactionPool transactionPool,
+                ShellTaskOrganizer taskOrganizer, StageTaskListener mainStage,
+                StageTaskListener sideStage, DisplayController displayController,
+                DisplayImeController imeController, DisplayInsetsController insetsController,
+                SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool,
                 ShellExecutor mainExecutor, Handler mainHandler,
                 Optional<RecentTasksController> recentTasks,
                 LaunchAdjacentController launchAdjacentController,
@@ -89,7 +88,7 @@
 
             // Prepare root task for testing.
             mRootTask = new TestRunningTaskInfoBuilder().build();
-            mRootLeash = new SurfaceControl.Builder(new SurfaceSession()).setName("test").build();
+            mRootLeash = new SurfaceControl.Builder().setName("test").build();
             onTaskAppeared(mRootTask, mRootLeash);
         }
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index e167433..ce3944a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -53,7 +53,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.window.IRemoteTransition;
 import android.window.RemoteTransition;
 import android.window.TransitionInfo;
@@ -106,7 +105,6 @@
     @Mock private DisplayInsetsController mDisplayInsetsController;
     @Mock private TransactionPool mTransactionPool;
     @Mock private Transitions mTransitions;
-    @Mock private SurfaceSession mSurfaceSession;
     @Mock private IconProvider mIconProvider;
     @Mock private WindowDecorViewModel mWindowDecorViewModel;
     @Mock private ShellExecutor mMainExecutor;
@@ -116,7 +114,7 @@
     @Mock private SplitScreen.SplitInvocationListener mInvocationListener;
     private final TestShellExecutor mTestShellExecutor = new TestShellExecutor();
     private SplitLayout mSplitLayout;
-    private MainStage mMainStage;
+    private StageTaskListener mMainStage;
     private StageTaskListener mSideStage;
     private StageCoordinator mStageCoordinator;
     private SplitScreenTransitions mSplitScreenTransitions;
@@ -133,12 +131,12 @@
         doReturn(mockExecutor).when(mTransitions).getAnimExecutor();
         doReturn(mock(SurfaceControl.Transaction.class)).when(mTransactionPool).acquire();
         mSplitLayout = SplitTestUtils.createMockSplitLayout();
-        mMainStage = spy(new MainStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
-                StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession,
+        mMainStage = spy(new StageTaskListener(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
+                StageTaskListener.StageListenerCallbacks.class), mSyncQueue,
                 mIconProvider, Optional.of(mWindowDecorViewModel)));
         mMainStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
         mSideStage = spy(new StageTaskListener(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
-                StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession,
+                StageTaskListener.StageListenerCallbacks.class), mSyncQueue,
                 mIconProvider, Optional.of(mWindowDecorViewModel)));
         mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
         mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index c9e1414..a6c16c4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -50,7 +50,6 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.window.RemoteTransition;
 import android.window.WindowContainerTransaction;
 
@@ -97,7 +96,7 @@
     @Mock
     private SyncTransactionQueue mSyncQueue;
     @Mock
-    private MainStage mMainStage;
+    private StageTaskListener mMainStage;
     @Mock
     private StageTaskListener mSideStage;
     @Mock
@@ -119,7 +118,6 @@
     private final Rect mBounds2 = new Rect(5, 10, 15, 20);
     private final Rect mRootBounds = new Rect(0, 0, 45, 60);
 
-    private SurfaceSession mSurfaceSession = new SurfaceSession();
     private SurfaceControl mRootLeash;
     private SurfaceControl mDividerLeash;
     private ActivityManager.RunningTaskInfo mRootTask;
@@ -139,7 +137,7 @@
                 mDisplayInsetsController, mSplitLayout, mTransitions, mTransactionPool,
                 mMainExecutor, mMainHandler, Optional.empty(), mLaunchAdjacentController,
                 Optional.empty()));
-        mDividerLeash = new SurfaceControl.Builder(mSurfaceSession).setName("fakeDivider").build();
+        mDividerLeash = new SurfaceControl.Builder().setName("fakeDivider").build();
 
         when(mSplitLayout.getBounds1()).thenReturn(mBounds1);
         when(mSplitLayout.getBounds2()).thenReturn(mBounds2);
@@ -149,7 +147,7 @@
         when(mSplitLayout.getDividerLeash()).thenReturn(mDividerLeash);
 
         mRootTask = new TestRunningTaskInfoBuilder().build();
-        mRootLeash = new SurfaceControl.Builder(mSurfaceSession).setName("test").build();
+        mRootLeash = new SurfaceControl.Builder().setName("test").build();
         mStageCoordinator.onTaskAppeared(mRootTask, mRootLeash);
 
         mSideStage.mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
index acd612e..b7b7d0d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
@@ -32,7 +32,6 @@
 import android.app.ActivityManager;
 import android.os.SystemProperties;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.window.WindowContainerTransaction;
 
 import androidx.test.annotation.UiThreadTest;
@@ -82,7 +81,6 @@
     private WindowContainerTransaction mWct;
     @Captor
     private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor;
-    private SurfaceSession mSurfaceSession = new SurfaceSession();
     private SurfaceControl mSurfaceControl;
     private ActivityManager.RunningTaskInfo mRootTask;
     private StageTaskListener mStageTaskListener;
@@ -97,12 +95,11 @@
                 DEFAULT_DISPLAY,
                 mCallbacks,
                 mSyncQueue,
-                mSurfaceSession,
                 mIconProvider,
                 Optional.of(mWindowDecorViewModel));
         mRootTask = new TestRunningTaskInfoBuilder().build();
         mRootTask.parentTaskId = INVALID_TASK_ID;
-        mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession).setName("test").build();
+        mSurfaceControl = new SurfaceControl.Builder().setName("test").build();
         mStageTaskListener.onTaskAppeared(mRootTask, mSurfaceControl);
     }
 
@@ -199,4 +196,13 @@
         assertThat(mStageTaskListener.removeTask(task.taskId, null, mWct)).isTrue();
         verify(mWct).reparent(eq(task.token), isNull(), eq(false));
     }
+
+    @Test
+    public void testActiveDeactivate() {
+        mStageTaskListener.activate(mWct, true /* reparent */);
+        assertThat(mStageTaskListener.isActive()).isTrue();
+
+        mStageTaskListener.deactivate(mWct);
+        assertThat(mStageTaskListener.isActive()).isFalse();
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
index 1984885..17fd95b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
@@ -49,7 +49,6 @@
 import android.testing.TestableLooper;
 import android.view.SurfaceControl;
 import android.view.SurfaceHolder;
-import android.view.SurfaceSession;
 import android.view.ViewTreeObserver;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
@@ -95,7 +94,6 @@
     Looper mViewLooper;
     TestHandler mViewHandler;
 
-    SurfaceSession mSession;
     SurfaceControl mLeash;
 
     Context mContext;
@@ -106,7 +104,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mLeash = new SurfaceControl.Builder(mSession)
+        mLeash = new SurfaceControl.Builder()
                 .setName("test")
                 .build();
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
index f51a960..8f49de0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
@@ -20,6 +20,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
 
@@ -39,6 +40,7 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.view.SurfaceControl;
@@ -213,6 +215,35 @@
         verify(mListener, times(1)).onHomeVisibilityChanged(true);
     }
 
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_MIGRATE_PREDICTIVE_BACK_TRANSITION)
+    public void testHomeActivityWithBackGestureNotifiesHomeIsVisibleAfterClose()
+            throws RemoteException {
+        TransitionInfo info = mock(TransitionInfo.class);
+        TransitionInfo.Change change = mock(TransitionInfo.Change.class);
+        ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class);
+        when(change.getTaskInfo()).thenReturn(taskInfo);
+        when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change)));
+        when(info.getType()).thenReturn(TRANSIT_PREPARE_BACK_NAVIGATION);
+
+        when(change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)).thenReturn(true);
+        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_OPEN, true);
+
+        mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
+                info,
+                mock(SurfaceControl.Transaction.class),
+                mock(SurfaceControl.Transaction.class));
+        verify(mListener, times(0)).onHomeVisibilityChanged(anyBoolean());
+
+        when(info.getType()).thenReturn(TRANSIT_TO_BACK);
+        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_CHANGE, true);
+        mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
+                info,
+                mock(SurfaceControl.Transaction.class),
+                mock(SurfaceControl.Transaction.class));
+        verify(mListener, times(1)).onHomeVisibilityChanged(true);
+    }
+
     /**
      * Helper class to initialize variables for the rest.
      */
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index be0549b..3dd8a2b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -73,6 +73,7 @@
 import com.android.wm.shell.TestRunningTaskInfoBuilder
 import com.android.wm.shell.TestShellExecutor
 import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser
+import com.android.wm.shell.apptoweb.AssistContentRequester
 import com.android.wm.shell.common.DisplayChangeController
 import com.android.wm.shell.common.DisplayController
 import com.android.wm.shell.common.DisplayInsetsController
@@ -165,6 +166,7 @@
     @Mock private lateinit var mockInteractionJankMonitor: InteractionJankMonitor
     @Mock private lateinit var mockGenericLinksParser: AppToWebGenericLinksParser
     @Mock private lateinit var mockUserHandle: UserHandle
+    @Mock private lateinit var mockAssistContentRequester: AssistContentRequester
     @Mock private lateinit var mockToast: Toast
     private val bgExecutor = TestShellExecutor()
     @Mock private lateinit var mockMultiInstanceHelper: MultiInstanceHelper
@@ -218,6 +220,7 @@
                 mockTransitions,
                 Optional.of(mockDesktopTasksController),
                 mockGenericLinksParser,
+                mockAssistContentRequester,
                 mockMultiInstanceHelper,
                 mockDesktopModeWindowDecorFactory,
                 mockInputMonitorFactory,
@@ -1131,7 +1134,7 @@
         whenever(
             mockDesktopModeWindowDecorFactory.create(
                 any(), any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(),
-                any(), any(), any())
+                any(), any(), any(), any())
         ).thenReturn(decoration)
         decoration.mTaskInfo = task
         whenever(decoration.isFocused).thenReturn(task.isFocused)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 258c860..b9e542a0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -46,6 +46,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
+import android.app.assist.AssistContent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
@@ -88,6 +89,7 @@
 import com.android.wm.shell.TestRunningTaskInfoBuilder;
 import com.android.wm.shell.TestShellExecutor;
 import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
+import com.android.wm.shell.apptoweb.AssistContentRequester;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.MultiInstanceHelper;
 import com.android.wm.shell.common.ShellExecutor;
@@ -133,6 +135,7 @@
 
     private static final Uri TEST_URI1 = Uri.parse("https://www.google.com/");
     private static final Uri TEST_URI2 = Uri.parse("https://docs.google.com/");
+    private static final Uri TEST_URI3 = Uri.parse("https://slides.google.com/");
 
     @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
 
@@ -175,6 +178,8 @@
     @Mock
     private WindowManager mMockWindowManager;
     @Mock
+    private AssistContentRequester mMockAssistContentRequester;
+    @Mock
     private HandleMenu mMockHandleMenu;
     @Mock
     private HandleMenuFactory mMockHandleMenuFactory;
@@ -189,7 +194,8 @@
     private SurfaceControl.Transaction mMockTransaction;
     private StaticMockitoSession mMockitoSession;
     private TestableContext mTestableContext;
-    private ShellExecutor mBgExecutor = new TestShellExecutor();
+    private final ShellExecutor mBgExecutor = new TestShellExecutor();
+    private final AssistContent mAssistContent = new AssistContent();
 
     /** Set up run before test class. */
     @BeforeClass
@@ -673,10 +679,11 @@
     public void capturedLink_handleMenuBrowserLinkSetToCapturedLinkIfValid() {
         final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
         final DesktopModeWindowDecoration decor = createWindowDecoration(
-                taskInfo, TEST_URI1 /* captured link */, TEST_URI2 /* generic link */);
+                taskInfo, TEST_URI1 /* captured link */, TEST_URI2 /* web uri */,
+                TEST_URI3 /* generic link */);
 
         // Verify handle menu's browser link set as captured link
-        decor.createHandleMenu(mMockSplitScreenController);
+        createHandleMenu(decor);
         verifyHandleMenuCreated(TEST_URI1);
     }
 
@@ -685,7 +692,8 @@
     public void capturedLink_postsOnCapturedLinkExpiredRunnable() {
         final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
         final DesktopModeWindowDecoration decor = createWindowDecoration(
-                taskInfo, TEST_URI1 /* captured link */, null /* generic link */);
+                taskInfo, TEST_URI1 /* captured link */, null /* web uri */,
+                null /* generic link */);
         final ArgumentCaptor<Runnable> runnableArgument = ArgumentCaptor.forClass(Runnable.class);
 
         // Run runnable to set captured link to expired
@@ -694,7 +702,7 @@
 
         // Verify captured link is no longer valid by verifying link is not set as handle menu
         // browser link.
-        decor.createHandleMenu(mMockSplitScreenController);
+        createHandleMenu(decor);
         verifyHandleMenuCreated(null /* uri */);
     }
 
@@ -703,7 +711,8 @@
     public void capturedLink_capturedLinkNotResetToSameLink() {
         final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
         final DesktopModeWindowDecoration decor = createWindowDecoration(
-                taskInfo, TEST_URI1 /* captured link */, null /* generic link */);
+                taskInfo, TEST_URI1 /* captured link */, null /* web uri */,
+                null /* generic link */);
         final ArgumentCaptor<Runnable> runnableArgument = ArgumentCaptor.forClass(Runnable.class);
 
         // Run runnable to set captured link to expired
@@ -714,7 +723,7 @@
         decor.relayout(taskInfo);
 
         // Verify handle menu's browser link not set to captured link since link is expired
-        decor.createHandleMenu(mMockSplitScreenController);
+        createHandleMenu(decor);
         verifyHandleMenuCreated(null /* uri */);
     }
 
@@ -723,11 +732,12 @@
     public void capturedLink_capturedLinkStillUsedIfExpiredAfterHandleMenuCreation() {
         final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
         final DesktopModeWindowDecoration decor = createWindowDecoration(
-                taskInfo, TEST_URI1 /* captured link */, null /* generic link */);
+                taskInfo, TEST_URI1 /* captured link */, null /* web uri */,
+                null /* generic link */);
         final ArgumentCaptor<Runnable> runnableArgument = ArgumentCaptor.forClass(Runnable.class);
 
         // Create handle menu before link expires
-        decor.createHandleMenu(mMockSplitScreenController);
+        createHandleMenu(decor);
 
         // Run runnable to set captured link to expired
         verify(mMockHandler).postDelayed(runnableArgument.capture(), anyLong());
@@ -735,7 +745,7 @@
 
         // Verify handle menu's browser link is set to captured link since menu was opened before
         // captured link expired
-        decor.createHandleMenu(mMockSplitScreenController);
+        createHandleMenu(decor);
         verifyHandleMenuCreated(TEST_URI1);
     }
 
@@ -744,12 +754,13 @@
     public void capturedLink_capturedLinkExpiresAfterClick() {
         final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
         final DesktopModeWindowDecoration decor = createWindowDecoration(
-                taskInfo, TEST_URI1 /* captured link */, null /* generic link */);
+                taskInfo, TEST_URI1 /* captured link */, null /* web uri */,
+                null /* generic link */);
         final ArgumentCaptor<Function1<Uri, Unit>> openInBrowserCaptor =
                 ArgumentCaptor.forClass(Function1.class);
 
         // Simulate menu opening and clicking open in browser button
-        decor.createHandleMenu(mMockSplitScreenController);
+        createHandleMenu(decor);
         verify(mMockHandleMenu).show(
                 any(),
                 any(),
@@ -763,7 +774,7 @@
 
         // Verify handle menu's browser link not set to captured link since link not valid after
         // open in browser clicked
-        decor.createHandleMenu(mMockSplitScreenController);
+        createHandleMenu(decor);
         verifyHandleMenuCreated(null /* uri */);
     }
 
@@ -772,10 +783,11 @@
     public void capturedLink_openInBrowserListenerCalledOnClick() {
         final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
         final DesktopModeWindowDecoration decor = createWindowDecoration(
-                taskInfo, TEST_URI1 /* captured link */, null /* generic link */);
+                taskInfo, TEST_URI1 /* captured link */, null /* web uri */,
+                null /* generic link */);
         final ArgumentCaptor<Function1<Uri, Unit>> openInBrowserCaptor =
                 ArgumentCaptor.forClass(Function1.class);
-        decor.createHandleMenu(mMockSplitScreenController);
+        createHandleMenu(decor);
         verify(mMockHandleMenu).show(
                 any(),
                 any(),
@@ -793,24 +805,38 @@
 
     @Test
     @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_TO_WEB)
-    public void genericLink_genericLinkUsedWhenCapturedLinkUnavailable() {
+    public void webUriLink_webUriLinkUsedWhenCapturedLinkUnavailable() {
         final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
         final DesktopModeWindowDecoration decor = createWindowDecoration(
-                taskInfo, null /* captured link */, TEST_URI2 /* generic link */);
-
-        // Verify handle menu's browser link set as generic link no captured link is available
-        decor.createHandleMenu(mMockSplitScreenController);
+                taskInfo, null /* captured link */, TEST_URI2 /* web uri */,
+                TEST_URI3 /* generic link */);
+        // Verify handle menu's browser link set as web uri link when captured link is unavailable
+        createHandleMenu(decor);
         verifyHandleMenuCreated(TEST_URI2);
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_TO_WEB)
+    public void genericLink_genericLinkUsedWhenCapturedLinkAndWebUriUnavailable() {
+        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
+        final DesktopModeWindowDecoration decor = createWindowDecoration(
+                taskInfo, null /* captured link */, null /* web uri */,
+                TEST_URI3 /* generic link */);
+
+        // Verify handle menu's browser link set as generic link when captured link and web uri link
+        // are unavailable
+        createHandleMenu(decor);
+        verifyHandleMenuCreated(TEST_URI3);
+    }
+
+    @Test
     public void handleMenu_onCloseMenuClick_closesMenu() {
         final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
         final DesktopModeWindowDecoration decoration = createWindowDecoration(taskInfo,
                 true /* relayout */);
         final ArgumentCaptor<Function0<Unit>> closeClickListener =
                 ArgumentCaptor.forClass(Function0.class);
-        decoration.createHandleMenu(mMockSplitScreenController);
+        createHandleMenu(decoration);
         verify(mMockHandleMenu).show(
                 any(),
                 any(),
@@ -860,9 +886,10 @@
 
     private DesktopModeWindowDecoration createWindowDecoration(
             ActivityManager.RunningTaskInfo taskInfo, @Nullable Uri capturedLink,
-            @Nullable Uri genericLink) {
+            @Nullable Uri webUri, @Nullable Uri genericLink) {
         taskInfo.capturedLink = capturedLink;
         taskInfo.capturedLinkTimestamp = System.currentTimeMillis();
+        mAssistContent.setWebUri(webUri);
         final String genericLinkString = genericLink == null ? null : genericLink.toString();
         doReturn(genericLinkString).when(mMockGenericLinksParser).getGenericLink(any());
         // Relayout to set captured link
@@ -894,11 +921,10 @@
                 mContext, mMockDisplayController, mMockSplitScreenController,
                 mMockShellTaskOrganizer, taskInfo, mMockSurfaceControl, mMockHandler, mBgExecutor,
                 mMockChoreographer, mMockSyncQueue, mMockRootTaskDisplayAreaOrganizer,
-                mMockGenericLinksParser, SurfaceControl.Builder::new, mMockTransactionSupplier,
-                WindowContainerTransaction::new, SurfaceControl::new,
-                new WindowManagerWrapper(mMockWindowManager),
-                mMockSurfaceControlViewHostFactory, maximizeMenuFactory, mMockHandleMenuFactory,
-                mMockMultiInstanceHelper);
+                mMockGenericLinksParser, mMockAssistContentRequester, SurfaceControl.Builder::new,
+                mMockTransactionSupplier, WindowContainerTransaction::new, SurfaceControl::new,
+                new WindowManagerWrapper(mMockWindowManager), mMockSurfaceControlViewHostFactory,
+                maximizeMenuFactory, mMockHandleMenuFactory, mMockMultiInstanceHelper);
         windowDecor.setCaptionListeners(mMockTouchEventListener, mMockTouchEventListener,
                 mMockTouchEventListener, mMockTouchEventListener);
         windowDecor.setExclusionRegionListener(mMockExclusionRegionListener);
@@ -926,6 +952,13 @@
 
     }
 
+    private void createHandleMenu(@NonNull DesktopModeWindowDecoration decor) {
+        decor.createHandleMenu();
+        // Call DesktopModeWindowDecoration#onAssistContentReceived because decor waits to receive
+        // {@link AssistContent} before creating the menu
+        decor.onAssistContentReceived(mAssistContent);
+    }
+
     private static boolean hasNoInputChannelFeature(RelayoutParams params) {
         return (params.mInputFeatures & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL)
                 != 0;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt
index a07be79..e0d16aa 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt
@@ -97,7 +97,7 @@
             .thenReturn(spyResizeVeilSurfaceBuilder)
         doReturn(mockResizeVeilSurface).whenever(spyResizeVeilSurfaceBuilder).build()
         whenever(mockSurfaceControlBuilderFactory
-            .create(eq("Resize veil background of Task=" + taskInfo.taskId), any()))
+            .create(eq("Resize veil background of Task=" + taskInfo.taskId)))
             .thenReturn(spyBackgroundSurfaceBuilder)
         doReturn(mockBackgroundSurface).whenever(spyBackgroundSurfaceBuilder).build()
         whenever(mockSurfaceControlBuilderFactory
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index e618245..5955915 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -1420,18 +1420,20 @@
 Mutex AssetManager::SharedZip::gLock;
 DefaultKeyedVector<String8, wp<AssetManager::SharedZip> > AssetManager::SharedZip::gOpen;
 
-AssetManager::SharedZip::SharedZip(const String8& path, time_t modWhen)
-    : mPath(path), mZipFile(NULL), mModWhen(modWhen),
-      mResourceTableAsset(NULL), mResourceTable(NULL)
-{
-    if (kIsDebug) {
-        ALOGI("Creating SharedZip %p %s\n", this, mPath.c_str());
-    }
-    ALOGV("+++ opening zip '%s'\n", mPath.c_str());
-    mZipFile = ZipFileRO::open(mPath.c_str());
-    if (mZipFile == NULL) {
-        ALOGD("failed to open Zip archive '%s'\n", mPath.c_str());
-    }
+AssetManager::SharedZip::SharedZip(const String8& path, ModDate modWhen)
+    : mPath(path),
+      mZipFile(NULL),
+      mModWhen(modWhen),
+      mResourceTableAsset(NULL),
+      mResourceTable(NULL) {
+  if (kIsDebug) {
+    ALOGI("Creating SharedZip %p %s\n", this, mPath.c_str());
+  }
+  ALOGV("+++ opening zip '%s'\n", mPath.c_str());
+  mZipFile = ZipFileRO::open(mPath.c_str());
+  if (mZipFile == NULL) {
+    ALOGD("failed to open Zip archive '%s'\n", mPath.c_str());
+  }
 }
 
 AssetManager::SharedZip::SharedZip(int fd, const String8& path)
@@ -1453,7 +1455,7 @@
         bool createIfNotPresent)
 {
     AutoMutex _l(gLock);
-    time_t modWhen = getFileModDate(path.c_str());
+    auto modWhen = getFileModDate(path.c_str());
     sp<SharedZip> zip = gOpen.valueFor(path).promote();
     if (zip != NULL && zip->mModWhen == modWhen) {
         return zip;
@@ -1520,8 +1522,8 @@
 
 bool AssetManager::SharedZip::isUpToDate()
 {
-    time_t modWhen = getFileModDate(mPath.c_str());
-    return mModWhen == modWhen;
+  auto modWhen = getFileModDate(mPath.c_str());
+  return mModWhen == modWhen;
 }
 
 void AssetManager::SharedZip::addOverlay(const asset_path& ap)
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index ce0985b..376c881 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -280,21 +280,21 @@
         ~SharedZip();
 
     private:
-        SharedZip(const String8& path, time_t modWhen);
-        SharedZip(int fd, const String8& path);
-        SharedZip(); // <-- not implemented
+     SharedZip(const String8& path, ModDate modWhen);
+     SharedZip(int fd, const String8& path);
+     SharedZip();  // <-- not implemented
 
-        String8 mPath;
-        ZipFileRO* mZipFile;
-        time_t mModWhen;
+     String8 mPath;
+     ZipFileRO* mZipFile;
+     ModDate mModWhen;
 
-        Asset* mResourceTableAsset;
-        ResTable* mResourceTable;
+     Asset* mResourceTableAsset;
+     ResTable* mResourceTable;
 
-        Vector<asset_path> mOverlays;
+     Vector<asset_path> mOverlays;
 
-        static Mutex gLock;
-        static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
+     static Mutex gLock;
+     static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
     };
 
     /*
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index 64b1f0c..98f1aa8 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -25,8 +25,9 @@
 #include "android-base/macros.h"
 #include "android-base/unique_fd.h"
 #include "androidfw/ConfigDescription.h"
-#include "androidfw/StringPiece.h"
 #include "androidfw/ResourceTypes.h"
+#include "androidfw/StringPiece.h"
+#include "androidfw/misc.h"
 #include "utils/ByteOrder.h"
 
 namespace android {
@@ -202,7 +203,7 @@
   android::base::unique_fd idmap_fd_;
   std::string_view overlay_apk_path_;
   std::string_view target_apk_path_;
-  time_t idmap_last_mod_time_;
+  ModDate idmap_last_mod_time_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadedIdmap);
diff --git a/libs/androidfw/include/androidfw/misc.h b/libs/androidfw/include/androidfw/misc.h
index 077609d..09ae40c 100644
--- a/libs/androidfw/include/androidfw/misc.h
+++ b/libs/androidfw/include/androidfw/misc.h
@@ -13,14 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
-#include <sys/types.h>
+#include <time.h>
 
 //
 // Handy utility functions and portability code.
 //
-#ifndef _LIBS_ANDROID_FW_MISC_H
-#define _LIBS_ANDROID_FW_MISC_H
 
 namespace android {
 
@@ -41,15 +40,35 @@
 } FileType;
 /* get the file's type; follows symlinks */
 FileType getFileType(const char* fileName);
-/* get the file's modification date; returns -1 w/errno set on failure */
-time_t getFileModDate(const char* fileName);
+
+// MinGW doesn't support nanosecond resolution in stat() modification time, and given
+// that it only matters on the device it's ok to keep it at the second level there.
+#ifdef _WIN32
+using ModDate = time_t;
+inline constexpr ModDate kInvalidModDate = ModDate(-1);
+inline constexpr unsigned long long kModDateResolutionNs = 1ull * 1000 * 1000 * 1000;
+inline time_t toTimeT(ModDate m) {
+  return m;
+}
+#else
+using ModDate = timespec;
+inline constexpr ModDate kInvalidModDate = {-1, -1};
+inline constexpr unsigned long long kModDateResolutionNs = 1;
+inline time_t toTimeT(ModDate m) {
+  return m.tv_sec;
+}
+#endif
+
+/* get the file's modification date; returns kInvalidModDate w/errno set on failure */
+ModDate getFileModDate(const char* fileName);
 /* same, but also returns -1 if the file has already been deleted */
-time_t getFileModDate(int fd);
+ModDate getFileModDate(int fd);
 
 // Check if |path| or |fd| resides on a readonly filesystem.
 bool isReadonlyFilesystem(const char* path);
 bool isReadonlyFilesystem(int fd);
 
-}; // namespace android
+}  // namespace android
 
-#endif // _LIBS_ANDROID_FW_MISC_H
+// Whoever uses getFileModDate() will need this as well
+bool operator==(const timespec& l, const timespec& r);
diff --git a/libs/androidfw/misc.cpp b/libs/androidfw/misc.cpp
index 93dcaf5..9bdaf18a 100644
--- a/libs/androidfw/misc.cpp
+++ b/libs/androidfw/misc.cpp
@@ -28,11 +28,13 @@
 #include <sys/vfs.h>
 #endif  // __linux__
 
-#include <cstring>
-#include <cstdio>
 #include <errno.h>
 #include <sys/stat.h>
 
+#include <cstdio>
+#include <cstring>
+#include <tuple>
+
 namespace android {
 
 /*
@@ -73,27 +75,32 @@
     }
 }
 
-/*
- * Get a file's modification date.
- */
-time_t getFileModDate(const char* fileName) {
-    struct stat sb;
-    if (stat(fileName, &sb) < 0) {
-        return (time_t)-1;
-    }
-    return sb.st_mtime;
+static ModDate getModDate(const struct stat& st) {
+#ifdef _WIN32
+  return st.st_mtime;
+#else
+  return st.st_mtim;
+#endif
 }
 
-time_t getFileModDate(int fd) {
-    struct stat sb;
-    if (fstat(fd, &sb) < 0) {
-        return (time_t)-1;
-    }
-    if (sb.st_nlink <= 0) {
-        errno = ENOENT;
-        return (time_t)-1;
-    }
-    return sb.st_mtime;
+ModDate getFileModDate(const char* fileName) {
+  struct stat sb;
+  if (stat(fileName, &sb) < 0) {
+    return kInvalidModDate;
+  }
+  return getModDate(sb);
+}
+
+ModDate getFileModDate(int fd) {
+  struct stat sb;
+  if (fstat(fd, &sb) < 0) {
+    return kInvalidModDate;
+  }
+  if (sb.st_nlink <= 0) {
+    errno = ENOENT;
+    return kInvalidModDate;
+  }
+  return getModDate(sb);
 }
 
 #ifndef __linux__
@@ -124,4 +131,8 @@
 }
 #endif  // __linux__
 
-}; // namespace android
+}  // namespace android
+
+bool operator==(const timespec& l, const timespec& r) {
+  return std::tie(l.tv_sec, l.tv_nsec) == std::tie(r.tv_sec, l.tv_nsec);
+}
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index 60aa7d8..cb2e56f 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#include <chrono>
+#include <thread>
+
 #include "android-base/file.h"
 #include "androidfw/ApkAssets.h"
 #include "androidfw/AssetManager2.h"
@@ -27,6 +30,7 @@
 #include "data/overlayable/R.h"
 #include "data/system/R.h"
 
+using namespace std::chrono_literals;
 using ::testing::NotNull;
 
 namespace overlay = com::android::overlay;
@@ -218,10 +222,13 @@
 
   unlink(temp_file.path);
   ASSERT_FALSE(apk_assets->IsUpToDate());
-  sleep(2);
+
+  const auto sleep_duration =
+      std::chrono::nanoseconds(std::max(kModDateResolutionNs, 1'000'000ull));
+  std::this_thread::sleep_for(sleep_duration);
 
   base::WriteStringToFile("hello", temp_file.path);
-  sleep(2);
+  std::this_thread::sleep_for(sleep_duration);
 
   ASSERT_FALSE(apk_assets->IsUpToDate());
 }
diff --git a/libs/hostgraphics/Android.bp b/libs/hostgraphics/Android.bp
index 09232b6..a58493a 100644
--- a/libs/hostgraphics/Android.bp
+++ b/libs/hostgraphics/Android.bp
@@ -7,6 +7,17 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
+cc_library_headers {
+    name: "libhostgraphics_headers",
+    host_supported: true,
+    export_include_dirs: ["include"],
+    target: {
+        windows: {
+            enabled: true,
+        },
+    },
+}
+
 cc_library_host_static {
     name: "libhostgraphics",
 
@@ -30,12 +41,13 @@
     ],
 
     header_libs: [
+        "libhostgraphics_headers",
         "libnativebase_headers",
         "libnativedisplay_headers",
         "libnativewindow_headers",
     ],
 
-    export_include_dirs: ["."],
+    export_include_dirs: ["include"],
 
     target: {
         windows: {
diff --git a/libs/hostgraphics/gui/BufferItem.h b/libs/hostgraphics/include/gui/BufferItem.h
similarity index 100%
rename from libs/hostgraphics/gui/BufferItem.h
rename to libs/hostgraphics/include/gui/BufferItem.h
diff --git a/libs/hostgraphics/gui/BufferItemConsumer.h b/libs/hostgraphics/include/gui/BufferItemConsumer.h
similarity index 100%
rename from libs/hostgraphics/gui/BufferItemConsumer.h
rename to libs/hostgraphics/include/gui/BufferItemConsumer.h
diff --git a/libs/hostgraphics/gui/BufferQueue.h b/libs/hostgraphics/include/gui/BufferQueue.h
similarity index 100%
rename from libs/hostgraphics/gui/BufferQueue.h
rename to libs/hostgraphics/include/gui/BufferQueue.h
diff --git a/libs/hostgraphics/gui/ConsumerBase.h b/libs/hostgraphics/include/gui/ConsumerBase.h
similarity index 100%
rename from libs/hostgraphics/gui/ConsumerBase.h
rename to libs/hostgraphics/include/gui/ConsumerBase.h
diff --git a/libs/hostgraphics/gui/IGraphicBufferConsumer.h b/libs/hostgraphics/include/gui/IGraphicBufferConsumer.h
similarity index 100%
rename from libs/hostgraphics/gui/IGraphicBufferConsumer.h
rename to libs/hostgraphics/include/gui/IGraphicBufferConsumer.h
diff --git a/libs/hostgraphics/gui/IGraphicBufferProducer.h b/libs/hostgraphics/include/gui/IGraphicBufferProducer.h
similarity index 100%
rename from libs/hostgraphics/gui/IGraphicBufferProducer.h
rename to libs/hostgraphics/include/gui/IGraphicBufferProducer.h
diff --git a/libs/hostgraphics/gui/Surface.h b/libs/hostgraphics/include/gui/Surface.h
similarity index 100%
rename from libs/hostgraphics/gui/Surface.h
rename to libs/hostgraphics/include/gui/Surface.h
diff --git a/libs/hostgraphics/ui/Fence.h b/libs/hostgraphics/include/ui/Fence.h
similarity index 100%
rename from libs/hostgraphics/ui/Fence.h
rename to libs/hostgraphics/include/ui/Fence.h
diff --git a/libs/hostgraphics/ui/GraphicBuffer.h b/libs/hostgraphics/include/ui/GraphicBuffer.h
similarity index 100%
rename from libs/hostgraphics/ui/GraphicBuffer.h
rename to libs/hostgraphics/include/ui/GraphicBuffer.h
diff --git a/libs/hwui/FeatureFlags.h b/libs/hwui/FeatureFlags.h
index c1c30f5..c0cedf1 100644
--- a/libs/hwui/FeatureFlags.h
+++ b/libs/hwui/FeatureFlags.h
@@ -25,14 +25,6 @@
 
 namespace text_feature {
 
-inline bool fix_double_underline() {
-#ifdef __ANDROID__
-    return com_android_text_flags_fix_double_underline();
-#else
-    return true;
-#endif  // __ANDROID__
-}
-
 inline bool deprecate_ui_fonts() {
 #ifdef __ANDROID__
     return com_android_text_flags_deprecate_ui_fonts();
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index a2748b0..236c3736 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -318,6 +318,11 @@
     return has101012Support;
 }
 
+bool HardwareBitmapUploader::has10101010Support() {
+    static bool has1010110Support = checkSupport(AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM);
+    return has1010110Support;
+}
+
 bool HardwareBitmapUploader::hasAlpha8Support() {
     static bool hasAlpha8Support = checkSupport(AHARDWAREBUFFER_FORMAT_R8_UNORM);
     return hasAlpha8Support;
@@ -376,6 +381,19 @@
             }
             formatInfo.format = GL_RGBA;
             break;
+        case kRGBA_10x6_SkColorType:
+            formatInfo.isSupported = HardwareBitmapUploader::has10101010Support();
+            if (formatInfo.isSupported) {
+                formatInfo.type = 0;  // Not supported in GL
+                formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM;
+                formatInfo.vkFormat = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16;
+            } else {
+                formatInfo.type = GL_UNSIGNED_BYTE;
+                formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
+                formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
+            }
+            formatInfo.format = 0;  // Not supported in GL
+            break;
         case kAlpha_8_SkColorType:
             formatInfo.isSupported = HardwareBitmapUploader::hasAlpha8Support();
             if (formatInfo.isSupported) {
diff --git a/libs/hwui/HardwareBitmapUploader.h b/libs/hwui/HardwareBitmapUploader.h
index 00ee996..76cb80b 100644
--- a/libs/hwui/HardwareBitmapUploader.h
+++ b/libs/hwui/HardwareBitmapUploader.h
@@ -33,12 +33,14 @@
 #ifdef __ANDROID__
     static bool hasFP16Support();
     static bool has1010102Support();
+    static bool has10101010Support();
     static bool hasAlpha8Support();
 #else
     static bool hasFP16Support() {
         return true;
     }
     static bool has1010102Support() { return true; }
+    static bool has10101010Support() { return true; }
     static bool hasAlpha8Support() { return true; }
 #endif
 };
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 72e83af..9e825fb 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -841,9 +841,6 @@
     sk_sp<SkTextBlob> textBlob(builder.make());
 
     applyLooper(&paintCopy, [&](const SkPaint& p) { mCanvas->drawTextBlob(textBlob, 0, 0, p); });
-    if (!text_feature::fix_double_underline()) {
-        drawTextDecorations(x, y, totalAdvance, paintCopy);
-    }
 }
 
 void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index 80b6c03..5af4af2 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -110,28 +110,26 @@
     DrawTextFunctor f(layout, this, paint, x, y, layout.getAdvance());
     MinikinUtils::forFontRun(layout, &paint, f);
 
-    if (text_feature::fix_double_underline()) {
-        Paint copied(paint);
-        PaintFilter* filter = getPaintFilter();
-        if (filter != nullptr) {
-            filter->filterFullPaint(&copied);
+    Paint copied(paint);
+    PaintFilter* filter = getPaintFilter();
+    if (filter != nullptr) {
+        filter->filterFullPaint(&copied);
+    }
+    const bool isUnderline = copied.isUnderline();
+    const bool isStrikeThru = copied.isStrikeThru();
+    if (isUnderline || isStrikeThru) {
+        const SkScalar left = x;
+        const SkScalar right = x + layout.getAdvance();
+        if (isUnderline) {
+            const SkScalar top = y + f.getUnderlinePosition();
+            drawStroke(left, right, top, f.getUnderlineThickness(), copied, this);
         }
-        const bool isUnderline = copied.isUnderline();
-        const bool isStrikeThru = copied.isStrikeThru();
-        if (isUnderline || isStrikeThru) {
-            const SkScalar left = x;
-            const SkScalar right = x + layout.getAdvance();
-            if (isUnderline) {
-                const SkScalar top = y + f.getUnderlinePosition();
-                drawStroke(left, right, top, f.getUnderlineThickness(), copied, this);
-            }
-            if (isStrikeThru) {
-                float textSize = paint.getSkFont().getSize();
-                const float position = textSize * Paint::kStdStrikeThru_Top;
-                const SkScalar thickness = textSize * Paint::kStdStrikeThru_Thickness;
-                const SkScalar top = y + position;
-                drawStroke(left, right, top, thickness, copied, this);
-            }
+        if (isStrikeThru) {
+            float textSize = paint.getSkFont().getSize();
+            const float position = textSize * Paint::kStdStrikeThru_Top;
+            const SkScalar thickness = textSize * Paint::kStdStrikeThru_Thickness;
+            const SkScalar top = y + position;
+            drawStroke(left, right, top, thickness, copied, this);
         }
     }
 }
diff --git a/libs/hwui/hwui/DrawTextFunctor.h b/libs/hwui/hwui/DrawTextFunctor.h
index 0efb2c8..d7bf201 100644
--- a/libs/hwui/hwui/DrawTextFunctor.h
+++ b/libs/hwui/hwui/DrawTextFunctor.h
@@ -142,32 +142,30 @@
             canvas->drawGlyphs(glyphFunc, glyphCount, paint, x, y, totalAdvance);
         }
 
-        if (text_feature::fix_double_underline()) {
-            // Extract underline position and thickness.
-            if (paint.isUnderline()) {
-                SkFontMetrics metrics;
-                paint.getSkFont().getMetrics(&metrics);
-                const float textSize = paint.getSkFont().getSize();
-                SkScalar position;
-                if (!metrics.hasUnderlinePosition(&position)) {
-                    position = textSize * Paint::kStdUnderline_Top;
-                }
-                SkScalar thickness;
-                if (!metrics.hasUnderlineThickness(&thickness)) {
-                    thickness = textSize * Paint::kStdUnderline_Thickness;
-                }
-
-                // If multiple fonts are used, use the most bottom position and most thick stroke
-                // width as the underline position. This follows the CSS standard:
-                // https://www.w3.org/TR/css-text-decor-3/#text-underline-position-property
-                // <quote>
-                // The exact position and thickness of line decorations is UA-defined in this level.
-                // However, for underlines and overlines the UA must use a single thickness and
-                // position on each line for the decorations deriving from a single decorating box.
-                // </quote>
-                underlinePosition = std::max(underlinePosition, position);
-                underlineThickness = std::max(underlineThickness, thickness);
+        // Extract underline position and thickness.
+        if (paint.isUnderline()) {
+            SkFontMetrics metrics;
+            paint.getSkFont().getMetrics(&metrics);
+            const float textSize = paint.getSkFont().getSize();
+            SkScalar position;
+            if (!metrics.hasUnderlinePosition(&position)) {
+                position = textSize * Paint::kStdUnderline_Top;
             }
+            SkScalar thickness;
+            if (!metrics.hasUnderlineThickness(&thickness)) {
+                thickness = textSize * Paint::kStdUnderline_Thickness;
+            }
+
+            // If multiple fonts are used, use the most bottom position and most thick stroke
+            // width as the underline position. This follows the CSS standard:
+            // https://www.w3.org/TR/css-text-decor-3/#text-underline-position-property
+            // <quote>
+            // The exact position and thickness of line decorations is UA-defined in this level.
+            // However, for underlines and overlines the UA must use a single thickness and
+            // position on each line for the decorations deriving from a single decorating box.
+            // </quote>
+            underlinePosition = std::max(underlinePosition, position);
+            underlineThickness = std::max(underlineThickness, thickness);
         }
     }
 
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index bce84ae..e302393 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -318,6 +318,15 @@
         tailPNext = &deviceFaultFeatures->pNext;
     }
 
+    if (grExtensions.hasExtension(VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME, 1)) {
+        VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT* formatFeatures =
+                new VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT;
+        formatFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT;
+        formatFeatures->pNext = nullptr;
+        *tailPNext = formatFeatures;
+        tailPNext = &formatFeatures->pNext;
+    }
+
     // query to get the physical device features
     mGetPhysicalDeviceFeatures2(mPhysicalDevice, &features);
     // this looks like it would slow things down,
diff --git a/libs/hwui/tests/unit/UnderlineTest.cpp b/libs/hwui/tests/unit/UnderlineTest.cpp
index c70a304..ecb06d8 100644
--- a/libs/hwui/tests/unit/UnderlineTest.cpp
+++ b/libs/hwui/tests/unit/UnderlineTest.cpp
@@ -109,9 +109,7 @@
     return f;
 }
 
-TEST_WITH_FLAGS(UnderlineTest, Roboto,
-                REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::text::flags,
-                                                    fix_double_underline))) {
+TEST(UnderlineTest, Roboto) {
     float textSize = 100;
     Paint paint;
     paint.getSkFont().setSize(textSize);
@@ -123,9 +121,7 @@
     EXPECT_EQ(ROBOTO_THICKNESS_EM * textSize, functor.getUnderlineThickness());
 }
 
-TEST_WITH_FLAGS(UnderlineTest, NotoCJK,
-                REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::text::flags,
-                                                    fix_double_underline))) {
+TEST(UnderlineTest, NotoCJK) {
     float textSize = 100;
     Paint paint;
     paint.getSkFont().setSize(textSize);
@@ -137,9 +133,7 @@
     EXPECT_EQ(NOTO_CJK_THICKNESS_EM * textSize, functor.getUnderlineThickness());
 }
 
-TEST_WITH_FLAGS(UnderlineTest, Mixture,
-                REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::text::flags,
-                                                    fix_double_underline))) {
+TEST(UnderlineTest, Mixture) {
     float textSize = 100;
     Paint paint;
     paint.getSkFont().setSize(textSize);
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index 6a560b3..9673c5f 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -49,6 +49,10 @@
             colorType = kRGBA_1010102_SkColorType;
             alphaType = kPremul_SkAlphaType;
             break;
+        case AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM:
+            colorType = kRGBA_10x6_SkColorType;
+            alphaType = kPremul_SkAlphaType;
+            break;
         case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
             colorType = kRGBA_F16_SkColorType;
             alphaType = kPremul_SkAlphaType;
@@ -86,6 +90,8 @@
             return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
         case kRGBA_1010102_SkColorType:
             return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
+        case kRGBA_10x6_SkColorType:
+            return AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM;
         case kARGB_4444_SkColorType:
             // Hardcoding the value from android::PixelFormat
             static constexpr uint64_t kRGBA4444 = 7;
@@ -108,6 +114,8 @@
             return kRGB_565_SkColorType;
         case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
             return kRGBA_1010102_SkColorType;
+        case AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM:
+            return kRGBA_10x6_SkColorType;
         case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
             return kRGBA_F16_SkColorType;
         case AHARDWAREBUFFER_FORMAT_R8_UNORM:
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 25fae76..4981cb3 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -6984,6 +6984,27 @@
     }
 
     /**
+     * Test method for enabling/disabling the volume controller long press timeout for checking
+     * whether two consecutive volume adjustments should be treated as a volume long press.
+     *
+     * <p>Used only for testing
+     *
+     * @param enable true for enabling, otherwise will be disabled (test mode)
+     *
+     * @hide
+     **/
+    @TestApi
+    @SuppressLint("UnflaggedApi") // @TestApi without associated feature.
+    @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)
+    public void setVolumeControllerLongPressTimeoutEnabled(boolean enable) {
+        try {
+            getService().setVolumeControllerLongPressTimeoutEnabled(enable);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Only useful for volume controllers.
      * @hide
      */
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index a96562d..9af6b28 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -303,6 +303,9 @@
 
     void notifyVolumeControllerVisible(in IVolumeController controller, boolean visible);
 
+    @EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED")
+    oneway void setVolumeControllerLongPressTimeoutEnabled(boolean enable);
+
     boolean isStreamAffectedByRingerMode(int streamType);
 
     boolean isStreamAffectedByMute(int streamType);
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
index cdf8f89..cc5ff81 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -82,6 +82,7 @@
     method public void onEnableStarted();
     method public void onHceEventReceived(int);
     method public void onNdefRead(@NonNull java.util.function.Consumer<java.lang.Boolean>);
+    method public void onReaderOptionChanged(boolean);
     method public void onRfDiscoveryStarted(boolean);
     method public void onRfFieldActivated(boolean);
     method public void onRoutingChanged();
diff --git a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
index b65c837..e49ef7e 100644
--- a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
+++ b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
@@ -37,6 +37,7 @@
    void onTagDispatch(in ResultReceiver isSkipped);
    void onRoutingChanged();
    void onHceEventReceived(int action);
+   void onReaderOptionChanged(boolean enabled);
    void onCardEmulationActivated(boolean isActivated);
    void onRfFieldActivated(boolean isActivated);
    void onRfDiscoveryStarted(boolean isDiscoveryStarted);
diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java
index 632f693..d51b704 100644
--- a/nfc/java/android/nfc/NfcOemExtension.java
+++ b/nfc/java/android/nfc/NfcOemExtension.java
@@ -223,6 +223,13 @@
         void onHceEventReceived(@HostCardEmulationAction int action);
 
         /**
+         * API to notify when reader option has been changed using
+         * {@link NfcAdapter#enableReaderOption(boolean)} by some app.
+         * @param enabled Flag indicating ReaderMode enabled/disabled
+         */
+        void onReaderOptionChanged(boolean enabled);
+
+        /**
         * Notifies NFC is activated in listen mode.
         * NFC Forum NCI-2.3 ch.5.2.6 specification
         *
@@ -488,6 +495,12 @@
                     handleVoidCallback(action, cb::onHceEventReceived, ex));
         }
 
+        @Override
+        public void onReaderOptionChanged(boolean enabled) throws RemoteException {
+            mCallbackMap.forEach((cb, ex) ->
+                    handleVoidCallback(enabled, cb::onReaderOptionChanged, ex));
+        }
+
         private <T> void handleVoidCallback(
                 T input, Consumer<T> callbackMethod, Executor executor) {
             synchronized (mLock) {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index ff09084..c4173ed 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -460,7 +460,7 @@
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK) {
+        if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE) {
             event.startTracking();
             return true;
         }
@@ -479,7 +479,7 @@
             return true;
         }
 
-        if (keyCode == KeyEvent.KEYCODE_BACK
+        if ((keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE)
                 && event.isTracking() && !event.isCanceled()) {
             if (mPrintPreviewController != null && mPrintPreviewController.isOptionsOpened()
                     && !hasErrors()) {
diff --git a/packages/SettingsLib/DataStore/Android.bp b/packages/SettingsLib/DataStore/Android.bp
index 86c8f0da..6840e10 100644
--- a/packages/SettingsLib/DataStore/Android.bp
+++ b/packages/SettingsLib/DataStore/Android.bp
@@ -17,6 +17,7 @@
         "androidx.annotation_annotation",
         "androidx.collection_collection-ktx",
         "androidx.core_core-ktx",
+        "error_prone_annotations",
         "guava",
     ],
     kotlincflags: ["-Xjvm-default=all"],
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyValueStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyValueStore.kt
new file mode 100644
index 0000000..3d41337
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyValueStore.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 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.settingslib.datastore
+
+import android.content.SharedPreferences
+
+/** Interface of key-value store. */
+interface KeyValueStore : KeyedObservable<String> {
+
+    /** Returns if the storage contains persistent value of given key. */
+    fun contains(key: String): Boolean
+
+    /** Gets default value of given key. */
+    fun <T : Any> getDefaultValue(key: String, valueType: Class<T>): T? =
+        when (valueType) {
+            Boolean::class.javaObjectType -> false
+            Float::class.javaObjectType -> 0f
+            Int::class.javaObjectType -> 0
+            Long::class.javaObjectType -> 0
+            else -> null
+        }
+            as T?
+
+    /** Gets value of given key. */
+    fun <T : Any> getValue(key: String, valueType: Class<T>): T?
+
+    /**
+     * Sets value for given key.
+     *
+     * @param key key
+     * @param valueType value type
+     * @param value value to set, null means remove
+     */
+    fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?)
+}
+
+/** [SharedPreferences] based [KeyValueStore]. */
+interface SharedPreferencesKeyValueStore : KeyValueStore {
+
+    /** [SharedPreferences] of the key-value store. */
+    val sharedPreferences: SharedPreferences
+
+    override fun contains(key: String): Boolean = sharedPreferences.contains(key)
+
+    override fun <T : Any> getValue(key: String, valueType: Class<T>): T? =
+        when (valueType) {
+            Boolean::class.javaObjectType -> sharedPreferences.getBoolean(key, false)
+            Float::class.javaObjectType -> sharedPreferences.getFloat(key, 0f)
+            Int::class.javaObjectType -> sharedPreferences.getInt(key, 0)
+            Long::class.javaObjectType -> sharedPreferences.getLong(key, 0)
+            String::class.javaObjectType -> sharedPreferences.getString(key, null)
+            Set::class.javaObjectType -> sharedPreferences.getStringSet(key, null)
+            else -> null
+        }
+            as T?
+
+    override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
+        if (value == null) {
+            sharedPreferences.edit().remove(key).apply()
+            return
+        }
+        val edit = sharedPreferences.edit()
+        when (valueType) {
+            Boolean::class.javaObjectType -> edit.putBoolean(key, value as Boolean)
+            Float::class.javaObjectType -> edit.putFloat(key, value as Float)
+            Int::class.javaObjectType -> edit.putInt(key, value as Int)
+            Long::class.javaObjectType -> edit.putLong(key, value as Long)
+            String::class.javaObjectType -> edit.putString(key, value as String)
+            Set::class.javaObjectType -> edit.putStringSet(key, value as Set<String>)
+            else -> {}
+        }
+        edit.apply()
+    }
+}
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyedObserver.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyedObserver.kt
index 4ce1d37..ec90317 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyedObserver.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyedObserver.kt
@@ -19,6 +19,7 @@
 import androidx.annotation.AnyThread
 import androidx.annotation.GuardedBy
 import androidx.collection.MutableScatterMap
+import com.google.errorprone.annotations.CanIgnoreReturnValue
 import java.util.WeakHashMap
 import java.util.concurrent.Executor
 
@@ -62,8 +63,9 @@
      *
      * @param observer observer to be notified
      * @param executor executor to run the callback
+     * @return if the observer is newly added
      */
-    fun addObserver(observer: KeyedObserver<K?>, executor: Executor)
+    @CanIgnoreReturnValue fun addObserver(observer: KeyedObserver<K?>, executor: Executor): Boolean
 
     /**
      * Adds an observer on given key.
@@ -73,14 +75,24 @@
      * @param key key to observe
      * @param observer observer to be notified
      * @param executor executor to run the callback
+     * @return if the observer is newly added
      */
-    fun addObserver(key: K, observer: KeyedObserver<K>, executor: Executor)
+    @CanIgnoreReturnValue
+    fun addObserver(key: K, observer: KeyedObserver<K>, executor: Executor): Boolean
 
-    /** Removes observer. */
-    fun removeObserver(observer: KeyedObserver<K?>)
+    /**
+     * Removes observer.
+     *
+     * @return if the observer is found and removed
+     */
+    @CanIgnoreReturnValue fun removeObserver(observer: KeyedObserver<K?>): Boolean
 
-    /** Removes observer on given key. */
-    fun removeObserver(key: K, observer: KeyedObserver<K>)
+    /**
+     * Removes observer on given key.
+     *
+     * @return if the observer is found and removed
+     */
+    @CanIgnoreReturnValue fun removeObserver(key: K, observer: KeyedObserver<K>): Boolean
 
     /**
      * Notifies all observers that a change occurs.
@@ -111,14 +123,17 @@
     @GuardedBy("itself")
     private val keyedObservers = MutableScatterMap<K, WeakHashMap<KeyedObserver<K>, Executor>>()
 
-    override fun addObserver(observer: KeyedObserver<K?>, executor: Executor) {
+    @CanIgnoreReturnValue
+    override fun addObserver(observer: KeyedObserver<K?>, executor: Executor): Boolean {
         val oldExecutor = synchronized(observers) { observers.put(observer, executor) }
         if (oldExecutor != null && oldExecutor != executor) {
             throw IllegalStateException("Add $observer twice, old=$oldExecutor, new=$executor")
         }
+        return oldExecutor == null
     }
 
-    override fun addObserver(key: K, observer: KeyedObserver<K>, executor: Executor) {
+    @CanIgnoreReturnValue
+    override fun addObserver(key: K, observer: KeyedObserver<K>, executor: Executor): Boolean {
         val oldExecutor =
             synchronized(keyedObservers) {
                 keyedObservers.getOrPut(key) { WeakHashMap() }.put(observer, executor)
@@ -126,20 +141,23 @@
         if (oldExecutor != null && oldExecutor != executor) {
             throw IllegalStateException("Add $observer twice, old=$oldExecutor, new=$executor")
         }
+        return oldExecutor == null
     }
 
-    override fun removeObserver(observer: KeyedObserver<K?>) {
-        synchronized(observers) { observers.remove(observer) }
-    }
+    @CanIgnoreReturnValue
+    override fun removeObserver(observer: KeyedObserver<K?>) =
+        synchronized(observers) { observers.remove(observer) } != null
 
-    override fun removeObserver(key: K, observer: KeyedObserver<K>) {
+    @CanIgnoreReturnValue
+    override fun removeObserver(key: K, observer: KeyedObserver<K>) =
         synchronized(keyedObservers) {
-            val observers = keyedObservers[key]
-            if (observers?.remove(observer) != null && observers.isEmpty()) {
+            val observers = keyedObservers[key] ?: return false
+            val removed = observers.remove(observer) != null
+            if (removed && observers.isEmpty()) {
                 keyedObservers.remove(key)
             }
+            removed
         }
-    }
 
     override fun notifyChange(reason: Int) {
         // make a copy to avoid potential ConcurrentModificationException
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsGlobalStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsGlobalStore.kt
new file mode 100644
index 0000000..4aef0fc
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsGlobalStore.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 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.settingslib.datastore
+
+import android.content.ContentResolver
+import android.content.Context
+import android.provider.Settings.Global
+import android.provider.Settings.SettingNotFoundException
+
+/**
+ * [KeyValueStore] for [Global] settings.
+ *
+ * By default, a boolean type `true` value is stored as `1` and `false` value is stored as `0`.
+ */
+class SettingsGlobalStore private constructor(contentResolver: ContentResolver) :
+    SettingsStore(contentResolver) {
+
+    override val tag: String
+        get() = "SettingsGlobalStore"
+
+    override fun contains(key: String): Boolean = Global.getString(contentResolver, key) != null
+
+    override fun <T : Any> getValue(key: String, valueType: Class<T>): T? =
+        try {
+            when (valueType) {
+                Boolean::class.javaObjectType -> Global.getInt(contentResolver, key) != 0
+                Float::class.javaObjectType -> Global.getFloat(contentResolver, key)
+                Int::class.javaObjectType -> Global.getInt(contentResolver, key)
+                Long::class.javaObjectType -> Global.getLong(contentResolver, key)
+                String::class.javaObjectType -> Global.getString(contentResolver, key)
+                else -> throw UnsupportedOperationException("Get $key $valueType")
+            }
+                as T?
+        } catch (e: SettingNotFoundException) {
+            null
+        }
+
+    override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
+        if (value == null) {
+            Global.putString(contentResolver, key, null)
+            return
+        }
+        when (valueType) {
+            Boolean::class.javaObjectType ->
+                Global.putInt(contentResolver, key, if (value == true) 1 else 0)
+            Float::class.javaObjectType -> Global.putFloat(contentResolver, key, value as Float)
+            Int::class.javaObjectType -> Global.putInt(contentResolver, key, value as Int)
+            Long::class.javaObjectType -> Global.putLong(contentResolver, key, value as Long)
+            String::class.javaObjectType -> Global.putString(contentResolver, key, value as String)
+            else -> throw UnsupportedOperationException("Set $key $valueType")
+        }
+    }
+
+    companion object {
+        @Volatile private var instance: SettingsGlobalStore? = null
+
+        @JvmStatic
+        fun get(context: Context): SettingsGlobalStore =
+            instance
+                ?: synchronized(this) {
+                    instance
+                        ?: SettingsGlobalStore(context.applicationContext.contentResolver).also {
+                            instance = it
+                        }
+                }
+    }
+}
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSecureStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSecureStore.kt
new file mode 100644
index 0000000..9f41ecb
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSecureStore.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 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.settingslib.datastore
+
+import android.content.ContentResolver
+import android.content.Context
+import android.provider.Settings.Secure
+import android.provider.Settings.SettingNotFoundException
+
+/**
+ * [KeyValueStore] for [Secure] settings.
+ *
+ * By default, a boolean type `true` value is stored as `1` and `false` value is stored as `0`.
+ */
+class SettingsSecureStore private constructor(contentResolver: ContentResolver) :
+    SettingsStore(contentResolver) {
+
+    override val tag: String
+        get() = "SettingsSecureStore"
+
+    override fun contains(key: String): Boolean = Secure.getString(contentResolver, key) != null
+
+    override fun <T : Any> getValue(key: String, valueType: Class<T>): T? =
+        try {
+            when (valueType) {
+                Boolean::class.javaObjectType -> Secure.getInt(contentResolver, key) != 0
+                Float::class.javaObjectType -> Secure.getFloat(contentResolver, key)
+                Int::class.javaObjectType -> Secure.getInt(contentResolver, key)
+                Long::class.javaObjectType -> Secure.getLong(contentResolver, key)
+                String::class.javaObjectType -> Secure.getString(contentResolver, key)
+                else -> throw UnsupportedOperationException("Get $key $valueType")
+            }
+                as T?
+        } catch (e: SettingNotFoundException) {
+            null
+        }
+
+    override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
+        if (value == null) {
+            Secure.putString(contentResolver, key, null)
+            return
+        }
+        when (valueType) {
+            Boolean::class.javaObjectType ->
+                Secure.putInt(contentResolver, key, if (value == true) 1 else 0)
+            Float::class.javaObjectType -> Secure.putFloat(contentResolver, key, value as Float)
+            Int::class.javaObjectType -> Secure.putInt(contentResolver, key, value as Int)
+            Long::class.javaObjectType -> Secure.putLong(contentResolver, key, value as Long)
+            String::class.javaObjectType -> Secure.putString(contentResolver, key, value as String)
+            else -> throw UnsupportedOperationException("Set $key $valueType")
+        }
+    }
+
+    companion object {
+        @Volatile private var instance: SettingsSecureStore? = null
+
+        @JvmStatic
+        fun get(context: Context): SettingsSecureStore =
+            instance
+                ?: synchronized(this) {
+                    instance
+                        ?: SettingsSecureStore(context.applicationContext.contentResolver).also {
+                            instance = it
+                        }
+                }
+    }
+}
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsStore.kt
new file mode 100644
index 0000000..5981688
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsStore.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2024 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.settingslib.datastore
+
+import android.content.ContentResolver
+import android.database.ContentObserver
+import android.net.Uri
+import android.os.Handler
+import android.os.Looper
+import android.provider.Settings
+import android.util.Log
+import java.util.concurrent.Executor
+import java.util.concurrent.atomic.AtomicInteger
+
+/** Base class of the Settings provider data stores. */
+open abstract class SettingsStore(protected val contentResolver: ContentResolver) :
+    KeyedDataObservable<String>(), KeyValueStore {
+
+    /**
+     * Counter of observers.
+     *
+     * The value is accurate only when [addObserver] and [removeObserver] are called correctly. When
+     * an observer is not removed (and its weak reference is garbage collected), the content
+     * observer is not unregistered but this is not a big deal.
+     */
+    private val counter = AtomicInteger()
+
+    private val contentObserver =
+        object : ContentObserver(Handler(Looper.getMainLooper())) {
+            override fun onChange(selfChange: Boolean) {
+                super.onChange(selfChange, null)
+            }
+
+            override fun onChange(selfChange: Boolean, uri: Uri?) {
+                val key = uri?.lastPathSegment ?: return
+                notifyChange(key, DataChangeReason.UPDATE)
+            }
+        }
+
+    override fun addObserver(observer: KeyedObserver<String?>, executor: Executor) =
+        if (super.addObserver(observer, executor)) {
+            onObserverAdded()
+            true
+        } else {
+            false
+        }
+
+    override fun addObserver(key: String, observer: KeyedObserver<String>, executor: Executor) =
+        if (super.addObserver(key, observer, executor)) {
+            onObserverAdded()
+            true
+        } else {
+            false
+        }
+
+    private fun onObserverAdded() {
+        if (counter.getAndIncrement() != 0) return
+        Log.i(tag, "registerContentObserver")
+        contentResolver.registerContentObserver(
+            Settings.Global.getUriFor(""),
+            true,
+            contentObserver,
+        )
+    }
+
+    override fun removeObserver(observer: KeyedObserver<String?>) =
+        if (super.removeObserver(observer)) {
+            onObserverRemoved()
+            true
+        } else {
+            false
+        }
+
+    override fun removeObserver(key: String, observer: KeyedObserver<String>) =
+        if (super.removeObserver(key, observer)) {
+            onObserverRemoved()
+            true
+        } else {
+            false
+        }
+
+    private fun onObserverRemoved() {
+        if (counter.decrementAndGet() != 0) return
+        Log.i(tag, "unregisterContentObserver")
+        contentResolver.unregisterContentObserver(contentObserver)
+    }
+
+    /** Tag for logging. */
+    abstract val tag: String
+}
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSystemStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSystemStore.kt
new file mode 100644
index 0000000..6cca7ed
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSystemStore.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 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.settingslib.datastore
+
+import android.content.ContentResolver
+import android.content.Context
+import android.provider.Settings.SettingNotFoundException
+import android.provider.Settings.System
+
+/**
+ * [KeyValueStore] for [System] settings.
+ *
+ * By default, a boolean type `true` value is stored as `1` and `false` value is stored as `0`.
+ */
+class SettingsSystemStore private constructor(contentResolver: ContentResolver) :
+    SettingsStore(contentResolver) {
+
+    override val tag: String
+        get() = "SettingsSystemStore"
+
+    override fun contains(key: String): Boolean = System.getString(contentResolver, key) != null
+
+    override fun <T : Any> getValue(key: String, valueType: Class<T>): T? =
+        try {
+            when (valueType) {
+                Boolean::class.javaObjectType -> System.getInt(contentResolver, key) != 0
+                Float::class.javaObjectType -> System.getFloat(contentResolver, key)
+                Int::class.javaObjectType -> System.getInt(contentResolver, key)
+                Long::class.javaObjectType -> System.getLong(contentResolver, key)
+                String::class.javaObjectType -> System.getString(contentResolver, key)
+                else -> throw UnsupportedOperationException("Get $key $valueType")
+            }
+                as T?
+        } catch (e: SettingNotFoundException) {
+            null
+        }
+
+    override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
+        if (value == null) {
+            System.putString(contentResolver, key, null)
+            return
+        }
+        when (valueType) {
+            Boolean::class.javaObjectType ->
+                System.putInt(contentResolver, key, if (value == true) 1 else 0)
+            Float::class.javaObjectType -> System.putFloat(contentResolver, key, value as Float)
+            Int::class.javaObjectType -> System.putInt(contentResolver, key, value as Int)
+            Long::class.javaObjectType -> System.putLong(contentResolver, key, value as Long)
+            String::class.javaObjectType -> System.putString(contentResolver, key, value as String)
+            else -> throw UnsupportedOperationException("Set $key $valueType")
+        }
+    }
+
+    companion object {
+        @Volatile private var instance: SettingsSystemStore? = null
+
+        @JvmStatic
+        fun get(context: Context): SettingsSystemStore =
+            instance
+                ?: synchronized(this) {
+                    instance
+                        ?: SettingsSystemStore(context.applicationContext.contentResolver).also {
+                            instance = it
+                        }
+                }
+    }
+}
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt
index 0ca91cd..ea17a56 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt
@@ -40,8 +40,9 @@
  * Note that existing entries in the SharedPreferences will NOT be deleted before restore.
  *
  * @param context Context to get SharedPreferences
- * @param name Name of the SharedPreferences
- * @param mode Operating mode, see [Context.getSharedPreferences]
+ * @param name Name of the backup restore storage
+ * @param sharedPreferences SharedPreferences object
+ * @param filePath shared preferences file path relative to data dir
  * @param verbose Verbose logging on key/value pairs during backup/restore. Enable for dev only!
  * @param filter Filter of key/value pairs for backup and restore.
  */
@@ -50,12 +51,14 @@
 constructor(
     context: Context,
     override val name: String,
-    @get:VisibleForTesting internal val sharedPreferences: SharedPreferences,
+    override val sharedPreferences: SharedPreferences,
+    filePath: String = getSharedPreferencesFilePath(context, name),
     private val codec: BackupCodec? = null,
     private val verbose: Boolean = defaultVerbose(),
     private val filter: (String, Any?) -> Boolean = { _, _ -> true },
 ) :
-    BackupRestoreFileStorage(context, context.getSharedPreferencesFilePath(name)),
+    BackupRestoreFileStorage(context, filePath),
+    SharedPreferencesKeyValueStore,
     KeyedObservable<String> by KeyedDataObservable() {
 
     @JvmOverloads
@@ -66,7 +69,15 @@
         codec: BackupCodec? = null,
         verbose: Boolean = defaultVerbose(),
         filter: (String, Any?) -> Boolean = { _, _ -> true },
-    ) : this(context, name, context.getSharedPreferences(name, mode), codec, verbose, filter)
+    ) : this(
+        context,
+        name,
+        context.getSharedPreferences(name, mode),
+        getSharedPreferencesFilePath(context, name),
+        codec,
+        verbose,
+        filter,
+    )
 
     /** Name of the intermediate SharedPreferences. */
     @VisibleForTesting
@@ -80,7 +91,15 @@
             return context.getSharedPreferences(intermediateName, Context.MODE_MULTI_PROCESS)
         }
 
-    private val sharedPreferencesListener = createSharedPreferenceListener()
+    private val sharedPreferencesListener =
+        SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
+            if (key != null) {
+                notifyChange(key, DataChangeReason.UPDATE)
+            } else {
+                // On Android >= R, SharedPreferences.Editor.clear() will trigger this case
+                notifyChange(DataChangeReason.DELETE)
+            }
+        }
 
     init {
         // listener is weakly referenced, so unregister is optional
@@ -183,7 +202,8 @@
                 else -> {
                     Log.e(
                         LOG_TAG,
-                        "[$name] $operation $key=$value, unknown type: ${value?.javaClass}")
+                        "[$name] $operation $key=$value, unknown type: ${value?.javaClass}",
+                    )
                 }
             }
         }
@@ -191,14 +211,31 @@
     }
 
     companion object {
-        private fun Context.getSharedPreferencesFilePath(name: String): String {
-            val file = getSharedPreferencesFile(name)
-            return file.relativeTo(dataDirCompat).toString()
+        /** Returns the storage object of default [SharedPreferences]. */
+        @JvmStatic
+        fun getDefault(context: Context, name: String): SharedPreferencesStorage {
+            val prefName = getDefaultSharedPreferencesName(context)
+            return SharedPreferencesStorage(
+                context,
+                name,
+                context.getSharedPreferences(prefName, Context.MODE_PRIVATE),
+                getSharedPreferencesFilePath(context, prefName),
+            )
+        }
+
+        /** Returns the name of default [SharedPreferences]. */
+        @JvmStatic
+        fun getDefaultSharedPreferencesName(context: Context) = context.packageName + "_preferences"
+
+        /** Returns the shared preferences file path relative to data dir. */
+        @JvmStatic
+        fun getSharedPreferencesFilePath(context: Context, name: String): String {
+            val file = context.getSharedPreferencesFile(name)
+            return file.relativeTo(context.dataDirCompat).toString()
         }
 
         /** Returns the absolute path of shared preferences file. */
-        @JvmStatic
-        fun Context.getSharedPreferencesFile(name: String): File {
+        private fun Context.getSharedPreferencesFile(name: String): File {
             // ContextImpl.getSharedPreferencesPath is private
             return File(getSharedPreferencesDir(), "$name.xml")
         }
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/KeyedObserverTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/KeyedObserverTest.kt
index 0fdecb0..c99d4b3 100644
--- a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/KeyedObserverTest.kt
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/KeyedObserverTest.kt
@@ -45,14 +45,14 @@
 
     @Test
     fun addObserver_sameExecutor() {
-        keyedObservable.addObserver(observer1, executor1)
-        keyedObservable.addObserver(observer1, executor1)
+        assertThat(keyedObservable.addObserver(observer1, executor1)).isTrue()
+        assertThat(keyedObservable.addObserver(observer1, executor1)).isFalse()
     }
 
     @Test
     fun addObserver_keyedObserver_sameExecutor() {
-        keyedObservable.addObserver(key1, keyedObserver1, executor1)
-        keyedObservable.addObserver(key1, keyedObserver1, executor1)
+        assertThat(keyedObservable.addObserver(key1, keyedObserver1, executor1)).isTrue()
+        assertThat(keyedObservable.addObserver(key1, keyedObserver1, executor1)).isFalse()
     }
 
     @Test
@@ -109,15 +109,15 @@
 
     @Test
     fun addObserver_notifyObservers_removeObserver() {
-        keyedObservable.addObserver(observer1, executor1)
-        keyedObservable.addObserver(observer2, executor2)
+        assertThat(keyedObservable.addObserver(observer1, executor1)).isTrue()
+        assertThat(keyedObservable.addObserver(observer2, executor2)).isTrue()
 
         keyedObservable.notifyChange(DataChangeReason.UPDATE)
         verify(observer1).onKeyChanged(null, DataChangeReason.UPDATE)
         verify(observer2).onKeyChanged(null, DataChangeReason.UPDATE)
 
         reset(observer1, observer2)
-        keyedObservable.removeObserver(observer2)
+        assertThat(keyedObservable.removeObserver(observer2)).isTrue()
 
         keyedObservable.notifyChange(DataChangeReason.DELETE)
         verify(observer1).onKeyChanged(null, DataChangeReason.DELETE)
@@ -126,15 +126,15 @@
 
     @Test
     fun addObserver_keyedObserver_notifyObservers_removeObserver() {
-        keyedObservable.addObserver(key1, keyedObserver1, executor1)
-        keyedObservable.addObserver(key2, keyedObserver2, executor2)
+        assertThat(keyedObservable.addObserver(key1, keyedObserver1, executor1)).isTrue()
+        assertThat(keyedObservable.addObserver(key2, keyedObserver2, executor2)).isTrue()
 
         keyedObservable.notifyChange(key1, DataChangeReason.UPDATE)
         verify(keyedObserver1).onKeyChanged(key1, DataChangeReason.UPDATE)
         verify(keyedObserver2, never()).onKeyChanged(key2, DataChangeReason.UPDATE)
 
         reset(keyedObserver1, keyedObserver2)
-        keyedObservable.removeObserver(key1, keyedObserver1)
+        assertThat(keyedObservable.removeObserver(key1, keyedObserver1)).isTrue()
 
         keyedObservable.notifyChange(key1, DataChangeReason.DELETE)
         verify(keyedObserver1, never()).onKeyChanged(key1, DataChangeReason.DELETE)
@@ -143,9 +143,9 @@
 
     @Test
     fun notifyChange_addMoreTypeObservers_checkOnKeyChanged() {
-        keyedObservable.addObserver(observer1, executor1)
-        keyedObservable.addObserver(key1, keyedObserver1, executor1)
-        keyedObservable.addObserver(key2, keyedObserver2, executor1)
+        assertThat(keyedObservable.addObserver(observer1, executor1)).isTrue()
+        assertThat(keyedObservable.addObserver(key1, keyedObserver1, executor1)).isTrue()
+        assertThat(keyedObservable.addObserver(key2, keyedObserver2, executor1)).isTrue()
 
         keyedObservable.notifyChange(DataChangeReason.UPDATE)
         verify(observer1).onKeyChanged(null, DataChangeReason.UPDATE)
@@ -171,25 +171,25 @@
     fun notifyChange_addObserverWithinCallback() {
         // ConcurrentModificationException is raised if it is not implemented correctly
         val observer: KeyedObserver<Any?> = KeyedObserver { _, _ ->
-            keyedObservable.addObserver(observer1, executor1)
+            assertThat(keyedObservable.addObserver(observer1, executor1)).isTrue()
         }
 
-        keyedObservable.addObserver(observer, executor1)
+        assertThat(keyedObservable.addObserver(observer, executor1)).isTrue()
 
         keyedObservable.notifyChange(DataChangeReason.UPDATE)
-        keyedObservable.removeObserver(observer)
+        assertThat(keyedObservable.removeObserver(observer)).isTrue()
     }
 
     @Test
     fun notifyChange_KeyedObserver_addObserverWithinCallback() {
         // ConcurrentModificationException is raised if it is not implemented correctly
         val keyObserver: KeyedObserver<Any?> = KeyedObserver { _, _ ->
-            keyedObservable.addObserver(key1, keyedObserver1, executor1)
+            assertThat(keyedObservable.addObserver(key1, keyedObserver1, executor1)).isTrue()
         }
 
-        keyedObservable.addObserver(key1, keyObserver, executor1)
+        assertThat(keyedObservable.addObserver(key1, keyObserver, executor1)).isTrue()
 
         keyedObservable.notifyChange(key1, DataChangeReason.UPDATE)
-        keyedObservable.removeObserver(key1, keyObserver)
+        assertThat(keyedObservable.removeObserver(key1, keyObserver)).isTrue()
     }
 }
diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
index 4387b6f..a0599bb 100644
--- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
+++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
@@ -35,6 +35,7 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.RawRes;
 import androidx.annotation.StringRes;
 import androidx.preference.Preference;
@@ -243,6 +244,14 @@
     }
 
     /**
+     * Gets the content description set by {@link #setContentDescription}.
+     */
+    @Nullable
+    public CharSequence getContentDescription() {
+        return mContentDescription;
+    }
+
+    /**
      * Gets the lottie illustration resource id.
      */
     public int getLottieAnimationResId() {
diff --git a/packages/SettingsLib/Metadata/Android.bp b/packages/SettingsLib/Metadata/Android.bp
new file mode 100644
index 0000000..207637f
--- /dev/null
+++ b/packages/SettingsLib/Metadata/Android.bp
@@ -0,0 +1,23 @@
+package {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+    name: "SettingsLibMetadata-srcs",
+    srcs: ["src/**/*.kt"],
+}
+
+android_library {
+    name: "SettingsLibMetadata",
+    defaults: [
+        "SettingsLintDefaults",
+    ],
+    srcs: [":SettingsLibMetadata-srcs"],
+    static_libs: [
+        "androidx.annotation_annotation",
+        "androidx.fragment_fragment",
+        "guava",
+        "SettingsLibDataStore",
+    ],
+    kotlincflags: ["-Xjvm-default=all"],
+}
diff --git a/packages/SettingsLib/Metadata/AndroidManifest.xml b/packages/SettingsLib/Metadata/AndroidManifest.xml
new file mode 100644
index 0000000..1c801e6
--- /dev/null
+++ b/packages/SettingsLib/Metadata/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.settingslib.metadata">
+
+    <uses-sdk android:minSdkVersion="21" />
+</manifest>
diff --git a/packages/SettingsLib/Metadata/processor/Android.bp b/packages/SettingsLib/Metadata/processor/Android.bp
new file mode 100644
index 0000000..d8acc76
--- /dev/null
+++ b/packages/SettingsLib/Metadata/processor/Android.bp
@@ -0,0 +1,11 @@
+package {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_plugin {
+    name: "SettingsLibMetadata-processor",
+    srcs: ["src/**/*.kt"],
+    processor_class: "com.android.settingslib.metadata.PreferenceScreenAnnotationProcessor",
+    java_resource_dirs: ["resources"],
+    visibility: ["//visibility:public"],
+}
diff --git a/packages/SettingsLib/Metadata/processor/resources/META-INF/services/javax.annotation.processing.Processor b/packages/SettingsLib/Metadata/processor/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 0000000..762a01a
--- /dev/null
+++ b/packages/SettingsLib/Metadata/processor/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+com.android.settingslib.metadata.PreferenceScreenAnnotationProcessor
\ No newline at end of file
diff --git a/packages/SettingsLib/Metadata/processor/src/com/android/settingslib/metadata/PreferenceScreenAnnotationProcessor.kt b/packages/SettingsLib/Metadata/processor/src/com/android/settingslib/metadata/PreferenceScreenAnnotationProcessor.kt
new file mode 100644
index 0000000..620d717
--- /dev/null
+++ b/packages/SettingsLib/Metadata/processor/src/com/android/settingslib/metadata/PreferenceScreenAnnotationProcessor.kt
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2024 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.settingslib.metadata
+
+import java.util.TreeMap
+import javax.annotation.processing.AbstractProcessor
+import javax.annotation.processing.ProcessingEnvironment
+import javax.annotation.processing.RoundEnvironment
+import javax.lang.model.SourceVersion
+import javax.lang.model.element.AnnotationMirror
+import javax.lang.model.element.AnnotationValue
+import javax.lang.model.element.Element
+import javax.lang.model.element.ElementKind
+import javax.lang.model.element.ExecutableElement
+import javax.lang.model.element.Modifier
+import javax.lang.model.element.TypeElement
+import javax.lang.model.type.TypeMirror
+import javax.tools.Diagnostic
+
+/** Processor to gather preference screens annotated with `@ProvidePreferenceScreen`. */
+class PreferenceScreenAnnotationProcessor : AbstractProcessor() {
+    private val screens = TreeMap<String, ConstructorType>()
+    private val overlays = mutableMapOf<String, String>()
+    private val contextType: TypeMirror by lazy {
+        processingEnv.elementUtils.getTypeElement("android.content.Context").asType()
+    }
+
+    private var options: Map<String, Any?>? = null
+    private lateinit var annotationElement: TypeElement
+    private lateinit var optionsElement: TypeElement
+    private lateinit var screenType: TypeMirror
+
+    override fun getSupportedAnnotationTypes() = setOf(ANNOTATION, OPTIONS)
+
+    override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latestSupported()
+
+    override fun init(processingEnv: ProcessingEnvironment) {
+        super.init(processingEnv)
+        val elementUtils = processingEnv.elementUtils
+        annotationElement = elementUtils.getTypeElement(ANNOTATION)
+        optionsElement = elementUtils.getTypeElement(OPTIONS)
+        screenType = elementUtils.getTypeElement("$PACKAGE.$PREFERENCE_SCREEN_METADATA").asType()
+    }
+
+    override fun process(
+        annotations: MutableSet<out TypeElement>,
+        roundEnv: RoundEnvironment,
+    ): Boolean {
+        roundEnv.getElementsAnnotatedWith(optionsElement).singleOrNull()?.run {
+            if (options != null) error("@$OPTIONS_NAME is already specified: $options", this)
+            options =
+                annotationMirrors
+                    .single { it.isElement(optionsElement) }
+                    .elementValues
+                    .entries
+                    .associate { it.key.simpleName.toString() to it.value.value }
+        }
+        for (element in roundEnv.getElementsAnnotatedWith(annotationElement)) {
+            (element as? TypeElement)?.process()
+        }
+        if (roundEnv.processingOver()) codegen()
+        return false
+    }
+
+    private fun TypeElement.process() {
+        if (kind != ElementKind.CLASS || modifiers.contains(Modifier.ABSTRACT)) {
+            error("@$ANNOTATION_NAME must be added to non abstract class", this)
+            return
+        }
+        if (!processingEnv.typeUtils.isAssignable(asType(), screenType)) {
+            error("@$ANNOTATION_NAME must be added to $PREFERENCE_SCREEN_METADATA subclass", this)
+            return
+        }
+        val constructorType = getConstructorType()
+        if (constructorType == null) {
+            error(
+                "Class must be an object, or has single public constructor that " +
+                    "accepts no parameter or a Context parameter",
+                this,
+            )
+            return
+        }
+        val screenQualifiedName = qualifiedName.toString()
+        screens[screenQualifiedName] = constructorType
+        val annotation = annotationMirrors.single { it.isElement(annotationElement) }
+        val overlay = annotation.getOverlay()
+        if (overlay != null) {
+            overlays.put(overlay, screenQualifiedName)?.let {
+                error("$overlay has been overlaid by $it", this)
+            }
+        }
+    }
+
+    private fun codegen() {
+        val collector = (options?.get("codegenCollector") as? String) ?: DEFAULT_COLLECTOR
+        if (collector.isEmpty()) return
+        val parts = collector.split('/')
+        if (parts.size == 3) {
+            generateCode(parts[0], parts[1], parts[2])
+        } else {
+            throw IllegalArgumentException(
+                "Collector option '$collector' does not follow 'PKG/CLASS/METHOD' format"
+            )
+        }
+    }
+
+    private fun generateCode(outputPkg: String, outputClass: String, outputFun: String) {
+        for ((overlay, screen) in overlays) {
+            if (screens.remove(overlay) == null) {
+                warn("$overlay is overlaid by $screen but not annotated with @$ANNOTATION_NAME")
+            } else {
+                processingEnv.messager.printMessage(
+                    Diagnostic.Kind.NOTE,
+                    "$overlay is overlaid by $screen",
+                )
+            }
+        }
+        processingEnv.filer.createSourceFile("$outputPkg.$outputClass").openWriter().use {
+            it.write("package $outputPkg;\n\n")
+            it.write("import $PACKAGE.$PREFERENCE_SCREEN_METADATA;\n\n")
+            it.write("// Generated by annotation processor for @$ANNOTATION_NAME\n")
+            it.write("public final class $outputClass {\n")
+            it.write("  private $outputClass() {}\n\n")
+            it.write(
+                "  public static java.util.List<$PREFERENCE_SCREEN_METADATA> " +
+                    "$outputFun(android.content.Context context) {\n"
+            )
+            it.write(
+                "    java.util.ArrayList<$PREFERENCE_SCREEN_METADATA> screens = " +
+                    "new java.util.ArrayList<>(${screens.size});\n"
+            )
+            for ((screen, constructorType) in screens) {
+                when (constructorType) {
+                    ConstructorType.DEFAULT -> it.write("    screens.add(new $screen());\n")
+                    ConstructorType.CONTEXT -> it.write("    screens.add(new $screen(context));\n")
+                    ConstructorType.SINGLETON -> it.write("    screens.add($screen.INSTANCE);\n")
+                }
+            }
+            for ((overlay, screen) in overlays) {
+                it.write("    // $overlay is overlaid by $screen\n")
+            }
+            it.write("    return screens;\n")
+            it.write("  }\n")
+            it.write("}")
+        }
+    }
+
+    private fun AnnotationMirror.isElement(element: TypeElement) =
+        processingEnv.typeUtils.isSameType(annotationType.asElement().asType(), element.asType())
+
+    private fun AnnotationMirror.getOverlay(): String? {
+        for ((key, value) in elementValues) {
+            if (key.simpleName.contentEquals("overlay")) {
+                return if (value.isDefaultClassValue(key)) null else value.value.toString()
+            }
+        }
+        return null
+    }
+
+    private fun AnnotationValue.isDefaultClassValue(key: ExecutableElement) =
+        processingEnv.typeUtils.isSameType(
+            value as TypeMirror,
+            key.defaultValue.value as TypeMirror,
+        )
+
+    private fun TypeElement.getConstructorType(): ConstructorType? {
+        var constructor: ExecutableElement? = null
+        for (element in enclosedElements) {
+            if (element.isKotlinObject()) return ConstructorType.SINGLETON
+            if (element.kind != ElementKind.CONSTRUCTOR) continue
+            if (!element.modifiers.contains(Modifier.PUBLIC)) continue
+            if (constructor != null) return null
+            constructor = element as ExecutableElement
+        }
+        return constructor?.parameters?.run {
+            when {
+                isEmpty() -> ConstructorType.DEFAULT
+                size == 1 && processingEnv.typeUtils.isSameType(this[0].asType(), contextType) ->
+                    ConstructorType.CONTEXT
+                else -> null
+            }
+        }
+    }
+
+    private fun Element.isKotlinObject() =
+        kind == ElementKind.FIELD &&
+            modifiers.run { contains(Modifier.PUBLIC) && contains(Modifier.STATIC) } &&
+            simpleName.toString() == "INSTANCE"
+
+    private fun warn(msg: CharSequence) =
+        processingEnv.messager.printMessage(Diagnostic.Kind.WARNING, msg)
+
+    private fun error(msg: CharSequence, element: Element) =
+        processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, msg, element)
+
+    private enum class ConstructorType {
+        DEFAULT, // default constructor with no parameter
+        CONTEXT, // constructor with a Context parameter
+        SINGLETON, // Kotlin object class
+    }
+
+    companion object {
+        private const val PACKAGE = "com.android.settingslib.metadata"
+        private const val ANNOTATION_NAME = "ProvidePreferenceScreen"
+        private const val ANNOTATION = "$PACKAGE.$ANNOTATION_NAME"
+        private const val PREFERENCE_SCREEN_METADATA = "PreferenceScreenMetadata"
+
+        private const val OPTIONS_NAME = "ProvidePreferenceScreenOptions"
+        private const val OPTIONS = "$PACKAGE.$OPTIONS_NAME"
+        private const val DEFAULT_COLLECTOR = "$PACKAGE/PreferenceScreenCollector/get"
+    }
+}
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/Annotations.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/Annotations.kt
new file mode 100644
index 0000000..ea20a74
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/Annotations.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 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.settingslib.metadata
+
+import kotlin.reflect.KClass
+
+/**
+ * Annotation to provide preference screen.
+ *
+ * The annotated class must satisfy either condition:
+ * - the primary constructor has no parameter
+ * - the primary constructor has a single [android.content.Context] parameter
+ * - it is a Kotlin object class
+ *
+ * @param overlay if specified, current annotated screen will overlay the given screen
+ */
+@Retention(AnnotationRetention.SOURCE)
+@Target(AnnotationTarget.CLASS)
+@MustBeDocumented
+annotation class ProvidePreferenceScreen(
+    val overlay: KClass<out PreferenceScreenMetadata> = PreferenceScreenMetadata::class,
+)
+
+/**
+ * Provides options for [ProvidePreferenceScreen] annotation processor.
+ *
+ * @param codegenCollector generated collector class (format: "pkg/class/method"), an empty string
+ *   means do not generate code
+ */
+@Retention(AnnotationRetention.SOURCE)
+@Target(AnnotationTarget.CLASS)
+@MustBeDocumented
+annotation class ProvidePreferenceScreenOptions(
+    val codegenCollector: String = "com.android.settingslib.metadata/PreferenceScreenCollector/get",
+)
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PersistentPreference.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PersistentPreference.kt
new file mode 100644
index 0000000..51a8580
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PersistentPreference.kt
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2024 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.settingslib.metadata
+
+import android.content.Context
+import androidx.annotation.ArrayRes
+import androidx.annotation.IntDef
+import com.android.settingslib.datastore.KeyValueStore
+
+/** Permit of read and write request. */
+@IntDef(
+    ReadWritePermit.ALLOW,
+    ReadWritePermit.DISALLOW,
+    ReadWritePermit.REQUIRE_APP_PERMISSION,
+    ReadWritePermit.REQUIRE_USER_AGREEMENT,
+)
+@Retention(AnnotationRetention.SOURCE)
+annotation class ReadWritePermit {
+    companion object {
+        /** Allow to read/write value. */
+        const val ALLOW = 0
+        /** Disallow to read/write value (e.g. uid not allowed). */
+        const val DISALLOW = 1
+        /** Require (runtime/special) app permission from user explicitly. */
+        const val REQUIRE_APP_PERMISSION = 2
+        /** Require explicit user agreement (e.g. terms of service). */
+        const val REQUIRE_USER_AGREEMENT = 3
+    }
+}
+
+/** Preference interface that has a value persisted in datastore. */
+interface PersistentPreference<T> {
+
+    /**
+     * Returns the key-value storage of the preference.
+     *
+     * The default implementation returns the storage provided by
+     * [PreferenceScreenRegistry.getKeyValueStore].
+     */
+    fun storage(context: Context): KeyValueStore =
+        PreferenceScreenRegistry.getKeyValueStore(context, this as PreferenceMetadata)!!
+
+    /**
+     * Returns if the external application (identified by [callingUid]) has permission to read
+     * preference value.
+     *
+     * The underlying implementation does NOT need to check common states like isEnabled,
+     * isRestricted or isAvailable.
+     */
+    @ReadWritePermit
+    fun getReadPermit(context: Context, myUid: Int, callingUid: Int): Int =
+        PreferenceScreenRegistry.getReadPermit(
+            context,
+            myUid,
+            callingUid,
+            this as PreferenceMetadata,
+        )
+
+    /**
+     * Returns if the external application (identified by [callingUid]) has permission to write
+     * preference with given [value].
+     *
+     * The underlying implementation does NOT need to check common states like isEnabled,
+     * isRestricted or isAvailable.
+     */
+    @ReadWritePermit
+    fun getWritePermit(context: Context, value: T?, myUid: Int, callingUid: Int): Int =
+        PreferenceScreenRegistry.getWritePermit(
+            context,
+            value,
+            myUid,
+            callingUid,
+            this as PreferenceMetadata,
+        )
+}
+
+/** Descriptor of values. */
+sealed interface ValueDescriptor {
+
+    /** Returns if given value (represented by index) is valid. */
+    fun isValidValue(context: Context, index: Int): Boolean
+}
+
+/**
+ * A boolean type value.
+ *
+ * A zero value means `False`, otherwise it is `True`.
+ */
+interface BooleanValue : ValueDescriptor {
+    override fun isValidValue(context: Context, index: Int) = true
+}
+
+/** Value falls into a given array. */
+interface DiscreteValue<T> : ValueDescriptor {
+    @get:ArrayRes val values: Int
+
+    @get:ArrayRes val valuesDescription: Int
+
+    fun getValue(context: Context, index: Int): T
+}
+
+/**
+ * Value falls into a text array, whose element is [CharSequence] type.
+ *
+ * [values] resource is `<string-array>`.
+ */
+interface DiscreteTextValue : DiscreteValue<CharSequence> {
+    override fun isValidValue(context: Context, index: Int): Boolean {
+        if (index < 0) return false
+        return index < context.resources.getTextArray(values).size
+    }
+
+    override fun getValue(context: Context, index: Int): CharSequence =
+        context.resources.getTextArray(values)[index]
+}
+
+/**
+ * Value falls into a string array, whose element is [String] type.
+ *
+ * [values] resource is `<string-array>`.
+ */
+interface DiscreteStringValue : DiscreteValue<String> {
+    override fun isValidValue(context: Context, index: Int): Boolean {
+        if (index < 0) return false
+        return index < context.resources.getStringArray(values).size
+    }
+
+    override fun getValue(context: Context, index: Int): String =
+        context.resources.getStringArray(values)[index]
+}
+
+/**
+ * Value falls into an integer array.
+ *
+ * [values] resource is `<integer-array>`.
+ */
+interface DiscreteIntValue : DiscreteValue<Int> {
+    override fun isValidValue(context: Context, index: Int): Boolean {
+        if (index < 0) return false
+        return index < context.resources.getIntArray(values).size
+    }
+
+    override fun getValue(context: Context, index: Int): Int =
+        context.resources.getIntArray(values)[index]
+}
+
+/** Value is between a range. */
+interface RangeValue : ValueDescriptor {
+    /** The lower bound (inclusive) of the range. */
+    val minValue: Int
+
+    /** The upper bound (inclusive) of the range. */
+    val maxValue: Int
+
+    /** The increment step within the range. 0 means unset, which implies step size is 1. */
+    val incrementStep: Int
+        get() = 0
+
+    override fun isValidValue(context: Context, index: Int) = index in minValue..maxValue
+}
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt
new file mode 100644
index 0000000..4503738
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2024 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.settingslib.metadata
+
+/** A node in preference hierarchy that is associated with [PreferenceMetadata]. */
+open class PreferenceHierarchyNode internal constructor(val metadata: PreferenceMetadata)
+
+/**
+ * Preference hierarchy describes the structure of preferences recursively.
+ *
+ * A root hierarchy represents a preference screen. A sub-hierarchy represents a preference group.
+ */
+class PreferenceHierarchy internal constructor(metadata: PreferenceMetadata) :
+    PreferenceHierarchyNode(metadata) {
+
+    private val children = mutableListOf<PreferenceHierarchyNode>()
+
+    /** Adds a preference to the hierarchy. */
+    operator fun PreferenceMetadata.unaryPlus() {
+        children.add(PreferenceHierarchyNode(this))
+    }
+
+    /**
+     * Adds preference screen with given key (as a placeholder) to the hierarchy.
+     *
+     * This is mainly to support Android Settings overlays. OEMs might want to custom some of the
+     * screens. In resource-based hierarchy, it leverages the resource overlay. In terms of DSL or
+     * programmatic hierarchy, it will be a problem to specify concrete screen metadata objects.
+     * Instead, use preference screen key as a placeholder in the hierarchy and screen metadata will
+     * be looked up from [PreferenceScreenRegistry] lazily at runtime.
+     *
+     * @throws NullPointerException if screen is not registered to [PreferenceScreenRegistry]
+     */
+    operator fun String.unaryPlus() {
+        children.add(PreferenceHierarchyNode(PreferenceScreenRegistry[this]!!))
+    }
+
+    /** Adds a preference to the hierarchy. */
+    fun add(metadata: PreferenceMetadata) {
+        children.add(PreferenceHierarchyNode(metadata))
+    }
+
+    /** Adds a preference group to the hierarchy. */
+    operator fun PreferenceGroup.unaryPlus() = PreferenceHierarchy(this).also { children.add(it) }
+
+    /** Adds a preference group and returns its preference hierarchy. */
+    fun addGroup(metadata: PreferenceGroup): PreferenceHierarchy =
+        PreferenceHierarchy(metadata).also { children.add(it) }
+
+    /**
+     * Adds preference screen with given key (as a placeholder) to the hierarchy.
+     *
+     * This is mainly to support Android Settings overlays. OEMs might want to custom some of the
+     * screens. In resource-based hierarchy, it leverages the resource overlay. In terms of DSL or
+     * programmatic hierarchy, it will be a problem to specify concrete screen metadata objects.
+     * Instead, use preference screen key as a placeholder in the hierarchy and screen metadata will
+     * be looked up from [PreferenceScreenRegistry] lazily at runtime.
+     *
+     * @throws NullPointerException if screen is not registered to [PreferenceScreenRegistry]
+     */
+    fun addPreferenceScreen(screenKey: String) {
+        children.add(PreferenceHierarchy(PreferenceScreenRegistry[screenKey]!!))
+    }
+
+    /** Extensions to add more preferences to the hierarchy. */
+    operator fun plusAssign(init: PreferenceHierarchy.() -> Unit) = init(this)
+
+    /** Traversals preference hierarchy and applies given action. */
+    fun forEach(action: (PreferenceHierarchyNode) -> Unit) {
+        for (it in children) action(it)
+    }
+
+    /** Traversals preference hierarchy and applies given action. */
+    suspend fun forEachAsync(action: suspend (PreferenceHierarchyNode) -> Unit) {
+        for (it in children) action(it)
+    }
+
+    /** Finds the [PreferenceMetadata] object associated with given key. */
+    fun find(key: String): PreferenceMetadata? {
+        if (metadata.key == key) return metadata
+        for (child in children) {
+            if (child is PreferenceHierarchy) {
+                val result = child.find(key)
+                if (result != null) return result
+            } else {
+                if (child.metadata.key == key) return child.metadata
+            }
+        }
+        return null
+    }
+
+    /** Returns all the [PreferenceMetadata]s appear in the hierarchy. */
+    fun getAllPreferences(): List<PreferenceMetadata> =
+        mutableListOf<PreferenceMetadata>().also { getAllPreferences(it) }
+
+    private fun getAllPreferences(result: MutableList<PreferenceMetadata>) {
+        result.add(metadata)
+        for (child in children) {
+            if (child is PreferenceHierarchy) {
+                child.getAllPreferences(result)
+            } else {
+                result.add(child.metadata)
+            }
+        }
+    }
+}
+
+/**
+ * Builder function to create [PreferenceHierarchy] in
+ * [DSL](https://kotlinlang.org/docs/type-safe-builders.html) manner.
+ */
+fun preferenceHierarchy(metadata: PreferenceMetadata, init: PreferenceHierarchy.() -> Unit) =
+    PreferenceHierarchy(metadata).also(init)
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceMetadata.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceMetadata.kt
new file mode 100644
index 0000000..f39f3a0
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceMetadata.kt
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2024 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.settingslib.metadata
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import androidx.annotation.AnyThread
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+
+/**
+ * Interface provides preference metadata (title, summary, icon, etc.).
+ *
+ * Besides the existing APIs, subclass could integrate with following interface to provide more
+ * information:
+ * - [PreferenceTitleProvider]: provide dynamic title content
+ * - [PreferenceSummaryProvider]: provide dynamic summary content (e.g. based on preference value)
+ * - [PreferenceAvailabilityProvider]: provide preference availability (e.g. based on flag)
+ * - [PreferenceLifecycleProvider]: provide the lifecycle callbacks and notify state change
+ *
+ * Notes:
+ * - UI framework support:
+ *     - This class does not involve any UI logic, it is the data layer.
+ *     - Subclass could integrate with datastore and UI widget to provide UI layer. For instance,
+ *       `PreferenceBinding` supports Jetpack Preference binding.
+ * - Datastore:
+ *     - Subclass should implement the [PersistentPreference] to note that current preference is
+ *       persistent in datastore.
+ *     - It is always recommended to support back up preference value changed by user. Typically,
+ *       the back up and restore happen within datastore, the [allowBackup] API is to mark if
+ *       current preference value should be backed up (backup allowed by default).
+ * - Preference indexing for search:
+ *     - Override [isIndexable] API to mark if preference is indexable (enabled by default).
+ *     - If [isIndexable] returns true, preference title and summary will be indexed with cache.
+ *       More indexing data could be provided through [keywords].
+ *     - Settings search will cache the preference title/summary/keywords for indexing. The cache is
+ *       invalidated when system locale changed, app upgraded, etc.
+ *     - Dynamic content is not suitable to be cached for indexing. Subclass that implements
+ *       [PreferenceTitleProvider] / [PreferenceSummaryProvider] will not have its title / summary
+ *       indexed.
+ */
+@AnyThread
+interface PreferenceMetadata {
+
+    /** Preference key. */
+    val key: String
+
+    /**
+     * Preference title resource id.
+     *
+     * Implement [PreferenceTitleProvider] if title is generated dynamically.
+     */
+    val title: Int
+        @StringRes get() = 0
+
+    /**
+     * Preference summary resource id.
+     *
+     * Implement [PreferenceSummaryProvider] if summary is generated dynamically (e.g. summary is
+     * provided per preference value)
+     */
+    val summary: Int
+        @StringRes get() = 0
+
+    /** Icon of the preference. */
+    val icon: Int
+        @DrawableRes get() = 0
+
+    /** Additional keywords for indexing. */
+    val keywords: Int
+        @StringRes get() = 0
+
+    /**
+     * Return the extras Bundle object associated with this preference.
+     *
+     * It is used to provide more information for metadata.
+     */
+    fun extras(context: Context): Bundle? = null
+
+    /**
+     * Returns if preference is indexable, default value is `true`.
+     *
+     * Return `false` only when the preference is always unavailable on current device. If it is
+     * conditional available, override [PreferenceAvailabilityProvider].
+     */
+    fun isIndexable(context: Context): Boolean = true
+
+    /**
+     * Returns if preference is enabled.
+     *
+     * UI framework normally does not allow user to interact with the preference widget when it is
+     * disabled.
+     *
+     * [dependencyOfEnabledState] is provided to support dependency, the [shouldDisableDependents]
+     * value of dependent preference is used to decide enabled state.
+     */
+    fun isEnabled(context: Context): Boolean {
+        val dependency = dependencyOfEnabledState(context) ?: return true
+        return !dependency.shouldDisableDependents(context)
+    }
+
+    /** Returns the key of depended preference to decide the enabled state. */
+    fun dependencyOfEnabledState(context: Context): PreferenceMetadata? = null
+
+    /** Returns whether this preference's dependents should be disabled. */
+    fun shouldDisableDependents(context: Context): Boolean = !isEnabled(context)
+
+    /** Returns if the preference is persistent in datastore. */
+    fun isPersistent(context: Context): Boolean = this is PersistentPreference<*>
+
+    /**
+     * Returns if preference value backup is allowed (by default returns `true` if preference is
+     * persistent).
+     */
+    fun allowBackup(context: Context): Boolean = isPersistent(context)
+
+    /** Returns preference intent. */
+    fun intent(context: Context): Intent? = null
+
+    /** Returns preference order. */
+    fun order(context: Context): Int? = null
+
+    /**
+     * Returns the preference title.
+     *
+     * Implement [PreferenceTitleProvider] interface if title content is generated dynamically.
+     */
+    fun getPreferenceTitle(context: Context): CharSequence? =
+        when {
+            title != 0 -> context.getText(title)
+            this is PreferenceTitleProvider -> getTitle(context)
+            else -> null
+        }
+
+    /**
+     * Returns the preference summary.
+     *
+     * Implement [PreferenceSummaryProvider] interface if summary content is generated dynamically
+     * (e.g. summary is provided per preference value).
+     */
+    fun getPreferenceSummary(context: Context): CharSequence? =
+        when {
+            summary != 0 -> context.getText(summary)
+            this is PreferenceSummaryProvider -> getSummary(context)
+            else -> null
+        }
+}
+
+/** Metadata of preference group. */
+@AnyThread
+open class PreferenceGroup(override val key: String, override val title: Int) : PreferenceMetadata
+
+/** Metadata of preference screen. */
+@AnyThread
+interface PreferenceScreenMetadata : PreferenceMetadata {
+
+    /**
+     * The screen title resource, which precedes [getScreenTitle] if provided.
+     *
+     * By default, screen title is same with [title].
+     */
+    val screenTitle: Int
+        get() = title
+
+    /** Returns dynamic screen title, use [screenTitle] whenever possible. */
+    fun getScreenTitle(context: Context): CharSequence? = null
+
+    /** Returns the fragment class to show the preference screen. */
+    fun fragmentClass(): Class<out Fragment>?
+
+    /**
+     * Indicates if [getPreferenceHierarchy] returns a complete hierarchy of the preference screen.
+     *
+     * If `true`, the result of [getPreferenceHierarchy] will be used to inflate preference screen.
+     * Otherwise, it is an intermediate state called hybrid mode, preference hierarchy is
+     * represented by other ways (e.g. XML resource) and [PreferenceMetadata]s in
+     * [getPreferenceHierarchy] will only be used to bind UI widgets.
+     */
+    fun hasCompleteHierarchy(): Boolean = true
+
+    /**
+     * Returns the hierarchy of preference screen.
+     *
+     * The implementation MUST include all preferences into the hierarchy regardless of the runtime
+     * conditions. DO NOT check any condition (except compile time flag) before adding a preference.
+     */
+    fun getPreferenceHierarchy(context: Context): PreferenceHierarchy
+}
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceScreenBindingKeyProvider.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceScreenBindingKeyProvider.kt
new file mode 100644
index 0000000..84014f1
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceScreenBindingKeyProvider.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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.settingslib.metadata
+
+import android.content.Context
+
+/** Provides the associated preference screen key for binding. */
+interface PreferenceScreenBindingKeyProvider {
+
+    /** Returns the associated preference screen key. */
+    fun getPreferenceScreenBindingKey(context: Context): String?
+}
+
+/** Extra key to provide the preference screen key for binding. */
+const val EXTRA_BINDING_SCREEN_KEY = "settingslib:binding_screen_key"
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceScreenRegistry.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceScreenRegistry.kt
new file mode 100644
index 0000000..48798da
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceScreenRegistry.kt
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2024 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.settingslib.metadata
+
+import android.content.Context
+import com.android.settingslib.datastore.KeyValueStore
+import com.google.common.base.Supplier
+import com.google.common.base.Suppliers
+import com.google.common.collect.ImmutableMap
+
+private typealias PreferenceScreenMap = ImmutableMap<String, PreferenceScreenMetadata>
+
+/** Registry of all available preference screens in the app. */
+object PreferenceScreenRegistry : ReadWritePermitProvider {
+
+    /** Provider of key-value store. */
+    private lateinit var keyValueStoreProvider: KeyValueStoreProvider
+
+    private var preferenceScreensSupplier: Supplier<PreferenceScreenMap> = Supplier {
+        ImmutableMap.of()
+    }
+
+    private val preferenceScreens: PreferenceScreenMap
+        get() = preferenceScreensSupplier.get()
+
+    private var readWritePermitProvider: ReadWritePermitProvider? = null
+
+    /** Sets the [KeyValueStoreProvider]. */
+    fun setKeyValueStoreProvider(keyValueStoreProvider: KeyValueStoreProvider) {
+        this.keyValueStoreProvider = keyValueStoreProvider
+    }
+
+    /**
+     * Returns the key-value store for given preference.
+     *
+     * Must call [setKeyValueStoreProvider] before invoking this method, otherwise
+     * [NullPointerException] is raised.
+     */
+    fun getKeyValueStore(context: Context, preference: PreferenceMetadata): KeyValueStore? =
+        keyValueStoreProvider.getKeyValueStore(context, preference)
+
+    /** Sets supplier to provide available preference screens. */
+    fun setPreferenceScreensSupplier(supplier: Supplier<List<PreferenceScreenMetadata>>) {
+        preferenceScreensSupplier =
+            Suppliers.memoize {
+                val screensBuilder = ImmutableMap.builder<String, PreferenceScreenMetadata>()
+                for (screen in supplier.get()) screensBuilder.put(screen.key, screen)
+                screensBuilder.buildOrThrow()
+            }
+    }
+
+    /** Sets available preference screens. */
+    fun setPreferenceScreens(vararg screens: PreferenceScreenMetadata) {
+        val screensBuilder = ImmutableMap.builder<String, PreferenceScreenMetadata>()
+        for (screen in screens) screensBuilder.put(screen.key, screen)
+        preferenceScreensSupplier = Suppliers.ofInstance(screensBuilder.buildOrThrow())
+    }
+
+    /** Returns [PreferenceScreenMetadata] of particular key. */
+    operator fun get(key: String?): PreferenceScreenMetadata? =
+        if (key != null) preferenceScreens[key] else null
+
+    /**
+     * Sets the provider to check read write permit. Read and write requests are denied by default.
+     */
+    fun setReadWritePermitProvider(readWritePermitProvider: ReadWritePermitProvider?) {
+        this.readWritePermitProvider = readWritePermitProvider
+    }
+
+    override fun getReadPermit(
+        context: Context,
+        myUid: Int,
+        callingUid: Int,
+        preference: PreferenceMetadata,
+    ) =
+        readWritePermitProvider?.getReadPermit(context, myUid, callingUid, preference)
+            ?: ReadWritePermit.DISALLOW
+
+    override fun getWritePermit(
+        context: Context,
+        value: Any?,
+        myUid: Int,
+        callingUid: Int,
+        preference: PreferenceMetadata,
+    ) =
+        readWritePermitProvider?.getWritePermit(context, value, myUid, callingUid, preference)
+            ?: ReadWritePermit.DISALLOW
+}
+
+/** Provider of [KeyValueStore]. */
+fun interface KeyValueStoreProvider {
+
+    /**
+     * Returns the key-value store for given preference.
+     *
+     * Here are some use cases:
+     * - provide the default storage for all preferences
+     * - determine the storage per preference keys or the interfaces implemented by the preference
+     */
+    fun getKeyValueStore(context: Context, preference: PreferenceMetadata): KeyValueStore?
+}
+
+/** Provider of read and write permit. */
+interface ReadWritePermitProvider {
+
+    @ReadWritePermit
+    fun getReadPermit(
+        context: Context,
+        myUid: Int,
+        callingUid: Int,
+        preference: PreferenceMetadata,
+    ): Int
+
+    @ReadWritePermit
+    fun getWritePermit(
+        context: Context,
+        value: Any?,
+        myUid: Int,
+        callingUid: Int,
+        preference: PreferenceMetadata,
+    ): Int
+
+    companion object {
+        @JvmField
+        val ALLOW_ALL_READ_WRITE =
+            object : ReadWritePermitProvider {
+                override fun getReadPermit(
+                    context: Context,
+                    myUid: Int,
+                    callingUid: Int,
+                    preference: PreferenceMetadata,
+                ) = ReadWritePermit.ALLOW
+
+                override fun getWritePermit(
+                    context: Context,
+                    value: Any?,
+                    myUid: Int,
+                    callingUid: Int,
+                    preference: PreferenceMetadata,
+                ) = ReadWritePermit.ALLOW
+            }
+    }
+}
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceStateProviders.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceStateProviders.kt
new file mode 100644
index 0000000..a3aa85d
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceStateProviders.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 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.settingslib.metadata
+
+import android.content.Context
+
+/**
+ * Interface to provide dynamic preference title.
+ *
+ * Implement this interface implies that the preference title should not be cached for indexing.
+ */
+interface PreferenceTitleProvider {
+
+    /** Provides preference title. */
+    fun getTitle(context: Context): CharSequence?
+}
+
+/**
+ * Interface to provide dynamic preference summary.
+ *
+ * Implement this interface implies that the preference summary should not be cached for indexing.
+ */
+interface PreferenceSummaryProvider {
+
+    /** Provides preference summary. */
+    fun getSummary(context: Context): CharSequence?
+}
+
+/**
+ * Interface to provide the state of preference availability.
+ *
+ * UI framework normally does not show the preference widget if it is unavailable.
+ */
+interface PreferenceAvailabilityProvider {
+
+    /** Returns if the preference is available. */
+    fun isAvailable(context: Context): Boolean
+}
+
+/**
+ * Interface to provide the managed configuration state of the preference.
+ *
+ * See [Managed configurations](https://developer.android.com/work/managed-configurations) for the
+ * Android Enterprise support.
+ */
+interface PreferenceRestrictionProvider {
+
+    /** Returns if preference is restricted by managed configs. */
+    fun isRestricted(context: Context): Boolean
+}
+
+/**
+ * Preference lifecycle to deal with preference state.
+ *
+ * Implement this interface when preference depends on runtime conditions.
+ */
+interface PreferenceLifecycleProvider {
+
+    /**
+     * Called when preference is attached to UI.
+     *
+     * Subclass could override this API to register runtime condition listeners, and invoke
+     * `onPreferenceStateChanged(this)` on the given [preferenceStateObserver] to update UI when
+     * internal state (e.g. availability, enabled state, title, summary) is changed.
+     */
+    fun onAttach(context: Context, preferenceStateObserver: PreferenceStateObserver)
+
+    /**
+     * Called when preference is detached from UI.
+     *
+     * Clean up and release resource.
+     */
+    fun onDetach(context: Context)
+
+    /** Observer of preference state. */
+    interface PreferenceStateObserver {
+
+        /** Callbacks when preference state is changed. */
+        fun onPreferenceStateChanged(preference: PreferenceMetadata)
+    }
+}
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt
new file mode 100644
index 0000000..ad996c7
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 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.settingslib.metadata
+
+import android.content.Context
+import androidx.annotation.StringRes
+
+/**
+ * Common base class for preferences that have two selectable states, save a boolean value, and may
+ * have dependent preferences that are enabled/disabled based on the current state.
+ */
+interface TwoStatePreference : PreferenceMetadata, PersistentPreference<Boolean>, BooleanValue {
+
+    override fun shouldDisableDependents(context: Context) =
+        storage(context).getValue(key, Boolean::class.javaObjectType) != true ||
+            super.shouldDisableDependents(context)
+}
+
+/** A preference that provides a two-state toggleable option. */
+open class SwitchPreference
+@JvmOverloads
+constructor(
+    override val key: String,
+    @StringRes override val title: Int = 0,
+    @StringRes override val summary: Int = 0,
+) : TwoStatePreference
diff --git a/packages/SettingsLib/Preference/Android.bp b/packages/SettingsLib/Preference/Android.bp
new file mode 100644
index 0000000..9665dbd
--- /dev/null
+++ b/packages/SettingsLib/Preference/Android.bp
@@ -0,0 +1,23 @@
+package {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+    name: "SettingsLibPreference-srcs",
+    srcs: ["src/**/*.kt"],
+}
+
+android_library {
+    name: "SettingsLibPreference",
+    defaults: [
+        "SettingsLintDefaults",
+    ],
+    srcs: [":SettingsLibPreference-srcs"],
+    static_libs: [
+        "SettingsLibDataStore",
+        "SettingsLibMetadata",
+        "androidx.annotation_annotation",
+        "androidx.preference_preference",
+    ],
+    kotlincflags: ["-Xjvm-default=all"],
+}
diff --git a/packages/SettingsLib/Preference/AndroidManifest.xml b/packages/SettingsLib/Preference/AndroidManifest.xml
new file mode 100644
index 0000000..2d7f7ba
--- /dev/null
+++ b/packages/SettingsLib/Preference/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.settingslib.preference">
+
+  <uses-sdk android:minSdkVersion="21" />
+</manifest>
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt
new file mode 100644
index 0000000..9be0e71
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2024 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.settingslib.preference
+
+import android.content.Context
+import androidx.preference.DialogPreference
+import androidx.preference.ListPreference
+import androidx.preference.Preference
+import androidx.preference.PreferenceScreen
+import androidx.preference.SeekBarPreference
+import com.android.settingslib.metadata.DiscreteIntValue
+import com.android.settingslib.metadata.DiscreteValue
+import com.android.settingslib.metadata.PreferenceAvailabilityProvider
+import com.android.settingslib.metadata.PreferenceMetadata
+import com.android.settingslib.metadata.PreferenceScreenMetadata
+import com.android.settingslib.metadata.RangeValue
+
+/** Binding of preference widget and preference metadata. */
+interface PreferenceBinding {
+
+    /**
+     * Provides a new [Preference] widget instance.
+     *
+     * By default, it returns a new [Preference] object. Subclass could override this method to
+     * provide customized widget and do **one-off** initialization (e.g.
+     * [Preference.setOnPreferenceClickListener]). To update widget everytime when state is changed,
+     * override the [bind] method.
+     *
+     * Notes:
+     * - DO NOT set any properties defined in [PreferenceMetadata]. For example,
+     *   title/summary/icon/extras/isEnabled/isVisible/isPersistent/dependency. These properties
+     *   will be reset by [bind].
+     * - Override [bind] if needed to provide more information for customized widget.
+     */
+    fun createWidget(context: Context): Preference = Preference(context)
+
+    /**
+     * Binds preference widget with given metadata.
+     *
+     * Whenever metadata state is changed, this callback is invoked to update widget. By default,
+     * the common states like title, summary, enabled, etc. are already applied. Subclass should
+     * override this method to bind more data (e.g. read preference value from storage and apply it
+     * to widget).
+     *
+     * @param preference preference widget created by [createWidget]
+     * @param metadata metadata to apply
+     */
+    fun bind(preference: Preference, metadata: PreferenceMetadata) {
+        metadata.apply {
+            preference.key = key
+            if (icon != 0) {
+                preference.setIcon(icon)
+            } else {
+                preference.icon = null
+            }
+            val context = preference.context
+            preference.peekExtras()?.clear()
+            extras(context)?.let { preference.extras.putAll(it) }
+            preference.title = getPreferenceTitle(context)
+            preference.summary = getPreferenceSummary(context)
+            preference.isEnabled = isEnabled(context)
+            preference.isVisible =
+                (this as? PreferenceAvailabilityProvider)?.isAvailable(context) != false
+            preference.isPersistent = isPersistent(context)
+            metadata.order(context)?.let { preference.order = it }
+            // PreferenceRegistry will notify dependency change, so we do not need to set
+            // dependency here. This simplifies dependency management and avoid the
+            // IllegalStateException when call Preference.setDependency
+            preference.dependency = null
+            if (preference !is PreferenceScreen) { // avoid recursive loop when build graph
+                preference.fragment = (this as? PreferenceScreenCreator)?.fragmentClass()?.name
+                preference.intent = intent(context)
+            }
+            if (preference is DialogPreference) {
+                preference.dialogTitle = preference.title
+            }
+            if (preference is ListPreference && this is DiscreteValue<*>) {
+                preference.setEntries(valuesDescription)
+                if (this is DiscreteIntValue) {
+                    val intValues = context.resources.getIntArray(values)
+                    preference.entryValues = Array(intValues.size) { intValues[it].toString() }
+                } else {
+                    preference.setEntryValues(values)
+                }
+            } else if (preference is SeekBarPreference && this is RangeValue) {
+                preference.min = minValue
+                preference.max = maxValue
+                preference.seekBarIncrement = incrementStep
+            }
+        }
+    }
+}
+
+/** Abstract preference screen to provide preference hierarchy and binding factory. */
+interface PreferenceScreenCreator : PreferenceScreenMetadata, PreferenceScreenProvider {
+
+    val preferenceBindingFactory: PreferenceBindingFactory
+        get() = DefaultPreferenceBindingFactory
+
+    override fun createPreferenceScreen(factory: PreferenceScreenFactory) =
+        factory.getOrCreatePreferenceScreen().apply {
+            inflatePreferenceHierarchy(preferenceBindingFactory, getPreferenceHierarchy(context))
+        }
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt
new file mode 100644
index 0000000..4c2e1ba
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 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.settingslib.preference
+
+import com.android.settingslib.metadata.PreferenceGroup
+import com.android.settingslib.metadata.PreferenceMetadata
+import com.android.settingslib.metadata.SwitchPreference
+
+/** Factory to map [PreferenceMetadata] to [PreferenceBinding]. */
+interface PreferenceBindingFactory {
+
+    /** Returns the [PreferenceBinding] associated with the [PreferenceMetadata]. */
+    fun getPreferenceBinding(metadata: PreferenceMetadata): PreferenceBinding?
+}
+
+/** Default [PreferenceBindingFactory]. */
+object DefaultPreferenceBindingFactory : PreferenceBindingFactory {
+
+    override fun getPreferenceBinding(metadata: PreferenceMetadata) =
+        metadata as? PreferenceBinding
+            ?: when (metadata) {
+                is SwitchPreference -> SwitchPreferenceBinding.INSTANCE
+                is PreferenceGroup -> PreferenceGroupBinding.INSTANCE
+                is PreferenceScreenCreator -> PreferenceScreenBinding.INSTANCE
+                else -> DefaultPreferenceBinding
+            }
+}
+
+/** A preference key based binding factory. */
+class KeyedPreferenceBindingFactory(private val bindings: Map<String, PreferenceBinding>) :
+    PreferenceBindingFactory {
+
+    override fun getPreferenceBinding(metadata: PreferenceMetadata) =
+        bindings[metadata.key] ?: DefaultPreferenceBindingFactory.getPreferenceBinding(metadata)
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
new file mode 100644
index 0000000..ede970e
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2024 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.settingslib.preference
+
+import android.content.Context
+import androidx.preference.Preference
+import androidx.preference.PreferenceCategory
+import androidx.preference.PreferenceScreen
+import androidx.preference.SwitchPreferenceCompat
+import com.android.settingslib.metadata.EXTRA_BINDING_SCREEN_KEY
+import com.android.settingslib.metadata.PersistentPreference
+import com.android.settingslib.metadata.PreferenceMetadata
+import com.android.settingslib.metadata.PreferenceScreenMetadata
+import com.android.settingslib.metadata.PreferenceTitleProvider
+
+/** Binding of preference group associated with [PreferenceCategory]. */
+interface PreferenceScreenBinding : PreferenceBinding {
+
+    override fun bind(preference: Preference, metadata: PreferenceMetadata) {
+        super.bind(preference, metadata)
+        val context = preference.context
+        val screenMetadata = metadata as PreferenceScreenMetadata
+        // Pass the preference key to fragment, so that the fragment could find associated
+        // preference screen registered in PreferenceScreenRegistry
+        preference.extras.putString(EXTRA_BINDING_SCREEN_KEY, preference.key)
+        if (preference is PreferenceScreen) {
+            val screenTitle = screenMetadata.screenTitle
+            preference.title =
+                if (screenTitle != 0) {
+                    context.getString(screenTitle)
+                } else {
+                    screenMetadata.getScreenTitle(context)
+                        ?: (this as? PreferenceTitleProvider)?.getTitle(context)
+                }
+        }
+    }
+
+    companion object {
+        @JvmStatic val INSTANCE = object : PreferenceScreenBinding {}
+    }
+}
+
+/** Binding of preference group associated with [PreferenceCategory]. */
+interface PreferenceGroupBinding : PreferenceBinding {
+
+    override fun createWidget(context: Context) = PreferenceCategory(context)
+
+    companion object {
+        @JvmStatic val INSTANCE = object : PreferenceGroupBinding {}
+    }
+}
+
+/** A boolean value type preference associated with [SwitchPreferenceCompat]. */
+interface SwitchPreferenceBinding : PreferenceBinding {
+
+    override fun createWidget(context: Context): Preference = SwitchPreferenceCompat(context)
+
+    override fun bind(preference: Preference, metadata: PreferenceMetadata) {
+        super.bind(preference, metadata)
+        (metadata as? PersistentPreference<*>)
+            ?.storage(preference.context)
+            ?.getValue(metadata.key, Boolean::class.javaObjectType)
+            ?.let { (preference as SwitchPreferenceCompat).isChecked = it }
+    }
+
+    companion object {
+        @JvmStatic val INSTANCE = object : SwitchPreferenceBinding {}
+    }
+}
+
+/** Default [PreferenceBinding] for [Preference]. */
+object DefaultPreferenceBinding : PreferenceBinding
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceDataStoreAdapter.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceDataStoreAdapter.kt
new file mode 100644
index 0000000..02acfca
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceDataStoreAdapter.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 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.settingslib.preference
+
+import androidx.preference.PreferenceDataStore
+import com.android.settingslib.datastore.KeyValueStore
+
+/** Adapter to translate [KeyValueStore] into [PreferenceDataStore]. */
+class PreferenceDataStoreAdapter(private val keyValueStore: KeyValueStore) : PreferenceDataStore() {
+
+    override fun getBoolean(key: String, defValue: Boolean): Boolean =
+        keyValueStore.getValue(key, Boolean::class.javaObjectType) ?: defValue
+
+    override fun getFloat(key: String, defValue: Float): Float =
+        keyValueStore.getValue(key, Float::class.javaObjectType) ?: defValue
+
+    override fun getInt(key: String, defValue: Int): Int =
+        keyValueStore.getValue(key, Int::class.javaObjectType) ?: defValue
+
+    override fun getLong(key: String, defValue: Long): Long =
+        keyValueStore.getValue(key, Long::class.javaObjectType) ?: defValue
+
+    override fun getString(key: String, defValue: String?): String? =
+        keyValueStore.getValue(key, String::class.javaObjectType) ?: defValue
+
+    override fun getStringSet(key: String, defValues: Set<String>?): Set<String>? =
+        (keyValueStore.getValue(key, Set::class.javaObjectType) as Set<String>?) ?: defValues
+
+    override fun putBoolean(key: String, value: Boolean) =
+        keyValueStore.setValue(key, Boolean::class.javaObjectType, value)
+
+    override fun putFloat(key: String, value: Float) =
+        keyValueStore.setValue(key, Float::class.javaObjectType, value)
+
+    override fun putInt(key: String, value: Int) =
+        keyValueStore.setValue(key, Int::class.javaObjectType, value)
+
+    override fun putLong(key: String, value: Long) =
+        keyValueStore.setValue(key, Long::class.javaObjectType, value)
+
+    override fun putString(key: String, value: String?) =
+        keyValueStore.setValue(key, String::class.javaObjectType, value)
+
+    override fun putStringSet(key: String, values: Set<String>?) =
+        keyValueStore.setValue(key, Set::class.javaObjectType, values)
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceFragment.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceFragment.kt
new file mode 100644
index 0000000..2072009
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 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.settingslib.preference
+
+import android.content.Context
+import android.os.Bundle
+import androidx.annotation.XmlRes
+import androidx.preference.PreferenceFragmentCompat
+import androidx.preference.PreferenceScreen
+import com.android.settingslib.metadata.EXTRA_BINDING_SCREEN_KEY
+import com.android.settingslib.metadata.PreferenceScreenBindingKeyProvider
+import com.android.settingslib.metadata.PreferenceScreenRegistry
+import com.android.settingslib.preference.PreferenceScreenBindingHelper.Companion.bindRecursively
+
+/** Fragment to display a preference screen. */
+open class PreferenceFragment :
+    PreferenceFragmentCompat(), PreferenceScreenProvider, PreferenceScreenBindingKeyProvider {
+
+    private var preferenceScreenBindingHelper: PreferenceScreenBindingHelper? = null
+
+    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+        preferenceScreen = createPreferenceScreen()
+    }
+
+    fun createPreferenceScreen(): PreferenceScreen? =
+        createPreferenceScreen(PreferenceScreenFactory(this))
+
+    override fun createPreferenceScreen(factory: PreferenceScreenFactory): PreferenceScreen? {
+        val context = factory.context
+        fun createPreferenceScreenFromResource() =
+            factory.inflate(getPreferenceScreenResId(context))
+
+        if (!usePreferenceScreenMetadata()) return createPreferenceScreenFromResource()
+
+        val screenKey = getPreferenceScreenBindingKey(context)
+        val screenCreator =
+            (PreferenceScreenRegistry[screenKey] as? PreferenceScreenCreator)
+                ?: return createPreferenceScreenFromResource()
+
+        val preferenceBindingFactory = screenCreator.preferenceBindingFactory
+        val preferenceHierarchy = screenCreator.getPreferenceHierarchy(context)
+        val preferenceScreen =
+            if (screenCreator.hasCompleteHierarchy()) {
+                factory.getOrCreatePreferenceScreen().apply {
+                    inflatePreferenceHierarchy(preferenceBindingFactory, preferenceHierarchy)
+                }
+            } else {
+                createPreferenceScreenFromResource()?.also {
+                    bindRecursively(it, preferenceBindingFactory, preferenceHierarchy)
+                } ?: return null
+            }
+        preferenceScreenBindingHelper =
+            PreferenceScreenBindingHelper(
+                context,
+                preferenceBindingFactory,
+                preferenceScreen,
+                preferenceHierarchy,
+            )
+        return preferenceScreen
+    }
+
+    /**
+     * Returns if preference screen metadata can be used to set up preference screen.
+     *
+     * This is for flagging purpose. If false (e.g. flag is disabled), xml resource is used to build
+     * preference screen.
+     */
+    protected open fun usePreferenceScreenMetadata(): Boolean = true
+
+    /** Returns the xml resource to create preference screen. */
+    @XmlRes protected open fun getPreferenceScreenResId(context: Context): Int = 0
+
+    override fun getPreferenceScreenBindingKey(context: Context): String? =
+        arguments?.getString(EXTRA_BINDING_SCREEN_KEY)
+
+    override fun onDestroy() {
+        preferenceScreenBindingHelper?.close()
+        super.onDestroy()
+    }
+
+    companion object {
+        /** Returns [PreferenceFragment] instance to display the preference screen of given key. */
+        fun of(screenKey: String): PreferenceFragment? {
+            val screenMetadata = PreferenceScreenRegistry[screenKey] ?: return null
+            if (
+                screenMetadata is PreferenceScreenCreator && screenMetadata.hasCompleteHierarchy()
+            ) {
+                return PreferenceFragment().apply {
+                    arguments = Bundle().apply { putString(EXTRA_BINDING_SCREEN_KEY, screenKey) }
+                }
+            }
+            return null
+        }
+    }
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceHierarchyInflater.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceHierarchyInflater.kt
new file mode 100644
index 0000000..5ef7823
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceHierarchyInflater.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 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.settingslib.preference
+
+import androidx.preference.PreferenceDataStore
+import androidx.preference.PreferenceGroup
+import com.android.settingslib.datastore.KeyValueStore
+import com.android.settingslib.metadata.PersistentPreference
+import com.android.settingslib.metadata.PreferenceHierarchy
+import com.android.settingslib.metadata.PreferenceMetadata
+
+/** Inflates [PreferenceHierarchy] into given [PreferenceGroup] recursively. */
+fun PreferenceGroup.inflatePreferenceHierarchy(
+    preferenceBindingFactory: PreferenceBindingFactory,
+    hierarchy: PreferenceHierarchy,
+    storages: MutableMap<KeyValueStore, PreferenceDataStore> = mutableMapOf(),
+) {
+    fun PreferenceMetadata.preferenceBinding() = preferenceBindingFactory.getPreferenceBinding(this)
+
+    hierarchy.metadata.let { it.preferenceBinding()?.bind(this, it) }
+    hierarchy.forEach {
+        val metadata = it.metadata
+        val preferenceBinding = metadata.preferenceBinding() ?: return@forEach
+        val widget = preferenceBinding.createWidget(context)
+        if (it is PreferenceHierarchy) {
+            val preferenceGroup = widget as PreferenceGroup
+            // MUST add preference before binding, otherwise exception is raised when add child
+            addPreference(preferenceGroup)
+            preferenceGroup.inflatePreferenceHierarchy(preferenceBindingFactory, it)
+        } else {
+            preferenceBinding.bind(widget, metadata)
+            (metadata as? PersistentPreference<*>)?.storage(context)?.let { storage ->
+                widget.preferenceDataStore =
+                    storages.getOrPut(storage) { PreferenceDataStoreAdapter(storage) }
+            }
+            // MUST add preference after binding for persistent preference to get initial value
+            // (preference key is set within bind method)
+            addPreference(widget)
+        }
+    }
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
new file mode 100644
index 0000000..3610894
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2024 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.settingslib.preference
+
+import android.content.Context
+import android.os.Handler
+import android.os.Looper
+import androidx.preference.Preference
+import androidx.preference.PreferenceGroup
+import androidx.preference.PreferenceScreen
+import com.android.settingslib.datastore.KeyedDataObservable
+import com.android.settingslib.datastore.KeyedObservable
+import com.android.settingslib.datastore.KeyedObserver
+import com.android.settingslib.metadata.PersistentPreference
+import com.android.settingslib.metadata.PreferenceHierarchy
+import com.android.settingslib.metadata.PreferenceLifecycleProvider
+import com.android.settingslib.metadata.PreferenceMetadata
+import com.android.settingslib.metadata.PreferenceScreenRegistry
+import com.google.common.collect.ImmutableMap
+import com.google.common.collect.ImmutableMultimap
+import java.util.concurrent.Executor
+
+/**
+ * Helper to bind preferences on given [preferenceScreen].
+ *
+ * When there is any preference change event detected (e.g. preference value changed, runtime
+ * states, dependency is updated), this helper class will re-bind [PreferenceMetadata] to update
+ * widget UI.
+ */
+class PreferenceScreenBindingHelper(
+    context: Context,
+    private val preferenceBindingFactory: PreferenceBindingFactory,
+    private val preferenceScreen: PreferenceScreen,
+    preferenceHierarchy: PreferenceHierarchy,
+) : KeyedDataObservable<String>(), AutoCloseable {
+
+    private val handler = Handler(Looper.getMainLooper())
+    private val executor =
+        object : Executor {
+            override fun execute(command: Runnable) {
+                handler.post(command)
+            }
+        }
+
+    private val preferences: ImmutableMap<String, PreferenceMetadata>
+    private val dependencies: ImmutableMultimap<String, String>
+    private val storages = mutableSetOf<KeyedObservable<String>>()
+
+    private val preferenceObserver: KeyedObserver<String?>
+
+    private val storageObserver =
+        KeyedObserver<String?> { key, _ ->
+            if (key != null) {
+                notifyChange(key, CHANGE_REASON_VALUE)
+            }
+        }
+
+    private val stateObserver =
+        object : PreferenceLifecycleProvider.PreferenceStateObserver {
+            override fun onPreferenceStateChanged(preference: PreferenceMetadata) {
+                notifyChange(preference.key, CHANGE_REASON_STATE)
+            }
+        }
+
+    init {
+        val preferencesBuilder = ImmutableMap.builder<String, PreferenceMetadata>()
+        val dependenciesBuilder = ImmutableMultimap.builder<String, String>()
+        fun PreferenceMetadata.addDependency(dependency: PreferenceMetadata) {
+            dependenciesBuilder.put(key, dependency.key)
+        }
+
+        fun PreferenceMetadata.add() {
+            preferencesBuilder.put(key, this)
+            dependencyOfEnabledState(context)?.addDependency(this)
+            if (this is PreferenceLifecycleProvider) onAttach(context, stateObserver)
+            if (this is PersistentPreference<*>) storages.add(storage(context))
+        }
+
+        fun PreferenceHierarchy.addPreferences() {
+            metadata.add()
+            forEach {
+                if (it is PreferenceHierarchy) {
+                    it.addPreferences()
+                } else {
+                    it.metadata.add()
+                }
+            }
+        }
+
+        preferenceHierarchy.addPreferences()
+        this.preferences = preferencesBuilder.buildOrThrow()
+        this.dependencies = dependenciesBuilder.build()
+
+        preferenceObserver = KeyedObserver { key, reason -> onPreferenceChange(key, reason) }
+        addObserver(preferenceObserver, executor)
+        for (storage in storages) storage.addObserver(storageObserver, executor)
+    }
+
+    private fun onPreferenceChange(key: String?, reason: Int) {
+        if (key == null) return
+
+        // bind preference to update UI
+        preferenceScreen.findPreference<Preference>(key)?.let {
+            preferenceBindingFactory.bind(it, preferences[key])
+        }
+
+        // check reason to avoid potential infinite loop
+        if (reason != CHANGE_REASON_DEPENDENT) {
+            notifyDependents(key, mutableSetOf())
+        }
+    }
+
+    /** Notifies dependents recursively. */
+    private fun notifyDependents(key: String, notifiedKeys: MutableSet<String>) {
+        if (!notifiedKeys.add(key)) return
+        for (dependency in dependencies[key]) {
+            notifyChange(dependency, CHANGE_REASON_DEPENDENT)
+            notifyDependents(dependency, notifiedKeys)
+        }
+    }
+
+    override fun close() {
+        removeObserver(preferenceObserver)
+        val context = preferenceScreen.context
+        for (preference in preferences.values) {
+            if (preference is PreferenceLifecycleProvider) preference.onDetach(context)
+        }
+        for (storage in storages) storage.removeObserver(storageObserver)
+    }
+
+    companion object {
+        /** Preference value is changed. */
+        private const val CHANGE_REASON_VALUE = 0
+        /** Preference state (title/summary, enable state, etc.) is changed. */
+        private const val CHANGE_REASON_STATE = 1
+        /** Dependent preference state is changed. */
+        private const val CHANGE_REASON_DEPENDENT = 2
+
+        /** Updates preference screen that has incomplete hierarchy. */
+        @JvmStatic
+        fun bind(preferenceScreen: PreferenceScreen) {
+            PreferenceScreenRegistry[preferenceScreen.key]?.run {
+                if (!hasCompleteHierarchy()) {
+                    val preferenceBindingFactory =
+                        (this as? PreferenceScreenCreator)?.preferenceBindingFactory ?: return
+                    bindRecursively(
+                        preferenceScreen,
+                        preferenceBindingFactory,
+                        getPreferenceHierarchy(preferenceScreen.context),
+                    )
+                }
+            }
+        }
+
+        internal fun bindRecursively(
+            preferenceScreen: PreferenceScreen,
+            preferenceBindingFactory: PreferenceBindingFactory,
+            preferenceHierarchy: PreferenceHierarchy,
+        ) =
+            preferenceScreen.bindRecursively(
+                preferenceBindingFactory,
+                preferenceHierarchy.getAllPreferences().associateBy { it.key },
+            )
+
+        private fun PreferenceGroup.bindRecursively(
+            preferenceBindingFactory: PreferenceBindingFactory,
+            preferences: Map<String, PreferenceMetadata>,
+        ) {
+            preferenceBindingFactory.bind(this, preferences[key])
+            val count = preferenceCount
+            for (index in 0 until count) {
+                val preference = getPreference(index)
+                if (preference is PreferenceGroup) {
+                    preference.bindRecursively(preferenceBindingFactory, preferences)
+                } else {
+                    preferenceBindingFactory.bind(preference, preferences[preference.key])
+                }
+            }
+        }
+
+        private fun PreferenceBindingFactory.bind(
+            preference: Preference,
+            metadata: PreferenceMetadata?,
+        ) = metadata?.let { getPreferenceBinding(it)?.bind(preference, it) }
+    }
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenFactory.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenFactory.kt
new file mode 100644
index 0000000..7f99d7a
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenFactory.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 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.settingslib.preference
+
+import android.content.Context
+import androidx.preference.Preference
+import androidx.preference.PreferenceFragmentCompat
+import androidx.preference.PreferenceManager
+import androidx.preference.PreferenceScreen
+import com.android.settingslib.metadata.PreferenceScreenRegistry
+
+/** Factory to create preference screen. */
+class PreferenceScreenFactory {
+    /** Preference manager to create/inflate preference screen. */
+    val preferenceManager: PreferenceManager
+
+    /**
+     * Optional existing hierarchy to merge the new hierarchies into.
+     *
+     * Provide existing hierarchy will preserve the internal state (e.g. scrollbar position) for
+     * [PreferenceFragmentCompat].
+     */
+    private val rootScreen: PreferenceScreen?
+
+    /**
+     * Factory constructor from preference fragment.
+     *
+     * The fragment must be within a valid lifecycle.
+     */
+    constructor(preferenceFragment: PreferenceFragmentCompat) {
+        preferenceManager = preferenceFragment.preferenceManager
+        rootScreen = preferenceFragment.preferenceScreen
+    }
+
+    /** Factory constructor from [Context]. */
+    constructor(context: Context) : this(PreferenceManager(context))
+
+    /** Factory constructor from [PreferenceManager]. */
+    constructor(preferenceManager: PreferenceManager) {
+        this.preferenceManager = preferenceManager
+        rootScreen = null
+    }
+
+    /** Context of the factory to create preference screen. */
+    val context: Context
+        get() = preferenceManager.context
+
+    /** Returns the existing hierarchy or create a new empty preference screen. */
+    fun getOrCreatePreferenceScreen(): PreferenceScreen =
+        rootScreen ?: preferenceManager.createPreferenceScreen(context)
+
+    /**
+     * Inflates [PreferenceScreen] from xml resource.
+     *
+     * @param xmlRes The resource ID of the XML to inflate
+     * @return The root hierarchy (if one was not provided, the new hierarchy's root)
+     */
+    fun inflate(xmlRes: Int): PreferenceScreen? =
+        if (xmlRes != 0) {
+            preferenceManager.inflateFromResource(preferenceManager.context, xmlRes, rootScreen)
+        } else {
+            rootScreen
+        }
+
+    /**
+     * Creates [PreferenceScreen] of given key.
+     *
+     * The screen must be registered in [PreferenceScreenFactory] and provide a complete hierarchy.
+     */
+    fun createBindingScreen(screenKey: String?): PreferenceScreen? {
+        val metadata = PreferenceScreenRegistry[screenKey] ?: return null
+        if (metadata is PreferenceScreenCreator && metadata.hasCompleteHierarchy()) {
+            return metadata.createPreferenceScreen(this)
+        }
+        return null
+    }
+
+    companion object {
+        /** Creates [PreferenceScreen] from [PreferenceScreenRegistry]. */
+        @JvmStatic
+        fun createBindingScreen(preference: Preference): PreferenceScreen? {
+            val preferenceScreenCreator =
+                (PreferenceScreenRegistry[preference.key] as? PreferenceScreenCreator)
+                    ?: return null
+            if (!preferenceScreenCreator.hasCompleteHierarchy()) return null
+            val factory = PreferenceScreenFactory(preference.context)
+            val preferenceScreen = preferenceScreenCreator.createPreferenceScreen(factory)
+            factory.preferenceManager.setPreferences(preferenceScreen)
+            return preferenceScreen
+        }
+    }
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenProvider.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenProvider.kt
new file mode 100644
index 0000000..0573292
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenProvider.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 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.settingslib.preference
+
+import android.content.Context
+import androidx.preference.PreferenceScreen
+
+/**
+ * Interface to provide [PreferenceScreen].
+ *
+ * When implemented by Activity/Fragment, the Activity/Fragment [Context] APIs (e.g. `getContext()`,
+ * `getActivity()`) MUST not be used: preference screen creation could happen in background service,
+ * where the Activity/Fragment lifecycle callbacks (`onCreate`, `onDestroy`, etc.) are not invoked
+ * and context APIs return null.
+ */
+interface PreferenceScreenProvider {
+
+    /**
+     * Creates [PreferenceScreen].
+     *
+     * Preference screen creation could happen in background service. The implementation MUST use
+     * [PreferenceScreenFactory.context] to obtain context.
+     */
+    fun createPreferenceScreen(factory: PreferenceScreenFactory): PreferenceScreen?
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
index 90cee16..1f3e2425 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
@@ -25,6 +25,13 @@
     val paddingLarge = 16.dp
     val paddingExtraLarge = 24.dp
 
+    val spinnerHorizontalPadding = paddingExtraLarge
+    val spinnerVerticalPadding = paddingLarge
+
+    val actionIconWidth = 32.dp
+    val actionIconHeight = 40.dp
+    val actionIconPadding = 4.dp
+
     val itemIconSize = 24.dp
     val itemIconContainerSize = 72.dp
     val itemPaddingStart = paddingExtraLarge
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
index 5f320f7..9bbc16d 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
@@ -17,15 +17,24 @@
 package com.android.settingslib.spa.widget.scaffold
 
 import androidx.appcompat.R
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.automirrored.outlined.ArrowBack
 import androidx.compose.material.icons.outlined.Clear
 import androidx.compose.material.icons.outlined.FindInPage
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
 import androidx.compose.ui.res.stringResource
 import com.android.settingslib.spa.framework.compose.LocalNavController
+import com.android.settingslib.spa.framework.theme.SettingsDimension
+import com.android.settingslib.spa.framework.theme.SettingsShape
+import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled
 
 /** Action that navigates back to last page. */
 @Composable
@@ -50,6 +59,11 @@
         Icon(
             imageVector = Icons.AutoMirrored.Outlined.ArrowBack,
             contentDescription = contentDescription,
+            modifier = if (isSpaExpressiveEnabled) Modifier
+                .size(SettingsDimension.actionIconWidth, SettingsDimension.actionIconHeight)
+                .clip(SettingsShape.CornerExtraLarge)
+                .background(MaterialTheme.colorScheme.onSurfaceVariant)
+                .padding(SettingsDimension.actionIconPadding) else Modifier
         )
     }
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsScaffold.kt
index 4cf741e..7d8ee79 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsScaffold.kt
@@ -39,6 +39,7 @@
 import com.android.settingslib.spa.framework.compose.horizontalValues
 import com.android.settingslib.spa.framework.compose.verticalValues
 import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled
 import com.android.settingslib.spa.framework.theme.settingsBackground
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
@@ -55,6 +56,10 @@
 ) {
     ActivityTitle(title)
     val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
+    if (isSpaExpressiveEnabled) {
+        LaunchedEffect(scrollBehavior.state.heightOffsetLimit) { scrollBehavior.collapse() }
+    }
+
     Scaffold(
         modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
         topBar = { SettingsTopAppBar(title, scrollBehavior, actions) },
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt
index c48a147..6b2db90 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt
@@ -46,6 +46,7 @@
 import androidx.compose.ui.unit.dp
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled
 
 data class SpinnerOption(
     val id: Int,
@@ -70,7 +71,10 @@
             )
             .selectableGroup(),
     ) {
-        val contentPadding = PaddingValues(horizontal = SettingsDimension.itemPaddingEnd)
+        val contentPadding = if (isSpaExpressiveEnabled) PaddingValues(
+            horizontal = SettingsDimension.spinnerHorizontalPadding,
+            vertical = SettingsDimension.spinnerVerticalPadding
+        ) else PaddingValues(horizontal = SettingsDimension.itemPaddingEnd)
         Button(
             modifier = Modifier.semantics { role = Role.DropdownList },
             onClick = { expanded = true },
@@ -129,7 +133,11 @@
         text = option?.text ?: "",
         modifier = modifier
             .padding(end = SettingsDimension.itemPaddingEnd)
-            .padding(vertical = SettingsDimension.itemPaddingAround),
+            .then(
+                if (!isSpaExpressiveEnabled)
+                    Modifier.padding(vertical = SettingsDimension.itemPaddingAround)
+                else Modifier
+            ),
         color = color,
         style = MaterialTheme.typography.labelLarge,
     )
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 1161a30..9c75556 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en onthounotas"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie app toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die app op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie app geskeduleer is, nie werk nie."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"skedule, wekker, onthounota, horlosie"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Moenie Steur Nie"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Skakel aan"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Skakel Moenie steur nie aan"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 8aae837..093fbbb 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"ማንቂያዎች እና አስታዋሾች"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ይህ መተግበሪያ ማንቂያዎችን እንዲያቀናብር እና የጊዜ ትብነት ያላቸው እርምጃዎችን መርሐግብር እንዲያስይዝ ይፍቀዱለት። ይህ መተግበሪያው ከበስተጀርባ ማሄድ እንዲችል ያስችለዋል፣ ይህም የበለጠ ባትሪ ሊጠቀም ይችላል።\n\nይህ ፈቃድ ከጠፋ በዚህ መተግበሪያ መርሐግብር የተያዘላቸው ነባር ማንቂያዎች እና ጊዜ-ተኮር ክስተቶች አይሰሩም።"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"የጊዜ መርሐግብር፣ ማንቂያ፣ አስታዋሽ ሰዓት"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"አይረብሹ"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"አብራ"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"አትረብሽን አብራ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 02fa9aa..a1f4109 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"المنبّهات والتذكيرات"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"يمكنك السماح لهذا التطبيق بضبط المنبّهات وجدولة الإجراءات لتنفيذها في الوقت المناسب. ويسمح هذا الإذن بتشغيل التطبيق في الخلفية، ما قد يستهلك المزيد من البطارية.\n\nفي حال عدم تفعيل هذا الإذن، لن تعمل المنبهات المضبوطة والأحداث المستندة إلى الوقت المجدولة حاليًا في هذا التطبيق."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"جدول زمني، جدولة، منبّه، تذكير، ساعة"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"وضع \"عدم الإزعاج\""</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"تفعيل"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"تفعيل ميزة \"عدم الإزعاج\""</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index f7c68a3..019fb86 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"এলাৰ্ম আৰু ৰিমাইণ্ডাৰ"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"এই এপ্‌টোক এলাৰ্ম ছেট কৰিবলৈ আৰু সময় সংবেদনশীল কাৰ্যৰ সময়সূচী নিৰ্ধাৰণ কৰিবলৈ দিয়ক। ই এপ্‌টোক নেপথ্যত চলি থকাৰ অনুমতি দিয়ে যাৰ ফলত অধিক বেটাৰী ব্যৱহাৰ হয়।\n\nএই অনুমতিটো অফ কৰা থাকিলে, ইতিমধ্যে ছেট কৰা এলাৰ্ম আৰু এই এপ্‌টোৱে সময়সূচী নিৰ্ধাৰণ কৰা সময় ভিত্তিক অনুষ্ঠানসমূহে কাম নকৰা হ’ব।"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"সময়সূচী, এলাৰ্ম, ৰিমাইণ্ডাৰ, ঘড়ী"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"অসুবিধা নিদিব"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"অন কৰক"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"অসুবিধা নিদিব অন কৰক"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 4a08007..7f17e79 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Siqnallar və xatırlatmalar"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu tətbiqə siqnallar ayarlamağa və vaxta əsaslanan əməliyyatları planlaşdırmağa icazə verin. Bu, tətbiqin arxa fonda işləməsinə imkan verir ki, nəticədə daha çox enerji istifadə edilə bilər.\n\nBu icazə deaktiv olsa, bu tətbiq tərəfindən planlaşdırılan mövcud siqnallar və vaxta əsaslanan tədbirlər işləməyəcəkdir."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"cədvəl, siqnal, xatırlatma, saat"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Narahat etməyin"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktiv edin"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\"Narahat Etməyin\" rejimini aktiv edin"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 617533f..25bf587 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsetnici"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Omogućite ovoj aplikaciji da podešava alarme i zakazuje vremenski osetljive radnje. To omogućava da aplikacija bude pokrenuta u pozadini, što može da troši više baterije.\n\nAko je ova dozvola isključena, postojeći alarmi i događaji zasnovani na vremenu zakazani pomoću ove aplikacije neće raditi."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"zakazati, alarm, podsetnik, sat"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne uznemiravaj"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključite režim Ne uznemiravaj"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index f5c4440..3a61980 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будзільнікі і напаміны"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Дазвольце гэтай праграме ўключаць будзільнікі і задаваць час дзеянняў. З такім дазволам праграма можа працаваць у фонавым рэжыме і ў выніку хутчэй разраджаць акумулятар.\n\nКалі вы не ўключыце гэты дазвол, існуючыя будзільнікі і запланаваны праграмай час падзей не будуць працаваць."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"расклад, будзільнік, напамін, гадзіннік"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Не турбаваць"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Уключыць"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Уключэнне рэжыму \"Не турбаваць\""</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index ecf1e5a..5f0def5 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будилници и напомняния"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Разрешаване на това приложение да задава будилници и да насрочва действия, ограничени във времето. Това му позволява да работи на заден план, при което може да се използва повече батерия.\n\nАко разрешението е изключено, съществуващите будилници и събитията въз основа на времето, насрочени от приложението, няма да работят."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"график, будилник, напомняне, часовник"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Не безпокойте"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Включване"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Включване на режима „Не безпокойте“"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index b6fde48..0c0b569 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"অ্যালার্ম এবং রিমাইন্ডার"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"অ্যালার্ম এবং সময়ের মধ্যে শেষ করতে হবে এমন অ্যাকশনের শিডিউল সেট করতে এই অ্যাপকে অনুমতি দিন। এর ফলে ব্যাকগ্রাউন্ডে অ্যাপ চলতে পারে, যার জন্য আরও ব্যাটারির চার্জ খরচ হতে পারে।\n\nএই অনুমতি বন্ধ করা থাকলে, আগে থেকে থাকা অ্যালার্ম এবং অ্যাপের মাধ্যমে শিডিউল করা সময় ভিত্তিক ইভেন্টের রিমাইন্ডার কাজ করবে না।"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"শিডিউল, অ্যালার্ম, রিমাইন্ডার, ঘড়ি"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"বিরক্ত করবে না"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"চালু করুন"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'বিরক্ত করবে না\' মোড চালু করুন"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 44391d5..ea4150f 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu, a koje je ova aplikacija zakazala, neće funkcionirati."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"raspored, alarm, podsjetnik, sat"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne ometaj"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključi način rada Ne ometaj"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 9079c73..adfa6f2 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes i recordatoris"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions a una hora determinada. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments que ja hagi programat l\'aplicació no funcionaran."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programació, alarma, recordatori, rellotge"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"No molestis"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activa"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activa el mode No molestis"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 33955de..96d04a8 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a připomenutí"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Když tuto možnost povolíte, aplikace bude moci nastavovat budíky a plánovat akce závislé na čase. Aplikace poběží na pozadí, což může vést k vyšší spotřebě baterie.\n\nPokud toto oprávnění zůstane vypnuté, stávající budíky a události závislé na čase naplánované touto aplikací nebudou fungovat."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plán, budík, připomenutí, hodiny"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Nerušit"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Zapnout"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zapněte funkci Nerušit"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index de09e95..c6a5a43 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmer og påmindelser"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Tillad, at denne app indstiller alarmer og planlægger tidsbestemte handlinger. Appen vil køre i baggrunden, hvor den muligvis bruger mere batteri.\n\nHvis denne tilladelse er deaktiveret, vil eksisterende alarmer og tidsbestemte handlinger, der er planlagt af denne app, ikke fungere."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planlæg, alarm, påmindelse, ur"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Forstyr ikke"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivér"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktivér Forstyr ikke"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index f24fb35..88db823 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wecker und Erinnerungen"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dieser App erlauben, Wecker zu stellen und zeitgebundene Aktionen zu planen. Dadurch läuft die App im Hintergrund. Dies kann den Akkuverbrauch erhöhen. \n\nWenn diese Berechtigung deaktiviert ist, funktionieren bereits gestellte Wecker und zeitgebundene Ereignisse, die von dieser App geplant sind, nicht wie erwartet."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planen, Wecker, Erinnerung, Uhr"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Bitte nicht stören"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivieren"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"„Bitte nicht stören“ aktivieren"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index bb518d7..35734a9 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ξυπνητήρια και υπενθυμίσεις"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Επιτρέψτε σε αυτή την εφαρμογή να ορίζει ξυπνητήρια και να προγραμματίζει ενέργειες που εξαρτώνται από τον χρόνο. Αυτό επιτρέπει στην εφαρμογή να εκτελείται στο παρασκήνιο και, ως εκ τούτου, μπορεί να καταναλώνει περισσότερη μπαταρία.\n\nΑν αυτή η άδεια δεν είναι ενεργή, τα υπάρχοντα ξυπνητήρια και συμβάντα βάσει χρόνου που έχουν προγραμματιστεί από αυτή την εφαρμογή δεν θα λειτουργούν."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"πρόγραμμα, ξυπνητήρι, υπενθύμιση, ρολόι"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Μην ενοχλείτε"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ενεργοποίηση"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ενεργοποίηση λειτουργίας \"Μην ενοχλείτε\""</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 73502ed..2d03437 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms and reminders"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Do Not Disturb"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index c0b0dff..be5dfaa 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -564,6 +564,7 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms &amp; reminders"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
+    <string name="zen_mode_do_not_disturb_name" msgid="6798711401734798283">"Do Not Disturb"</string>
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Do Not Disturb"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 73502ed..2d03437 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms and reminders"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Do Not Disturb"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 73502ed..2d03437 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms and reminders"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Do Not Disturb"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 59be4be..92af284 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -564,6 +564,7 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎Alarms &amp; reminders‎‏‎‎‏‎"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎If this permission is off, existing alarms and time-based events scheduled by this app won’t work.‎‏‎‎‏‎"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‏‎‏‎‏‏‎‏‎‎‏‏‎schedule, alarm, reminder, clock‎‏‎‎‏‎"</string>
+    <string name="zen_mode_do_not_disturb_name" msgid="6798711401734798283">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎Do Not Disturb‎‏‎‎‏‎"</string>
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‏‎‏‎‏‏‎Do Not Disturb‎‏‎‎‏‎"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‎‏‎‏‏‎‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‏‎‏‎‎Turn on‎‏‎‎‏‎"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎Turn on Do Not Disturb‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 2cfd356..ff69f64 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas y recordatorios"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite que esta app establezca alarmas y programe acciones para horarios específicos. De esta manera, la app puede ejecutarse en segundo plano, lo que podría aumentar el consumo de batería.\n\nSi se desactiva este permiso, no funcionarán las alarmas ni los eventos basados en el tiempo existentes que programe esta app."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarma, recordatorio, reloj"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"No interrumpir"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activar"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activar No interrumpir"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 6779f46..e2d3589 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas y recordatorios"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite que esta aplicación programe alarmas y otras acciones que se llevan a cabo a una hora determinada. Esto hace que la aplicación pueda seguir activa en segundo plano, lo que puede usar más batería.\n\nSi este permiso está desactivado, no funcionarán las alarmas ni los eventos que se activan a una hora determinada que programe esta aplicación."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarma, recordatorio, reloj"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"No molestar"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activar"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activar el modo No molestar"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 4cb05ba..e4490a3 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmid ja meeldetuletused"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lubage sellel rakendusel määrata alarme ja ajastada ajakriitilisi toiminguid. See võimaldab rakendusel töötada taustal, mistõttu võib akukasutus olla suurem.\n\nKui see luba on välja lülitatud, siis olemasolevad alarmid ja selle rakenduse ajastatud ajapõhised sündmused ei tööta."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ajakava, äratus, meeldetuletus, kell"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Mitte segada"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Lülita sisse"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Valiku Mitte segada sisselülitamine"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 666af7c..828831e 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmak eta abisuak"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nBaimen hori ematen ez baduzu, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programazioa, alarma, abisua, erlojua"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Ez molestatzeko modua"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktibatu"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktibatu ez molestatzeko modua"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index f2a2bb5..7858cc8 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"زنگ‌های ساعت و یادآوری‌ها"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"به این برنامه اجازه می‌دهد زنگ ساعت تنظیم کند و کنش‌های حساس به زمان را زمان‌بندی کند. این تنظیم به برنامه اجازه می‌دهد در پس‌زمینه اجرا شود که ممکن است باتری بیشتری مصرف کند.\n\nاگر این اجازه خاموش باشد، زنگ‌های ساعت موجود و رویدادهای زمان‌محور که این برنامه زمان‌بندی کرده است کار نخواهند کرد."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"زمان‌بندی، زنگ ساعت، یادآوری، ساعت"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"مزاحم نشوید"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"روشن کردن"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"روشن کردن «مزاحم نشوید»"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 66db8f7..8ad343a 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Herätykset ja muistutukset"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Anna sovelluksen lisätä herätyksiä ja ajoittaa kiireellisiä tapahtumia. Näin sovellus voi toimia taustalla, mikä voi kuluttaa enemmän virtaa.\n\nIlman tätä lupaa sovelluksen ajoittamat herätykset ja aikaan perustuvat tapahtumat eivät toimi."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ajoitus, herätys, muistutus, kello"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Älä häiritse"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ota käyttöön"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Laita Älä häiritse ‑tila päälle"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 6ce0e82..2e3a6a7 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes et rappels"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Autorisez cette appli à créer des alarmes et à programmer des actions urgentes. Cela permet à l’appli de s\'exécuter en arrière-plan, ce qui peut nécessiter plus de pile.\n\nSi cette autorisation est désactivée, les alarmes existantes et les événements en temps réel programmés par cette appli ne fonctionneront pas."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"horaire, alarme, rappel, horloge"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne pas déranger"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activer"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activer le mode Ne pas déranger"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index ea24b23..4327708 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes et rappels"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Autoriser cette appli à définir des alarmes et à programmer des actions à certaines heures. Elle s\'exécutera alors en arrière-plan, ce qui peut solliciter davantage la batterie.\n\nSi l\'autorisation est désactivée, les alarmes existantes et les événements programmés par l\'appli ne fonctionneront pas."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"définir, alarme, rappel, horloge"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne pas déranger"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activer"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activer le mode Ne pas déranger"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 647f6dd..9bcdc97 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas e recordatorios"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite que esta aplicación defina alarmas e planifique accións que dependan da hora. Con este permiso, a aplicación pode executarse en segundo plano, o que pode provocar un maior consumo de batería.\n\nSe este permiso está desactivado, non funcionarán as alarmas que xa se definisen nin os eventos que dependan da hora planificados por esta aplicación."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planificar, alarma, recordatorio, reloxo"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Non molestar"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activar"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activar modo Non molestar"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index a0724b0..e402ad3 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"અલાર્મ અને રિમાઇન્ડર"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"આ ઍપને અલાર્મ સેટ કરવા અને સમય પ્રતિ સંવેદનશીલ ક્રિયાઓ શેડ્યૂલ કરવા માટે મંજૂરી આપો. આ ઍપને બૅકગ્રાઉન્ડમાં ચાલવા દે છે, જેને કારણે બૅટરીનો વધુ વપરાશ થઈ શકે છે.\n\nજો આ પરવાનગી બંધ હોય, તો આ ઍપ દ્વારા શેડ્યૂલ કરવામાં આવેલા વર્તમાન અલાર્મ અને સમય આધારિત ઇવેન્ટ કામ કરશે નહીં."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"શેડ્યૂલ, અલાર્મ, રિમાઇન્ડર, ઘડિયાળ"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"ખલેલ પાડશો નહીં"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ચાલુ કરો"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"ખલેલ પાડશો નહીં ચાલુ કરો"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index cdab138..2e484e4 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म और रिमाइंडर"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"इस ऐप्लिकेशन को अलार्म और तय समय पर होने वाली कार्रवाइयों के रिमाइंडर सेट करने की अनुमति दें. ऐसा करने से, ऐप्लिकेशन को बैकग्राउंड में चलने की अनुमति मिलती है. इससे बैटरी ज़्यादा खर्च होती है.\n\nऐप्लिकेशन को यह अनुमति न देने पर, इसकी मदद से सेट किए गए अलार्म और तय समय पर होने वाली कार्रवाइयों के रिमाइंडर काम नहीं करेंगे."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"शेड्यूल, अलार्म, रिमाइंडर, घड़ी"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"परेशान न करें"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"चालू करें"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'परेशान न करें\' चालू करें"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index fbf89cb..a1c9a61 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Omogućite toj aplikaciji da postavlja alarme i zakazuje radnje u točno određeno vrijeme. To aplikaciji omogućuje da se izvodi u pozadini, pa je moguća dodatna potrošnja baterije.\n\nAko je to dopuštenje isključeno, postojeći alarmi i događaji zakazani putem te aplikacije neće funkcionirati."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"raspored, alarm, podsjetnik, sat"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne uznemiravaj"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključite opciju Ne uznemiravaj."</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 541406d..5ea4fdb 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ébresztések és emlékeztetők"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lehetővé teszi ennek az alkalmazásnak, hogy ébresztéseket állítson be és időérzékeny feladatokat ütemezzen. Ezzel engedélyezi az alkalmazásnak, hogy a háttérben fusson, ami megnövekedett akkumulátorhasználattal járhat.\n\nHa ez az engedély ki van kapcsolva, az alkalmazás által beállított ébresztések és ütemezett időérzékeny események nem fognak működni."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ütemezés, ébresztés, emlékeztető, óra"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne zavarjanak"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Bekapcsolás"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"A Ne zavarjanak mód bekapcsolása"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index ac77232..f7b51a5 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Զարթուցիչներ և հիշեցումներ"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Թույլատրել այս հավելվածին զարթուցիչներ կարգավորել և որոշակի ժամանակի համար գործողություններ պլանավորել։ Այդ դեպքում հավելվածն աշխատում է ֆոնային ռեժիմում, և արդյունքում մարտկոցի լիցքն ավելի արագ է սպառվում։\n\nԵթե այս թույլտվությունն անջատված է, հավելվածի կողմից կարգավորված զարթուցիչները և գործողությունների ժամանակացույցները չեն աշխատի։"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ժամանակացույց, զարթուցիչ, հիշեցում, ժամացույց"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Չանհանգստացնել"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Միացնել"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Միացրեք «Չանհանգստացնել» ռեժիմը"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 2297376..070c161 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -432,7 +432,7 @@
     <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksternal, terlepas dari nilai manifes"</string>
     <string name="force_resizable_activities" msgid="7143612144399959606">"Paksa aktivitas agar ukurannya dapat diubah"</string>
     <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Membuat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string>
-    <string name="enable_freeform_support" msgid="7599125687603914253">"Aktifkan jendela berformat bebas"</string>
+    <string name="enable_freeform_support" msgid="7599125687603914253">"Aktifkan jendela berbentuk bebas"</string>
     <string name="local_backup_password_title" msgid="4631017948933578709">"Sandi cadangan desktop"</string>
     <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Saat ini cadangan desktop penuh tidak dilindungi"</string>
     <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ketuk guna mengubah atau menghapus sandi untuk cadangan lengkap desktop"</string>
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarm &amp; pengingat"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Mengizinkan aplikasi ini menyetel alarm dan menjadwalkan tindakan yang sensitif waktu. Hal ini memungkinkan aplikasi berjalan di latar belakang, sehingga mungkin menggunakan lebih banyak daya baterai.\n\nJika izin ini dinonaktifkan, alarm dan acara berbasis waktu yang dijadwalkan oleh aplikasi ini tidak akan berfungsi."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"jadwal, alarm, pengingat, jam"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Jangan Ganggu"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktifkan"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktifkan mode Jangan Ganggu"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 30d36bc..5408b50 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Vekjarar og áminningar"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Leyfa þessu forriti að stilla vekjara og áætla aðgerðir sem þurfa að eiga sér stað innan ákveðins tímaramma. Þetta leyfir forritinu að keyra í bakgrunninum sem getur notað meiri rafhlöðuorku.\n\nEf slökkt er á þessari heimild munu núverandi vekjarar og tímasettir viðburðir sem þetta forrit stillir ekki virka."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"áætlun, vekjari, áminning, klukka"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Ónáðið ekki"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Kveikja"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Kveikja á „Ónáðið ekki“"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 9dac1f6..10394f1 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Sveglie e promemoria"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Consenti a questa app di impostare sveglie e programmare azioni per orari specifici. L\'app potrà essere eseguita in background, comportando un consumo maggiore della batteria.\n\nSe questa autorizzazione viene disattivata, le sveglie esistenti e gli eventi basati sull\'orario programmati da questa app non funzioneranno."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programmare, sveglia, promemoria, orologio"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Non disturbare"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Attiva"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Attiva Non disturbare"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index e7ad1eb..fce947a 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"שעונים מעוררים ותזכורות"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ההרשאה הזו מתירה לאפליקציה להגדיר שעון מעורר ולתזמן פעולות דחופות. האפליקציה תוכל לפעול ברקע ובכך להגביר את צריכת הסוללה.\n\nאם ההרשאה מושבתת, ההתראות והאירועים מבוססי-הזמן שהוגדרו ותוזמנו על ידי האפליקציה לא יפעלו."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"תזמון, שעון מעורר, תזכורת, שעון"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"נא לא להפריע"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"הפעלה"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"הפעלת מצב נא לא להפריע"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 9848a91..41acfc0 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"アラームとリマインダー"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"アラームの設定や時間ベースのアクション設定を、このアプリに許可します。これによりアプリがバックグラウンドで実行できるようになるため、バッテリーの使用量が増えることがあります。\n\nこの権限が OFF の場合、このアプリで設定された既存のアラームと時間ベースのイベントは機能しなくなります。"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"スケジュール, アラーム, リマインダー, 時計"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"サイレント モード"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ON にする"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"サイレント モードを ON にする"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 3c03b3c..58a01a4 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"მაღვიძარები და შეხსენებები"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ნებას რთავს ამ აპს, დააყენოს მაღვიძარები და დაგეგმოს დროზე დამოკიდებული მოქმედებები. ეს საშუალებას აძლევს აპს, იმუშაოს ფონურად, რამაც შეიძლება ბატარეის ხარჯი გაზარდოს.\n\nთუ ეს ნებართვა გამორთულია, ამ აპით დაგეგმილი მაღვიძარები და დროზე დამოკიდებული მოვლენები არ იმუშავებს."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"განრიგი, მაღვიძარა, შეხსენება, საათი"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"არ შემაწუხოთ"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ჩართვა"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"„არ შემაწუხოთ“ რეჟიმის ჩართვა"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 80a1442..485120d 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Оятқыштар мен еске салғыштар"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Бұл қолданбаға оятқыштарды орнатуға және уақытқа байланысты әрекеттерді жоспарлауға рұқсат береді. Мұндайда қолданба фондық режимде жұмыс істейді, сондықтан батарея шығыны артуы мүмкін.\n\nБұл рұқсат өшірулі болса, осы қолданбада жоспарланған ағымдағы оятқыштар мен уақытқа байланысты іс-шаралар жұмыс істемейді."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"кесте, оятқыш, еске салғыш, сағат"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Мазаламау"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Қосу"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Мазаламау режимін қосу"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 4010a8b..7fbc509 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"ម៉ោងរោទ៍ និង​ការរំលឹក"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"អនុញ្ញាតឱ្យ​កម្មវិធីនេះ​កំណត់ម៉ោងរោទ៍ និងកំណត់កាលវិភាគសកម្មភាពដែលតម្រូវឱ្យទាន់ពេលវេលា។ ការធ្វើបែបនេះអនុញ្ញាតឱ្យកម្មវិធីនេះដំណើរការនៅផ្ទៃខាងក្រោយ ដែលអាចប្រើថ្មកាន់តែច្រើន។\n\nប្រសិនបើបិទការអនុញ្ញាតនេះ ម៉ោងរោទ៍ដែលមានស្រាប់ និងព្រឹត្តិការណ៍ផ្អែកលើពេលវេលាដែលកំណត់ដោយកម្មវិធីនេះ​នឹងមិនដំណើរការទេ។"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"កាលវិភាគ ម៉ោងរោទ៍ ការរំលឹក នាឡិកា"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"កុំ​រំខាន"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"បើក"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"បើកមុខងារកុំរំខាន"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index ea1dc7d..85075c3 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"ಅಲಾರಂಗಳು ಮತ್ತು ರಿಮೈಂಡರ್‌ಗಳು"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ಅಲಾರಂಗಳನ್ನು ಹೊಂದಿಸಲು ಮತ್ತು ಸಮಯ-ಸೂಕ್ಷ್ಮವಾದ ಕ್ರಿಯೆಗಳನ್ನು ನಿಗದಿಪಡಿಸಲು ಈ ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸಿ. ಇದು ಹಿನ್ನೆಲೆಯಲ್ಲಿ ರನ್ ಆಗಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ, ಅದರಿಂದ ಹೆಚ್ಚು ಬ್ಯಾಟರಿ ಬಳಕೆಯಾಗಬಹುದು.\n\nಈ ಅನುಮತಿ ಆಫ್ ಆಗಿದ್ದರೆ, ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಅಲಾರಂಗಳು ಮತ್ತು ಈ ಆ್ಯಪ್ ನಿಗದಿಪಡಿಸಿದ ಸಮಯ-ಸೂಕ್ಷ್ಮ ಈವೆಂಟ್‌ಗಳು ಕೆಲಸ ಮಾಡುವುದಿಲ್ಲ."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ವೇಳಾಪಟ್ಟಿ, ಅಲಾರಂ, ರಿಮೈಂಡರ್, ಗಡಿಯಾರ"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ಆನ್ ಮಾಡಿ"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಅನ್ನು ಆನ್ ಮಾಡಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 2a8807f..480d78f 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"알람 및 리마인더"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"이 앱이 알람을 설정하고 시간 기반 작업을 예약할 수 있도록 허용합니다. 이렇게 하면 백그라운드에서 앱 실행이 허용되어 배터리 사용량이 증가할 수 있습니다.\n\n이 권한을 사용 중지하면 이 앱에서 예약한 기존의 알람 및 시간 기반 일정이 작동하지 않습니다."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"일정 예약, 알람, 리마인더, 시계"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"방해 금지 모드"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"사용 설정"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"방해 금지 모드 사용 설정"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 8e1a1a4..1667041 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ойготкучтар жана эстеткичтер"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Бул колдонмого ойготкучтарды коюуга жана башка аракеттерди графикке киргизүүгө уруксат бересиз. Ушуну менен колдонмо фондо иштеп, батареяны көбүрөөк сарпташы мүмкүн.\n\nЭгер бул уруксат өчүрүлсө, колдонмодогу ойготкучтар жана графикке киргизилген башка аракеттер иштебейт."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"график, ойготкуч, эстеткич, саат"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Тынчымды алба"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Күйгүзүү"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\"Тынчымды алба\" режимин күйгүзүү"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 1c7f520..2c6d6ba 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"ໂມງປຸກ ແລະ ການແຈ້ງເຕືອນ"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ອະນຸຍາດໃຫ້ແອັບນີ້ຕັ້ງໂມງປຸກ ແລະ ກຳນົດເວລາຄຳສັ່ງທີ່ເນັ້ນເລື່ອງເວລາເປັນສຳຄັນໄດ້. ນີ້ຈະເຮັດໃຫ້ແອັບເຮັດວຽກໄດ້ໃນພື້ນຫຼັງ, ເຊິ່ງອາດໃຊ້ແບັດເຕີຣີຫຼາຍຂຶ້ນ.\n\nຫາກປິດການອະນຸຍາດນີ້ໄວ້, ໂມງປຸກທີ່ມີຢູ່ກ່ອນແລ້ວ ແລະ ເຫດການທີ່ອ້າງອີງເວລາທີ່ກຳນົດໄວ້ໂດຍແອັບນີ້ຈະບໍ່ສາມາດເຮັດວຽກໄດ້."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ກຳນົດເວລາ, ໂມງປຸກ, ການແຈ້ງເຕືອນ, ໂມງ"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"ຫ້າມລົບກວນ"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ເປີດ"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"ເປີດໂໝດຫ້າມລົບກວນ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 35141d9..a6ef078 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signalai ir priminimai"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Leiskite šiai programai nustatyti signalus ir suplanuoti veiksmus, kuriems svarbus laiko veiksnys. Dėl to programa gali veikti fone ir sunaudoti daugiau akumuliatoriaus energijos.\n\nJei šis leidimas išjungtas, šios programos suplanuoti esami signalai ir laiku pagrįsti įvykiai neveiks."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"tvarkaraštis, signalas, priminimas, laikrodis"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Netrukdymo režimas"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Įjungti"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Netrukdymo režimo įjungimas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index dae1d2f..a1fef64 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signāli un atgādinājumi"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Atļaujiet šai lietotnei iestatīt signālus un ieplānot darbības, kas jāveic konkrētā laikā. Tādējādi lietotne darbosies fonā un, iespējams, patērēs vairāk akumulatora enerģijas.\n\nJa šī atļauja nav piešķirta, esošie signāli un šīs lietotnes ieplānotie notikumi, kas jāizpilda konkrētā laikā, nedarbosies."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ieplānot, signāls, atgādinājums, pulkstenis"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Netraucēt"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ieslēgt"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Režīma “Netraucēt” ieslēgšana"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index a256fa7..e22f67c 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Аларми и потсетници"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Дозволете ѝ на апликацијава да поставува аларми и да закажува дејства со временски рокови. Ова овозможува апликацијата да работи во заднина и така може повеќе да ја троши батеријата.\n\nАко дозволава е исклучена, нема да функционираат постојните аларми и настаните според време закажани од апликацијава."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"закажување, аларм, потсетник, часовник"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Не вознемирувај"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Вклучи"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Исклучување на „Не вознемирувај“"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 32a779e..0b6d3fb 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"അലാറങ്ങളും റിമെെൻഡറുകളും"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"അലാറങ്ങൾ സജ്ജീകരിക്കാനും സമയപ്രാധാന്യമുള്ള പ്രവർത്തനങ്ങൾ ഷെഡ്യൂൾ ചെയ്യാനും ഈ ആപ്പിനെ അനുവദിക്കുക. പശ്ചാത്തലത്തിൽ റൺ ചെയ്യാൻ ഇത് ഈ ആപ്പിന് അനുവാദം നൽകുന്നു, ഇതിന് കൂടുതൽ ബാറ്ററി ഉപയോഗിച്ചേക്കാം.\n\nഈ അനുമതി ഓഫാണെങ്കിൽ, ഈ ആപ്പ് നിലവിൽ ഷെഡ്യൂൾ ചെയ്‌ത അലാറങ്ങളും സമയാധിഷ്‌ഠിത ഇവന്റുകളും പ്രവർത്തിക്കില്ല."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ഷെഡ്യൂൾ, അലാറം, റിമെെൻഡർ, ക്ലോക്ക്"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"ശല്യപ്പെടുത്തരുത്"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ഓണാക്കുക"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'ശല്യപ്പെടുത്തരുത്\' ഓണാക്കുക"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 2a70e1c..1ce8b0f 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Сэрүүлэг, сануулагч"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Энэ аппад сэрүүлэг тавих болон хугацаанд мэдрэг үйлдлийн хуваарь гаргахыг зөвшөөрнө үү. Энэ нь аппад ард ажиллахыг зөвшөөрөх бөгөөд ингэснээр илүү их батарей ашиглаж магадгүй.\n\nХэрэв энэ зөвшөөрөл унтраалттай бол энэ аппын аль хэдийн тавьсан сэрүүлэг болон хуваарь гаргасан хугацаанд мэдрэг үйл явдал ажиллахгүй."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"хуваарь, сэрүүлэг, сануулагч, цаг"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Бүү саад бол"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Асаах"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Бүү саад бол горимыг асаах"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index cd32f6d..ad67ef2 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म आणि रिमाइंडर"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"या ॲपला अलार्म सेट करण्याची किंवा वेळेनुसार संवेदनशील असलेल्या कृती शेड्युल करण्याची अनुमती द्या. हे ॲपला बॅकग्राउंडमध्ये रन होऊ देते, ज्यामुळे जास्त बॅटरी वापरली जाऊ शकते.\n\nही परवानगी बंद असल्यास, सध्याचे अलार्म आणि या ॲपद्वारे शेड्युल केलेले वेळेवर आधारित इव्हेंट काम करणार नाहीत."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"शेड्युल, अलार्म, रिमाइंडर, घड्याळ"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"व्यत्यय आणू नका"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"सुरू करा"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"व्यत्यय आणू नका सुरू करा"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index da4e53b..5bb3ba0 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Penggera &amp; peringatan"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Benarkan apl ini menetapkan penggera dan menjadualkan tindakan yang sensitif masa. Hal ini membolehkan apl berjalan di latar, yang mungkin menggunakan lebih banyak bateri.\n\nJika kebenaran ini dimatikan, penggera sedia ada dan acara berdasarkan masa yang dijadualkan oleh apl ini tidak akan berfungsi."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"jadual, penggera, peringatan, jam"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Jangan Ganggu"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Hidupkan"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Hidupkan Jangan Ganggu"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index f9fae5a..7cce3d9 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"နှိုးစက်နှင့် သတိပေးချက်များ"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"နှိုးစက်သတ်မှတ်ရန်နှင့် အချိန်တိကျရန် လိုအပ်သည့် လုပ်ဆောင်ချက်များအတွက် အစီအစဉ်ဆွဲရန် ဤအက်ပ်ကို ခွင့်ပြုသည်။ ၎င်းက အက်ပ်ကို နောက်ခံတွင် လုပ်ဆောင်ခွင့်ပေးပြီး ဘက်ထရီပိုသုံးနိုင်သည်။\n\nဤခွင့်ပြုချက်ကို ပိတ်ထားပါက ဤအက်ပ်ဖြင့် အစီအစဉ်ဆွဲထားသော လက်ရှိနှိုးစက်နှင့် အချိန်သတ်မှတ်ထားသည့် အစီအစဉ်များ အလုပ်လုပ်တော့မည် မဟုတ်ပါ။"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"အချိန်ဇယား၊ နှိုးစက်၊ သတိပေးချက်၊ နာရီ"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"မနှောင့်ယှက်ရ"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ဖွင့်ရန်"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'မနှောင့်ယှက်ရ\' ဖွင့်ခြင်း"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index d221b9b..c6fbea1 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmer og påminnelser"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Gi denne appen tillatelse til å angi alarmer og planlegge tidssensitive handlinger. Dette gir appen tillatelse til å kjøre i bakgrunnen, noe som kan bruke mer batteri.\n\nHvis denne tillatelsen er av, fungerer ikke eksisterende alarmer og tidsbaserte hendelser som er planlagt av denne appen."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"tidsplan, alarm, påminnelse, klokke"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Ikke forstyrr"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Slå på"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Slå på Ikke forstyrr"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 1d419ee..5d18fd3 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म तथा रिमाइन्डर"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"यो एपलाई अलार्म सेट गर्ने र समयमै पूरा गर्नु पर्ने कारबाहीहरूको रुटिन बनाउने अनुमति दिनुहोस्। यो अनुमति दिइएको छ भने यो एप ब्याकग्राउन्डमा चल्छ र धेरै ब्याट्री खपत हुन्छ।\n\nयो अनुमति दिइएको छैन भने सेट गरिएका अलार्म बज्दैनन् र यो एपले तय गरेका गतिविधि चल्दैनन्।"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"समयतालिका, अलार्म, रिमाइन्डर, घडी"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"बाधा नपुऱ्याउनुहोस्"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"अन गर्नुहोस्"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"बाधा नपुऱ्याउनुहोस् नामक मोडलाई अन गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 749e5da..e457376 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en herinneringen"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Sta toe dat deze app wekkers zet en tijdgevoelige acties plant. De app kan hierdoor op de achtergrond worden uitgevoerd, waardoor je misschien meer batterijlading verbruikt.\n\nAls dit recht uitstaat, werken door deze app geplande bestaande wekkers en tijdgebaseerde afspraken niet."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plannen, schema, wekker, alarm, herinnering, klok"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Niet storen"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aanzetten"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zet Niet storen aan."</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 5ca07c0..2f25cde 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"ଆଲାରାମ୍ ଏବଂ ରିମାଇଣ୍ଡରଗୁଡ଼ିକ"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ଏହି ଆପକୁ ଆଲାରାମ୍ ସେଟ୍ କରିବାକୁ ଏବଂ ସମୟ-ସମ୍ବେଦନଶୀଳ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ସିଡୁଲ୍ କରିବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ। ଏହା ଆପକୁ ପୃଷ୍ଠପଟରେ ଚାଲିବାକୁ ଦେଇଥାଏ, ଯାହା ଅଧିକ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରିପାରେ।\n\nଯଦି ଏହି ଅନୁମତି ବନ୍ଦ ଅଛି, ତେବେ ଏହି ଆପ୍ ଦ୍ୱାରା ସିଡୁଲ୍ କରାଯାଇଥିବା ପୂର୍ବରୁ ଥିବା ଆଲାରାମ୍ ଏବଂ ସମୟ-ଆଧାରିତ ଇଭେଣ୍ଟଗୁଡ଼ିକ କାମ କରିବ ନାହିଁ।"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ସିଡୁଲ୍, ଆଲାରାମ୍, ରିମାଇଣ୍ଡର୍, ଘଣ୍ଟା"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ଚାଲୁ କରନ୍ତୁ"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ଅନ୍ କରନ୍ତୁ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 48db7f4..b13ef1b 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ਇਸ ਐਪ ਨੂੰ ਅਲਾਰਮ ਸੈੱਟ ਕਰਨ ਜਾਂ ਹੋਰ ਸਮਾਂ-ਸੰਵੇਦਨਸ਼ੀਲ ਕਾਰਵਾਈਆਂ ਨੂੰ ਨਿਯਤ ਕਰਨ ਦਿਓ। ਇਸ ਨਾਲ ਐਪ ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਣ ਦੀ ਇਜਾਜ਼ਤ ਮਿਲਦੀ ਹੈ, ਜਿਸ ਨਾਲ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਵੱਧ ਸਕਦੀ ਹੈ।\n\nਜੇ ਇਹ ਇਜਾਜ਼ਤ ਬੰਦ ਹੈ, ਤਾਂ ਇਸ ਐਪ ਰਾਹੀਂ ਨਿਯਤ ਕੀਤੇ ਮੌਜੂਦਾ ਅਲਾਰਮ ਅਤੇ ਸਮਾਂ-ਆਧਾਰਿਤ ਇਵੈਂਟ ਕੰਮ ਨਹੀਂ ਕਰਨਗੇ।"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ਸਮਾਂ-ਸੂਚੀ, ਅਲਾਰਮ, ਰਿਮਾਈਂਡਰ, ਘੜੀ"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ਚਾਲੂ ਕਰੋ"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index d0b6979..3f90774 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmy i przypomnienia"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwalaj tej aplikacji na ustawianie alarmów i planowanie działań, w przypadku których czas jest istotny. Aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tego uprawnienia, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"harmonogram, alarm, przypomnienie, zegar"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Nie przeszkadzać"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Włącz"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Włącz tryb Nie przeszkadzać"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 6eaa518..00375b0 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Não perturbe"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index a411dc8..97d2848 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permita que a app defina alarmes e agende ações com um horário específico. Esta ação permite que a app seja executada em segundo plano, o que pode usar mais bateria.\n\nSe esta autorização estiver desativada, os alarmes existentes e os eventos com base no tempo agendados por esta app não funcionam."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"agendar, alarme, lembrete, relógio"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Não incomodar"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o modo Não incomodar"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 6eaa518..00375b0 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Não perturbe"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 71f0d2f..900851e 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarme și mementouri"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să seteze alarme și să planifice acțiuni care trebuie realizate în timp scurt. Astfel, aplicația poate să ruleze în fundal, ceea ce ar putea crește consumul de 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>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"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>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 0c9c9cf..db4be66 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будильники и напоминания"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Вы можете разрешить этому приложению устанавливать будильники и планировать запуск действий в определенное время. В этом случае оно будет работать в фоновом режиме и быстрее расходовать заряд батареи.\n\nЕсли отключить это разрешение, текущие будильники и созданные приложением события перестанут запускаться."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"установить, будильник, напоминание, часы"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Не беспокоить"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Включить"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Включите режим \"Не беспокоить\""</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 0bba018..d9df5eb 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"එලාම සහ සිහිකැඳවීම්"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"එලාම සැකසීමට සහ කාල සංවේදී ක්‍රියා කාලසටහන්ගත කිරීමට මෙම යෙදුමට ඉඩ දෙන්න. මෙය පසුබිමේ ධාවනය වීමට යෙදුමට ඉඩ දෙයි, එය වැඩි බැටරිය වැඩියෙන් භාවිත කළ හැකිය.\n\nමෙම අවසරය ක්‍රියාවිරහිත නම්, මෙම යෙදුම මඟින් සැලසුම් කර ඇති තිබෙන එලාම සහ වේලාව පදනම් කර ගත් සිදුවීම් ක්‍රියා නොකරනු ඇත."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"කාල සටහන, එලාමය, සිහිකැඳවීම, ඔරලෝසුව"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"බාධා නොකරන්න"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ක්‍රියාත්මක කරන්න"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"බාධා නොකරන්න ක්‍රියාත්මක කරන්න"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index acb528f1..c690a19 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a pripomenutia"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, existujúce budíky a udalosti s časovým obmedzením naplánované touto aplikáciou nebudú fungovať."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plán, budík, pripomenutie, hodiny"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Režim bez vyrušení"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Zapnúť"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zapnite režim bez vyrušení"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index ff11a7a..7fa5ed1 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi in opomniki"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Tej aplikaciji dovolite nastavljanje alarmov in načrtovanje časovno občutljivih dejanj. S tem aplikaciji omogočite izvajanje v ozadju, kar bo morda povečalo porabo energije baterije.\n\nČe je to dovoljenje izklopljeno, obstoječi alarmi in časovno občutljivi dogodki, ki jih nastavi ta aplikacija, ne bodo delovali."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"načrtovanje, urnik, alarm, opomnik, ura"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne moti"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Vklopi"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Vklop načina »Ne moti«"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index f0d1ac5..b64c8fd 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmet dhe alarmet rikujtuese"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lejo që ky aplikacion të caktojë alarmet dhe të planifikojë veprime që kanë një afat të caktuar. Kjo mundëson që aplikacioni të ekzekutohet në sfond, gjë që mund të përdorë më shumë bateri.\n\nNëse kjo leje është caktuar si joaktive, alarmet ekzistuese dhe ngjarjet në bazë kohore të planifikuara nga ky aplikacion nuk do të funksionojnë."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planifiko, alarm, alarm rikujtues, ora"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Mos shqetëso"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivizo"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktivizo \"Mos shqetëso\""</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 557e95b..f9001a8 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Аларми и подсетници"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Омогућите овој апликацији да подешава аларме и заказује временски осетљиве радње. То омогућава да апликација буде покренута у позадини, што може да троши више батерије.\n\nАко је ова дозвола искључена, постојећи аларми и догађаји засновани на времену заказани помоћу ове апликације неће радити."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"заказати, аларм, подсетник, сат"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Не узнемиравај"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Укључи"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Укључите режим Не узнемиравај"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 2404dc2..4ca4835 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarm och påminnelser"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Tillåt att den här appen ställer in alarm och schemalägger tidskänsliga åtgärder. Om du tillåter detta kan appen köras i bakgrunden, vilket kan dra mer batteri.\n\nOm behörigheten är inaktiverad fungerar inte befintliga alarm och tidsbaserade händelser som schemalagts av den här appen."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schema, alarm, påminnelse, klocka"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Stör ej"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivera"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktivera Stör ej."</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 03ddecd..3198d0a 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Kengele na vikumbusho"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Ruhusu programu hii iweke kengele na ratiba za vitendo vingine vinavyotegemea wakati. Hatua hii inairuhusu programu itumike chinichini, hali inayoweza kutumia chaji nyingi ya betri.\n\nIkiwa ruhusa hii itazimwa, kengele zilizopo na ratiba za vitendo vinavyotegemea wakati zilizowekwa na programu hii hazitafanya kazi."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ratiba, kengele, kikumbusho, saa"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Usinisumbue"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Washa"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Washa kipengele cha Usinisumbue"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index d3f3c96..108ddce 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"அலாரங்கள் &amp; நினைவூட்டல்கள்"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"அலாரங்களை அமைக்கவும் குறிப்பிட்ட கால இடைவெளியில் செயல்களைத் திட்டமிடவும் இந்த ஆப்ஸை அனுமதிக்கும். இது ஆப்ஸ் பின்னணியில் இயங்குவதை அனுமதிக்கும், இதற்காக அதிக பேட்டரியைப் பயன்படுத்தக்கூடும்.\n\nஇந்த அனுமதி முடக்கப்பட்டிருந்தால் இந்த ஆப்ஸ் மூலம் திட்டமிடப்பட்ட ஏற்கெனவே அமைத்த அலாரங்களும் நேர அடிப்படையிலான நிகழ்வுகளும் வேலை செய்யாது."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"திட்டமிடல், அலாரம், நினைவூட்டல், கடிகாரம்"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"தொந்தரவு செய்யாதே"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ஆன் செய்"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"தொந்தரவு செய்ய வேண்டாம் என்பதை ஆன் செய்யும்"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 0aa94a6..4811594 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"అలారాలు &amp; రిమైండర్‌లు"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"అలారాలను సెట్ చేయడానికి, టైమ్-సెన్సిటివ్ చర్యలను షెడ్యూల్ చేయడానికి ఈ యాప్‌ను అనుమతించండి. ఇది యాప్‌ను బ్యాక్‌గ్రౌండ్‌లో రన్ అవడానికి అనుమతిస్తుంది, ఇది ఎక్కువ బ్యాటరీని ఉపయోగించవచ్చు.\n\nఈ అనుమతిని ఆఫ్ చేస్తే, ఈ యాప్ ద్వారా షెడ్యూల్ చేసినటువంటి ఇప్పటికే ఉన్న అలారాలు, టైమ్-ఆధారిత ఈవెంట్‌లు పనిచేయవు."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"షెడ్యూల్, అలారం, రిమైండర్, గడియారం"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"అంతరాయం కలిగించవద్దు"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ఆన్ చేయండి"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"అంతరాయం కలిగించవద్దును ఆన్ చేయండి"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 970e456..b332154 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"การปลุกและการช่วยเตือน"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"อนุญาตให้แอปนี้ตั้งปลุกและกำหนดเวลาการดำเนินการที่ต้องคำนึงถึงเวลาเป็นสำคัญ สิทธิ์นี้ช่วยให้แอปทำงานในเบื้องหลังได้ จึงอาจทำให้ใช้แบตเตอรี่มากขึ้น\n\nหากปิดใช้สิทธิ์นี้ การปลุกที่มีอยู่และกิจกรรมที่ต้องคำนึงถึงเวลาเป็นสำคัญซึ่งแอปนี้กำหนดเวลาไว้จะไม่ทำงาน"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"กำหนดเวลา การปลุก การช่วยเตือน นาฬิกา"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"ห้ามรบกวน"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"เปิด"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"เปิด \"ห้ามรบกวน\""</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 0ba4a7b..cf88980 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Mga alarm at paalala"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Payagan ang app na ito na magtakda ng mga alarm at mag-iskedyul ng mga pagkilos na may limitadong oras. Papayagan nitong tumakbo ang app sa background, na posibleng gumamit ng mas maraming baterya.\n\nKung naka-off ang pahintulot na ito, hindi gagana ang mga kasalukuyang alarm at event na nakabatay sa oras na naiskedyul ng app na ito."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"iskedyul, alarm, paalala, orasan"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Huwag Istorbohin"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"I-on"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"I-on ang Huwag Istorbohin"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 0506480..6cdfa2e 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmlar ve hatırlatıcılar"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu uygulamanın alarm kurmasına ve zamana bağlı işlemler programlamasına izin verin. Bu izin, uygulamanın arka planda çalışmasına olanak sağlayarak daha fazla pil harcanmasına neden olabilir.\n\nBu izin verilmezse bu uygulama tarafından programlanmış mevcut alarmlar ve zamana bağlı etkinlikler çalışmaz."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"program, alarm, hatırlatıcı, saat"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Rahatsız Etmeyin"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aç"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Rahatsız Etmeyin\'i açın"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 0ee73bd..7abd4a8 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будильники й нагадування"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Дозволити цьому додатку налаштовувати будильники й створювати розклад дій. Додаток зможе працювати у фоновому режимі й використовувати більше заряду акумулятора.\n\nЯкщо вимкнути такий дозвіл, наявні будильники й дії, створені цим додатком, не працюватимуть."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"запланувати, будильник, нагадування, годинник"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Не турбувати"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Увімкнути"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Увімкнути режим \"Не турбувати\""</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 3678410..bf7ac58 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"الارمز اور یاد دہانیاں"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"اس ایپ کو الارمز سیٹ کرنے اور وقت کے لحاظ سے حساس کارروائیوں کو شیڈول کرنے کی اجازت دیں۔ اس سے ایپ کو پس منظر میں چلنے کی اجازت ملتی ہے، جس میں زیادہ بیٹری استعمال ہو سکتی ہے۔\n\n اگر یہ اجازت آف ہے تو موجودہ الارمز اور اس ایپ کے ذریعے شیڈول کردہ وقت پر مبنی ایونٹس کام نہیں کریں گے۔"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"شیڈول، الارم، یاد دہانی، گھڑی"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"ڈسٹرب نہ کریں"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"آن کریں"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'ڈسٹرب نہ کریں\' کو آن کریں"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 893cd57..2418053 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signal va eslatmalar"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu ilovaga signal oʻrnatish va vaqtga asoslangan amallarni rejalashtirishga ruxsat berish. Bunda ilovaga orqa fonda ishlashiga imkon beriladi, shu sababli batareya ortiqcha sarflanishi mumkin.\n\nAgar bu ruxsat oʻchirilsa, ushbu ilova tomonidan rejalashtirilgan mavjud signallar va vaqtga asoslangan tadbirlar ishlamaydi."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"reja, signal, eslatma, soat"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Bezovta qilinmasin"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Yoqish"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Bezovta qilinmasin rejimini yoqing"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 101d352..15839b8 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Chuông báo và lời nhắc"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Cho phép ứng dụng này đặt chuông báo và lên lịch các hành động cần chính xác về thời gian. Tùy chọn này cho phép ứng dụng chạy ở chế độ nền và có thể làm tiêu hao nhiều pin.\n\nNếu không cấp quyền này, các chuông báo và sự kiện theo thời gian do ứng dụng này lên lịch sẽ không hoạt động."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"lịch biểu, chuông báo, lời nhắc, đồng hồ"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Không làm phiền"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Bật"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Bật chế độ Không làm phiền"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 88e67f6..a2fd4ea 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"闹钟和提醒"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"允许该应用设置闹钟以及安排在特定时间执行某些操作。这项权限开启后,该应用将在后台运行,可能会消耗更多电池电量。\n\n如果您关闭此权限,该应用设置的现有闹钟将不会响起,而且该应用安排在特定时间执行的现有活动也不会执行。"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"设置, 闹钟, 提醒, 时钟, schedule, alarm, reminder, clock"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"勿扰模式"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"开启"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"开启勿扰模式"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 6a35ece..bcf624e4 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"鬧鐘和提醒"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"允許此應用程式設定鬧鐘及安排具時效性的操作。這讓應用程式在背景中執行,因此可能會較耗電。\n\n如果關閉此權限,此應用程式將不會在預定時間響起已設定的鬧鐘,亦不會就特定時間的活動傳送通知。"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"日程表, 鬧鐘, 提醒, 時鐘"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"請勿騷擾"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"開啟"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"開啟「請勿騷擾」模式"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 9d00a05..58a19793 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"鬧鐘和提醒"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"允許這個應用程式設定鬧鐘及安排有時效性的動作。之後應用程式可以在背景執行,並可能耗用較多電量。\n\n如果關閉這項權限,這個應用程式設定的現有鬧鐘將不會響起,系統也無法在預定的時間發出活動提醒。"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"時間表, 鬧鐘, 提醒, 時鐘"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"零打擾"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"開啟"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"開啟「零打擾」模式"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 0c326146..28b9b05 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -564,6 +564,8 @@
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ama-alamu nezikhumbuzi"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Vumela le app isethe ama-alamu futhi ushejule izenzo zesikhathi esizwelayo. Lokhu kuvumela i-app iqhubeke ngemuva okungasebenzisa ibhethri lakho eliningi.\n\nUma le mvume ivaliwe, ama-alamu asele nemicimbi esekelwe esikhathini ehlelwe yile app ngeke kusebenze."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ishejuli, i-alamu, isikhumbuzi, iwashi"</string>
+    <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+    <skip />
     <string name="zen_mode_settings_title" msgid="7374070457626419755">"Ungaphazamisi"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Vula"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Vula ukungaphazamisi"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingContract.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingContract.kt
new file mode 100644
index 0000000..65adec4
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingContract.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 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.settingslib.bluetooth.devicesettings
+
+/** The contract between the device settings provider services and Settings. */
+object DeviceSettingContract {
+    const val INVISIBLE_PROFILES = "INVISIBLE_PROFILES"
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt
index 457d6a3..769b6e6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt
@@ -22,6 +22,7 @@
 import com.android.settingslib.bluetooth.CachedBluetoothDevice
 import com.android.settingslib.bluetooth.devicesettings.ActionSwitchPreference
 import com.android.settingslib.bluetooth.devicesettings.DeviceSetting
+import com.android.settingslib.bluetooth.devicesettings.DeviceSettingContract
 import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId
 import com.android.settingslib.bluetooth.devicesettings.DeviceSettingItem
 import com.android.settingslib.bluetooth.devicesettings.DeviceSettingsConfig
@@ -30,6 +31,9 @@
 import com.android.settingslib.bluetooth.devicesettings.MultiTogglePreference
 import com.android.settingslib.bluetooth.devicesettings.ToggleInfo
 import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel.AppProvidedItem
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel.BuiltinItem.BluetoothProfilesItem
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem
 import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigModel
 import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon
 import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel
@@ -103,9 +107,18 @@
 
     private fun DeviceSettingItem.toModel(): DeviceSettingConfigItemModel {
         return if (!TextUtils.isEmpty(preferenceKey)) {
-            DeviceSettingConfigItemModel.BuiltinItem(settingId, preferenceKey!!)
+            if (settingId == DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_PROFILES) {
+                BluetoothProfilesItem(
+                    settingId,
+                    preferenceKey!!,
+                    extras.getStringArrayList(DeviceSettingContract.INVISIBLE_PROFILES)
+                        ?: emptyList()
+                )
+            } else {
+                CommonBuiltinItem(settingId, preferenceKey!!)
+            }
         } else {
-            DeviceSettingConfigItemModel.AppProvidedItem(settingId)
+            AppProvidedItem(settingId)
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingServiceConnection.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingServiceConnection.kt
index 33beb06..7eae5b2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingServiceConnection.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingServiceConnection.kt
@@ -23,6 +23,7 @@
 import android.content.ServiceConnection
 import android.os.IBinder
 import android.os.IInterface
+import android.text.TextUtils
 import android.util.Log
 import com.android.settingslib.bluetooth.BluetoothUtils
 import com.android.settingslib.bluetooth.CachedBluetoothDevice
@@ -84,6 +85,10 @@
                 }
                 setAction(intentAction)
             }
+
+        fun isValid(): Boolean {
+            return !TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(intentAction)
+        }
     }
 
     private var isServiceEnabled =
@@ -96,7 +101,8 @@
                     } else if (allStatus.all { it is ServiceConnectionStatus.Connected }) {
                         allStatus
                             .filterIsInstance<
-                                ServiceConnectionStatus.Connected<IDeviceSettingsProviderService>
+                                ServiceConnectionStatus.Connected<
+                                        IDeviceSettingsProviderService>
                             >()
                             .all { it.service.serviceStatus?.enabled == true }
                     } else {
@@ -215,6 +221,7 @@
                     )
                 }
             }
+            ?.filter { it.isValid() }
             ?.distinct()
             ?.associateBy(
                 { it },
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt
index c1ac763..08fb3fb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt
@@ -36,10 +36,23 @@
     @DeviceSettingId val settingId: Int
 
     /** A built-in item in Settings. */
-    data class BuiltinItem(
-        @DeviceSettingId override val settingId: Int,
-        val preferenceKey: String?
-    ) : DeviceSettingConfigItemModel
+    sealed interface BuiltinItem : DeviceSettingConfigItemModel {
+        @DeviceSettingId override val settingId: Int
+        val preferenceKey: String
+
+        /** A general built-in item in Settings. */
+        data class CommonBuiltinItem(
+            @DeviceSettingId override val settingId: Int,
+            override val preferenceKey: String,
+        ) : BuiltinItem
+
+        /** A bluetooth profiles in Settings. */
+        data class BluetoothProfilesItem(
+            @DeviceSettingId override val settingId: Int,
+            override val preferenceKey: String,
+            val invisibleProfiles: List<String>,
+        ) : BuiltinItem
+    }
 
     /** A remote item provided by other apps. */
     data class AppProvidedItem(@DeviceSettingId override val settingId: Int) :
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt
index 043219a..c686708 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt
@@ -61,6 +61,10 @@
         mutableModesFlow.value += zenModes
     }
 
+    fun addMode(mode: ZenMode) {
+        mutableModesFlow.value += mode
+    }
+
     fun addMode(id: String, @AutomaticZenRule.Type type: Int = AutomaticZenRule.TYPE_UNKNOWN,
         active: Boolean = false) {
         mutableModesFlow.value += newMode(id, type, active)
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt
index ce155b5..81b5634 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt
@@ -91,7 +91,9 @@
         `when`(cachedDevice.address).thenReturn(BLUETOOTH_ADDRESS)
         `when`(
                 bluetoothDevice.getMetadata(
-                    DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
+                    DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS
+                )
+            )
             .thenReturn(BLUETOOTH_DEVICE_METADATA.toByteArray())
 
         `when`(configService.queryLocalInterface(anyString())).thenReturn(configService)
@@ -114,7 +116,8 @@
                     connection.onServiceConnected(
                         ComponentName(
                             SETTING_PROVIDER_SERVICE_PACKAGE_NAME_1,
-                            SETTING_PROVIDER_SERVICE_CLASS_NAME_1),
+                            SETTING_PROVIDER_SERVICE_CLASS_NAME_1,
+                        ),
                         settingProviderService1,
                     )
                 SETTING_PROVIDER_SERVICE_INTENT_ACTION_2 ->
@@ -146,16 +149,24 @@
     fun getDeviceSettingsConfig_withMetadata_success() {
         testScope.runTest {
             `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
-            `when`(settingProviderService1.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
-            `when`(settingProviderService2.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
+            `when`(settingProviderService1.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
+            `when`(settingProviderService2.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
 
             val config = underTest.getDeviceSettingsConfig(cachedDevice)
 
             assertConfig(config!!, DEVICE_SETTING_CONFIG)
+            assertThat(config.mainItems[0])
+                .isInstanceOf(DeviceSettingConfigItemModel.AppProvidedItem::class.java)
+            assertThat(config.mainItems[1])
+                .isInstanceOf(
+                    DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem::class.java
+                )
+            assertThat(config.mainItems[2])
+                .isInstanceOf(
+                    DeviceSettingConfigItemModel.BuiltinItem.BluetoothProfilesItem::class.java
+                )
         }
     }
 
@@ -163,16 +174,16 @@
     fun getDeviceSettingsConfig_noMetadata_returnNull() {
         testScope.runTest {
             `when`(
-                bluetoothDevice.getMetadata(
-                    DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
+                    bluetoothDevice.getMetadata(
+                        DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS
+                    )
+                )
                 .thenReturn("".toByteArray())
             `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
-            `when`(settingProviderService1.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
-            `when`(settingProviderService2.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
+            `when`(settingProviderService1.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
+            `when`(settingProviderService2.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
 
             val config = underTest.getDeviceSettingsConfig(cachedDevice)
 
@@ -184,12 +195,10 @@
     fun getDeviceSettingsConfig_providerServiceNotEnabled_returnNull() {
         testScope.runTest {
             `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
-            `when`(settingProviderService1.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(false)
-            )
-            `when`(settingProviderService2.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
+            `when`(settingProviderService1.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(false))
+            `when`(settingProviderService2.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
 
             val config = underTest.getDeviceSettingsConfig(cachedDevice)
 
@@ -219,12 +228,10 @@
                     .getArgument<IDeviceSettingsListener>(1)
                     .onDeviceSettingsChanged(listOf(DEVICE_SETTING_1))
             }
-            `when`(settingProviderService1.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
-            `when`(settingProviderService2.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
+            `when`(settingProviderService1.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
+            `when`(settingProviderService2.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
             var setting: DeviceSettingModel? = null
 
             underTest
@@ -247,12 +254,10 @@
                     .getArgument<IDeviceSettingsListener>(1)
                     .onDeviceSettingsChanged(listOf(DEVICE_SETTING_2))
             }
-            `when`(settingProviderService1.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
-            `when`(settingProviderService2.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
+            `when`(settingProviderService1.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
+            `when`(settingProviderService2.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
             var setting: DeviceSettingModel? = null
 
             underTest
@@ -270,17 +275,15 @@
         testScope.runTest {
             `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
             `when`(settingProviderService2.registerDeviceSettingsListener(any(), any())).then {
-                    input ->
+                input ->
                 input
                     .getArgument<IDeviceSettingsListener>(1)
                     .onDeviceSettingsChanged(listOf(DEVICE_SETTING_HELP))
             }
-            `when`(settingProviderService1.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
-            `when`(settingProviderService2.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
+            `when`(settingProviderService1.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
+            `when`(settingProviderService2.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
             var setting: DeviceSettingModel? = null
 
             underTest
@@ -324,12 +327,10 @@
                     .getArgument<IDeviceSettingsListener>(1)
                     .onDeviceSettingsChanged(listOf(DEVICE_SETTING_1))
             }
-            `when`(settingProviderService1.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
-            `when`(settingProviderService2.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
+            `when`(settingProviderService1.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
+            `when`(settingProviderService2.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
             var setting: DeviceSettingModel? = null
 
             underTest
@@ -347,8 +348,10 @@
                     DeviceSettingState.Builder()
                         .setSettingId(DeviceSettingId.DEVICE_SETTING_ID_HEADER)
                         .setPreferenceState(
-                            ActionSwitchPreferenceState.Builder().setChecked(false).build())
-                        .build())
+                            ActionSwitchPreferenceState.Builder().setChecked(false).build()
+                        )
+                        .build(),
+                )
         }
     }
 
@@ -362,12 +365,10 @@
                     .getArgument<IDeviceSettingsListener>(1)
                     .onDeviceSettingsChanged(listOf(DEVICE_SETTING_2))
             }
-            `when`(settingProviderService1.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
-            `when`(settingProviderService2.serviceStatus).thenReturn(
-                DeviceSettingsProviderServiceStatus(true)
-            )
+            `when`(settingProviderService1.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
+            `when`(settingProviderService2.serviceStatus)
+                .thenReturn(DeviceSettingsProviderServiceStatus(true))
             var setting: DeviceSettingModel? = null
 
             underTest
@@ -385,8 +386,10 @@
                     DeviceSettingState.Builder()
                         .setSettingId(DeviceSettingId.DEVICE_SETTING_ID_ANC)
                         .setPreferenceState(
-                            MultiTogglePreferenceState.Builder().setState(2).build())
-                        .build())
+                            MultiTogglePreferenceState.Builder().setState(2).build()
+                        )
+                        .build(),
+                )
         }
     }
 
@@ -437,7 +440,7 @@
 
     private fun assertConfig(
         actual: DeviceSettingConfigModel,
-        serviceResponse: DeviceSettingsConfig
+        serviceResponse: DeviceSettingsConfig,
     ) {
         assertThat(actual.mainItems.size).isEqualTo(serviceResponse.mainContentItems.size)
         for (i in 0..<actual.mainItems.size) {
@@ -451,7 +454,7 @@
 
     private fun assertConfigItem(
         actual: DeviceSettingConfigItemModel,
-        serviceResponse: DeviceSettingItem
+        serviceResponse: DeviceSettingItem,
     ) {
         assertThat(actual.settingId).isEqualTo(serviceResponse.settingId)
     }
@@ -485,24 +488,43 @@
                 "</DEVICE_SETTINGS_CONFIG_ACTION>"
         val DEVICE_INFO = DeviceInfo.Builder().setBluetoothAddress(BLUETOOTH_ADDRESS).build()
         const val DEVICE_SETTING_ID_HELP = 12345
-        val DEVICE_SETTING_ITEM_1 =
+        val DEVICE_SETTING_APP_PROVIDED_ITEM_1 =
             DeviceSettingItem(
                 DeviceSettingId.DEVICE_SETTING_ID_HEADER,
                 SETTING_PROVIDER_SERVICE_PACKAGE_NAME_1,
                 SETTING_PROVIDER_SERVICE_CLASS_NAME_1,
-                SETTING_PROVIDER_SERVICE_INTENT_ACTION_1)
-        val DEVICE_SETTING_ITEM_2 =
+                SETTING_PROVIDER_SERVICE_INTENT_ACTION_1,
+            )
+        val DEVICE_SETTING_APP_PROVIDED_ITEM_2 =
             DeviceSettingItem(
                 DeviceSettingId.DEVICE_SETTING_ID_ANC,
                 SETTING_PROVIDER_SERVICE_PACKAGE_NAME_2,
                 SETTING_PROVIDER_SERVICE_CLASS_NAME_2,
-                SETTING_PROVIDER_SERVICE_INTENT_ACTION_2)
+                SETTING_PROVIDER_SERVICE_INTENT_ACTION_2,
+            )
+        val DEVICE_SETTING_BUILT_IN_ITEM =
+            DeviceSettingItem(
+                DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_AUDIO_DEVICE_TYPE_GROUP,
+                "",
+                "",
+                "",
+                "device_type",
+            )
+        val DEVICE_SETTING_BUILT_IN_BT_PROFILES_ITEM =
+            DeviceSettingItem(
+                DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_PROFILES,
+                "",
+                "",
+                "",
+                "bluetooth_profiles",
+            )
         val DEVICE_SETTING_HELP_ITEM =
             DeviceSettingItem(
                 DEVICE_SETTING_ID_HELP,
                 SETTING_PROVIDER_SERVICE_PACKAGE_NAME_2,
                 SETTING_PROVIDER_SERVICE_CLASS_NAME_2,
-                SETTING_PROVIDER_SERVICE_INTENT_ACTION_2)
+                SETTING_PROVIDER_SERVICE_INTENT_ACTION_2,
+            )
         val DEVICE_SETTING_1 =
             DeviceSetting.Builder()
                 .setSettingId(DeviceSettingId.DEVICE_SETTING_ID_HEADER)
@@ -511,7 +533,8 @@
                         .setTitle("title1")
                         .setHasSwitch(true)
                         .setAllowedChangingState(true)
-                        .build())
+                        .build()
+                )
                 .build()
         val DEVICE_SETTING_2 =
             DeviceSetting.Builder()
@@ -524,22 +547,30 @@
                             ToggleInfo.Builder()
                                 .setLabel("label1")
                                 .setIcon(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888))
-                                .build())
+                                .build()
+                        )
                         .addToggleInfo(
                             ToggleInfo.Builder()
                                 .setLabel("label2")
                                 .setIcon(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888))
-                                .build())
-                        .build())
+                                .build()
+                        )
+                        .build()
+                )
                 .build()
-        val DEVICE_SETTING_HELP = DeviceSetting.Builder()
-            .setSettingId(DEVICE_SETTING_ID_HELP)
-            .setPreference(DeviceSettingHelpPreference.Builder().setIntent(Intent()).build())
-            .build()
+        val DEVICE_SETTING_HELP =
+            DeviceSetting.Builder()
+                .setSettingId(DEVICE_SETTING_ID_HELP)
+                .setPreference(DeviceSettingHelpPreference.Builder().setIntent(Intent()).build())
+                .build()
         val DEVICE_SETTING_CONFIG =
             DeviceSettingsConfig(
-                listOf(DEVICE_SETTING_ITEM_1),
-                listOf(DEVICE_SETTING_ITEM_2),
+                listOf(
+                    DEVICE_SETTING_APP_PROVIDED_ITEM_1,
+                    DEVICE_SETTING_BUILT_IN_ITEM,
+                    DEVICE_SETTING_BUILT_IN_BT_PROFILES_ITEM,
+                ),
+                listOf(DEVICE_SETTING_APP_PROVIDED_ITEM_2),
                 DEVICE_SETTING_HELP_ITEM,
             )
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
index ca53fc2..3f3e1b2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
@@ -291,4 +291,12 @@
 
         assertThat(mPreference.isApplyDynamicColor()).isTrue();
     }
+
+    @Test
+    public void setContentDescription_getContentDescription_isEqual() {
+        final String contentDesc = "content desc";
+        mPreference.setContentDescription(contentDesc);
+
+        assertThat(mPreference.getContentDescription().toString()).isEqualTo(contentDesc);
+    }
 }
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 0b5187c..f3c5a18 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -941,6 +941,13 @@
     <!-- Permission required for CTS test - FileIntegrityManagerTest -->
     <uses-permission android:name="android.permission.SETUP_FSVERITY" />
 
+    <!-- Permissions required for CTS test - AppFunctionManagerTest -->
+    <uses-permission android:name="android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED" />
+    <uses-permission android:name="android.permission.EXECUTE_APP_FUNCTIONS" />
+
+    <!-- Permission required for CTS test - CtsNfcTestCases -->
+    <uses-permission android:name="android.permission.NFC_SET_CONTROLLER_ALWAYS_ON" />
+
     <application
         android:label="@string/app_label"
         android:theme="@android:style/Theme.DeviceDefault.DayNight"
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index d26a906..a9e81c7 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -756,6 +756,7 @@
         "notification_flags_lib",
         "PlatformComposeCore",
         "PlatformComposeSceneTransitionLayout",
+        "PlatformComposeSceneTransitionLayoutTestsUtils",
         "androidx.compose.runtime_runtime",
         "androidx.compose.material3_material3",
         "androidx.compose.material_material-icons-extended",
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant.xml
similarity index 89%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant.xml
index 9c3417f..6408a12 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant.xml
@@ -1,6 +1,6 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="108dp"
+    android:height="108dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
     android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_down_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_down.xml
similarity index 92%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_down_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_down.xml
index a64a0d1..f13239c 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_down_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_down.xml
@@ -1,6 +1,6 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="108dp"
+    android:height="108dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
     android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_up_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_up.xml
similarity index 95%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_up_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_up.xml
index 40423c7..a5d15f9 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_up_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_up.xml
@@ -15,8 +15,8 @@
   -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="108dp"
+    android:height="108dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
     android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_lock_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_lock.xml
similarity index 90%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_lock_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_lock.xml
index a0f7b5d..2127632 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_lock_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_lock.xml
@@ -1,6 +1,6 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="108dp"
+    android:height="108dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
     android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_notifications_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_notifications.xml
similarity index 90%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_notifications_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_notifications.xml
index 8757f22..62c8d1d 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_notifications_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_notifications.xml
@@ -1,6 +1,6 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="108dp"
+    android:height="108dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
     android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_power_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_power.xml
similarity index 90%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_power_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_power.xml
index 049013a..ed11b44 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_power_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_power.xml
@@ -1,6 +1,6 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="108dp"
+    android:height="108dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
     android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_quick_settings_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_quick_settings.xml
similarity index 97%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_quick_settings_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_quick_settings.xml
index 4f25e7d..2da63a6 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_quick_settings_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_quick_settings.xml
@@ -15,8 +15,8 @@
   -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="108dp"
+    android:height="108dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
     android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_recent_apps_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_recent_apps.xml
similarity index 94%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_recent_apps_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_recent_apps.xml
index 38234c0..9763b8e 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_recent_apps_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_recent_apps.xml
@@ -15,8 +15,8 @@
   -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="108dp"
+    android:height="108dp"
     android:viewportWidth="24"
     android:viewportHeight="24"
     android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_screenshot_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_screenshot.xml
similarity index 95%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_screenshot_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_screenshot.xml
index 6d7f49c..2bfbd5b 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_screenshot_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_screenshot.xml
@@ -15,8 +15,8 @@
   -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="108dp"
+    android:height="108dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
     android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_settings_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_settings.xml
similarity index 95%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_settings_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_settings.xml
index 5ed6f19..4ca9bfc 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_settings_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_settings.xml
@@ -15,8 +15,8 @@
   -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="108dp"
+    android:height="108dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
     android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_down_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_down.xml
similarity index 94%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_down_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_down.xml
index 16653e8..f924e5e 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_down_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_down.xml
@@ -15,8 +15,8 @@
   -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="108dp"
+    android:height="108dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
     android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_up_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_up.xml
similarity index 95%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_up_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_up.xml
index e572c6a..41fe351 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_up_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_up.xml
@@ -15,8 +15,8 @@
   -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="108dp"
+    android:height="108dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
     android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/menuitem_background_ripple.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/menuitem_background_ripple.xml
new file mode 100644
index 0000000..6cab464
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/menuitem_background_ripple.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2024 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.
+  -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/ripple_material_color" />
\ No newline at end of file
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
index 3c73eca..a1130e6 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
@@ -12,7 +12,8 @@
       android:layout_height="@dimen/image_button_height"
       android:layout_alignParentTop="true"
       android:layout_centerHorizontal="true"
-      android:scaleType="fitCenter"/>
+      android:scaleType="fitCenter"
+      android:background="@drawable/menuitem_background_ripple" />
 
   <TextView
       android:id="@+id/shortcutLabel"
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
index c698d18..11ce41e 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
@@ -53,73 +53,73 @@
     /** Map stores all shortcut resource IDs that is in matching order of defined shortcut. */
     private static final Map<ShortcutId, int[]> sShortcutResource = Map.ofEntries(
             Map.entry(ShortcutId.ID_ASSISTANT_VALUE, new int[] {
-                    R.drawable.ic_logo_a11y_assistant_24dp,
+                    R.drawable.ic_logo_a11y_assistant,
                     R.color.assistant_color,
                     R.string.assistant_utterance,
                     R.string.assistant_label,
             }),
             Map.entry(ShortcutId.ID_A11YSETTING_VALUE, new int[] {
-                    R.drawable.ic_logo_a11y_settings_24dp,
+                    R.drawable.ic_logo_a11y_settings,
                     R.color.a11y_settings_color,
                     R.string.a11y_settings_label,
                     R.string.a11y_settings_label,
             }),
             Map.entry(ShortcutId.ID_POWER_VALUE, new int[] {
-                    R.drawable.ic_logo_a11y_power_24dp,
+                    R.drawable.ic_logo_a11y_power,
                     R.color.power_color,
                     R.string.power_utterance,
                     R.string.power_label,
             }),
             Map.entry(ShortcutId.ID_RECENT_VALUE, new int[] {
-                    R.drawable.ic_logo_a11y_recent_apps_24dp,
+                    R.drawable.ic_logo_a11y_recent_apps,
                     R.color.recent_apps_color,
                     R.string.recent_apps_label,
                     R.string.recent_apps_label,
             }),
             Map.entry(ShortcutId.ID_LOCKSCREEN_VALUE, new int[] {
-                    R.drawable.ic_logo_a11y_lock_24dp,
+                    R.drawable.ic_logo_a11y_lock,
                     R.color.lockscreen_color,
                     R.string.lockscreen_label,
                     R.string.lockscreen_label,
             }),
             Map.entry(ShortcutId.ID_QUICKSETTING_VALUE, new int[] {
-                    R.drawable.ic_logo_a11y_quick_settings_24dp,
+                    R.drawable.ic_logo_a11y_quick_settings,
                     R.color.quick_settings_color,
                     R.string.quick_settings_label,
                     R.string.quick_settings_label,
             }),
             Map.entry(ShortcutId.ID_NOTIFICATION_VALUE, new int[] {
-                    R.drawable.ic_logo_a11y_notifications_24dp,
+                    R.drawable.ic_logo_a11y_notifications,
                     R.color.notifications_color,
                     R.string.notifications_label,
                     R.string.notifications_label,
             }),
             Map.entry(ShortcutId.ID_SCREENSHOT_VALUE, new int[] {
-                    R.drawable.ic_logo_a11y_screenshot_24dp,
+                    R.drawable.ic_logo_a11y_screenshot,
                     R.color.screenshot_color,
                     R.string.screenshot_utterance,
                     R.string.screenshot_label,
             }),
             Map.entry(ShortcutId.ID_BRIGHTNESS_UP_VALUE, new int[] {
-                    R.drawable.ic_logo_a11y_brightness_up_24dp,
+                    R.drawable.ic_logo_a11y_brightness_up,
                     R.color.brightness_color,
                     R.string.brightness_up_label,
                     R.string.brightness_up_label,
             }),
             Map.entry(ShortcutId.ID_BRIGHTNESS_DOWN_VALUE, new int[] {
-                    R.drawable.ic_logo_a11y_brightness_down_24dp,
+                    R.drawable.ic_logo_a11y_brightness_down,
                     R.color.brightness_color,
                     R.string.brightness_down_label,
                     R.string.brightness_down_label,
             }),
             Map.entry(ShortcutId.ID_VOLUME_UP_VALUE, new int[] {
-                    R.drawable.ic_logo_a11y_volume_up_24dp,
+                    R.drawable.ic_logo_a11y_volume_up,
                     R.color.volume_color,
                     R.string.volume_up_label,
                     R.string.volume_up_label,
             }),
             Map.entry(ShortcutId.ID_VOLUME_DOWN_VALUE, new int[] {
-                    R.drawable.ic_logo_a11y_volume_down_24dp,
+                    R.drawable.ic_logo_a11y_volume_down,
                     R.color.volume_color,
                     R.string.volume_down_label,
                     R.string.volume_down_label,
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/utils/ShortcutDrawableUtils.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/utils/ShortcutDrawableUtils.java
deleted file mode 100644
index 28ba4b5..0000000
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/utils/ShortcutDrawableUtils.java
+++ /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.accessibility.accessibilitymenu.utils;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.drawable.AdaptiveIconDrawable;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.RippleDrawable;
-
-import com.android.systemui.accessibility.accessibilitymenu.R;
-
-/** Creates background drawable for a11y menu shortcut. */
-public class ShortcutDrawableUtils {
-
-    /**
-     * To make the circular background of shortcut icons have higher resolution. The higher value of
-     * LENGTH is, the higher resolution of the circular background are.
-     */
-    private static final int LENGTH = 480;
-
-    private static final int RADIUS = LENGTH / 2;
-    private static final int COORDINATE = LENGTH / 2;
-    private static final int RIPPLE_COLOR_ID = R.color.ripple_material_color;
-
-    private final Context mContext;
-    private final ColorStateList mRippleColorStateList;
-
-    // Placeholder of drawable to prevent NullPointerException
-    private final ColorDrawable mTransparentDrawable = new ColorDrawable(Color.TRANSPARENT);
-
-    public ShortcutDrawableUtils(Context context) {
-        this.mContext = context;
-
-        int rippleColor = context.getColor(RIPPLE_COLOR_ID);
-        mRippleColorStateList = ColorStateList.valueOf(rippleColor);
-    }
-
-    /**
-     * Creates a circular drawable in specific color for shortcut.
-     *
-     * @param colorResId color resource ID
-     * @return drawable circular drawable
-     */
-    public Drawable createCircularDrawable(int colorResId) {
-        Bitmap output = Bitmap.createBitmap(LENGTH, LENGTH, Config.ARGB_8888);
-        Canvas canvas = new Canvas(output);
-        int color = mContext.getColor(colorResId);
-        Paint paint = new Paint();
-        paint.setColor(color);
-        paint.setStrokeCap(Paint.Cap.ROUND);
-        paint.setStyle(Style.FILL);
-        canvas.drawCircle(COORDINATE, COORDINATE, RADIUS, paint);
-
-        BitmapDrawable drawable = new BitmapDrawable(mContext.getResources(), output);
-        return drawable;
-    }
-
-    /**
-     * Creates an adaptive icon drawable in specific color for shortcut.
-     *
-     * @param colorResId color resource ID
-     * @return drawable for adaptive icon
-     */
-    public Drawable createAdaptiveIconDrawable(int colorResId) {
-        Drawable circleLayer = createCircularDrawable(colorResId);
-        RippleDrawable rippleLayer = new RippleDrawable(mRippleColorStateList, null, null);
-
-        AdaptiveIconDrawable adaptiveIconDrawable =
-                new AdaptiveIconDrawable(circleLayer, mTransparentDrawable);
-
-        Drawable[] layers = {adaptiveIconDrawable, rippleLayer};
-        LayerDrawable drawable = new LayerDrawable(layers);
-        return drawable;
-    }
-}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
index c333a7a..aa1bbbd 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
@@ -16,7 +16,12 @@
 
 package com.android.systemui.accessibility.accessibilitymenu.view;
 
+import android.content.res.Resources;
 import android.graphics.Rect;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
 import android.view.LayoutInflater;
 import android.view.TouchDelegate;
 import android.view.View;
@@ -26,11 +31,12 @@
 import android.widget.ImageButton;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
+
 import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
 import com.android.systemui.accessibility.accessibilitymenu.R;
 import com.android.systemui.accessibility.accessibilitymenu.activity.A11yMenuSettingsActivity.A11yMenuPreferenceFragment;
 import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut;
-import com.android.systemui.accessibility.accessibilitymenu.utils.ShortcutDrawableUtils;
 
 import java.util.List;
 
@@ -43,16 +49,12 @@
 
     private final AccessibilityMenuService mService;
     private final List<A11yMenuShortcut> mShortcutDataList;
-    private final ShortcutDrawableUtils mShortcutDrawableUtils;
 
     public A11yMenuAdapter(
             AccessibilityMenuService service,
             List<A11yMenuShortcut> shortcutDataList) {
         this.mService = service;
         this.mShortcutDataList = shortcutDataList;
-
-        mShortcutDrawableUtils = new ShortcutDrawableUtils(service);
-
         mLargeTextSize =
                 service.getResources().getDimensionPixelOffset(R.dimen.large_label_text_size);
     }
@@ -152,10 +154,10 @@
             shortcutIconButton.setContentDescription(
                     mService.getString(shortcutItem.imgContentDescription));
             shortcutLabel.setText(shortcutItem.labelText);
-            shortcutIconButton.setImageResource(shortcutItem.imageSrc);
 
-            shortcutIconButton.setBackground(
-                    mShortcutDrawableUtils.createAdaptiveIconDrawable(shortcutItem.imageColor));
+            AdaptiveIconDrawable iconDrawable = getAdaptiveIconDrawable(convertView,
+                    shortcutItem);
+            shortcutIconButton.setImageDrawable(iconDrawable);
 
             shortcutIconButton.setAccessibilityDelegate(new View.AccessibilityDelegate() {
                 @Override
@@ -167,4 +169,18 @@
             });
         }
     }
+
+    @NonNull
+    private static AdaptiveIconDrawable getAdaptiveIconDrawable(@NonNull View convertView,
+            @NonNull A11yMenuShortcut shortcutItem) {
+        Resources resources = convertView.getResources();
+        // Note: from the official guide, the foreground image of the adaptive icon should be
+        // sized at 108 x 108 dp
+        Drawable icon = resources.getDrawable(shortcutItem.imageSrc);
+        float inset = AdaptiveIconDrawable.getExtraInsetFraction();
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+                new ColorDrawable(resources.getColor(shortcutItem.imageColor)),
+                new InsetDrawable(icon, inset));
+        return iconDrawable;
+    }
 }
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
index 35f1248..b899c45 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
@@ -306,6 +306,10 @@
                     (viewPagerHeight - topMargin - defaultMargin
                             - (rowsInGridView * gridItemHeight))
                             / (rowsInGridView + 1);
+            // The interval is negative number when the viewPagerHeight is not able to fit
+            // the grid items, which result in text overlapping.
+            // Adjust the interval to 0 could solve the issue.
+            interval = Math.max(interval, 0);
             mViewPagerAdapter.setVerticalSpacing(interval);
 
             // Sets padding to view pager.
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index d1a59af..ad14035 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -288,6 +288,16 @@
 }
 
 flag {
+  name: "qs_quick_rebind_active_tiles"
+  namespace: "systemui"
+  description: "Rebind active custom tiles quickly."
+  bug: "362526228"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
     name: "coroutine_tracing"
     namespace: "systemui"
     description: "Adds thread-local data to System UI's global coroutine scopes to "
@@ -606,16 +616,6 @@
 }
 
 flag {
-    name: "screenshot_save_image_exporter"
-    namespace: "systemui"
-    description: "Save all screenshots using ImageExporter"
-    bug: "352308052"
-    metadata {
-        purpose: PURPOSE_BUGFIX
-    }
-}
-
-flag {
     name: "screenshot_ui_controller_refactor"
     namespace: "systemui"
     description: "Simplify and refactor ScreenshotController"
@@ -1396,3 +1396,9 @@
     }
 }
 
+flag {
+   name: "non_touchscreen_devices_bypass_falsing"
+   namespace: "systemui"
+   description: "Allow non-touchscreen devices to bypass falsing"
+   bug: "319809270"
+}
\ No newline at end of file
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
index 7fb88e8..ae92d259 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
@@ -99,8 +99,8 @@
         BouncerContent(
             viewModel,
             dialogFactory,
-            Modifier.sysuiResTag(Bouncer.TestTags.Root)
-                .element(Bouncer.Elements.Content)
+            Modifier.element(Bouncer.Elements.Content)
+                .sysuiResTag(Bouncer.TestTags.Root)
                 .fillMaxSize()
         )
     }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index ed12776..a4dc8fc 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -216,7 +216,7 @@
 
 /** Scene containing the glanceable hub UI. */
 @Composable
-private fun SceneScope.CommunalScene(
+fun SceneScope.CommunalScene(
     backgroundType: CommunalBackgroundType,
     colors: CommunalColors,
     content: CommunalContent,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 201c419..c63b29d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -65,6 +65,7 @@
 import androidx.compose.foundation.lazy.grid.GridItemSpan
 import androidx.compose.foundation.lazy.grid.LazyGridState
 import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
+import androidx.compose.foundation.lazy.grid.itemsIndexed
 import androidx.compose.foundation.lazy.grid.rememberLazyGridState
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.selection.selectable
@@ -136,6 +137,7 @@
 import androidx.compose.ui.semantics.contentDescription
 import androidx.compose.ui.semantics.customActions
 import androidx.compose.ui.semantics.onClick
+import androidx.compose.ui.semantics.paneTitle
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.semantics.testTagsAsResourceId
 import androidx.compose.ui.text.style.TextAlign
@@ -240,10 +242,15 @@
         }
     }
 
+    val paneTitle = stringResource(R.string.accessibility_content_description_for_communal_hub)
+
     Box(
         modifier =
             modifier
-                .semantics { testTagsAsResourceId = true }
+                .semantics {
+                    testTagsAsResourceId = true
+                    this.paneTitle = paneTitle
+                }
                 .testTag(COMMUNAL_HUB_TEST_TAG)
                 .fillMaxSize()
                 // Observe taps for selecting items
@@ -690,21 +697,20 @@
         horizontalArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing),
         verticalArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing),
     ) {
-        items(
-            count = list.size,
-            key = { index -> list[index].key },
-            contentType = { index -> list[index].key },
-            span = { index -> GridItemSpan(list[index].size.span) },
-        ) { index ->
+        itemsIndexed(
+            items = list,
+            key = { _, item -> item.key },
+            contentType = { _, item -> item.key },
+            span = { _, item -> GridItemSpan(item.size.span) },
+        ) { index, item ->
             val size =
                 SizeF(
                     Dimensions.CardWidth.value,
-                    list[index].size.dp().value,
+                    item.size.dp().value,
                 )
             val cardModifier = Modifier.requiredSize(width = size.width.dp, height = size.height.dp)
             if (viewModel.isEditMode && dragDropState != null) {
-                val selected by
-                    remember(index) { derivedStateOf { list[index].key == selectedKey.value } }
+                val selected = item.key == selectedKey.value
                 DraggableItem(
                     modifier =
                         if (dragDropState.draggingItemIndex == index) {
@@ -716,12 +722,12 @@
                         },
                     dragDropState = dragDropState,
                     selected = selected,
-                    enabled = list[index].isWidgetContent(),
+                    enabled = item.isWidgetContent(),
                     index = index,
                 ) { isDragging ->
                     CommunalContent(
                         modifier = cardModifier,
-                        model = list[index],
+                        model = item,
                         viewModel = viewModel,
                         size = size,
                         selected = selected && !isDragging,
@@ -734,7 +740,7 @@
                 }
             } else {
                 CommunalContent(
-                    model = list[index],
+                    model = item,
                     viewModel = viewModel,
                     size = size,
                     selected = false,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
index 8b6de6a..e41a7df 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
@@ -17,20 +17,21 @@
 package com.android.systemui.communal.ui.compose
 
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.ui.Modifier
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
 import com.android.compose.animation.scene.SceneScope
 import com.android.compose.animation.scene.Swipe
 import com.android.compose.animation.scene.SwipeDirection
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
-import com.android.systemui.communal.ui.view.layout.sections.CommunalAppWidgetSection
+import com.android.systemui.communal.shared.model.CommunalBackgroundType
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
-import com.android.systemui.communal.widgets.WidgetInteractionHandler
+import com.android.systemui.communal.util.CommunalColors
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.lifecycle.ExclusiveActivatable
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.ui.composable.Scene
-import com.android.systemui.statusbar.phone.SystemUIDialogFactory
 import javax.inject.Inject
 import kotlinx.coroutines.awaitCancellation
 import kotlinx.coroutines.flow.Flow
@@ -43,9 +44,8 @@
 @Inject
 constructor(
     private val viewModel: CommunalViewModel,
-    private val dialogFactory: SystemUIDialogFactory,
-    private val interactionHandler: WidgetInteractionHandler,
-    private val widgetSection: CommunalAppWidgetSection,
+    private val communalColors: CommunalColors,
+    private val communalContent: CommunalContent,
 ) : ExclusiveActivatable(), Scene {
     override val key = Scenes.Communal
 
@@ -63,12 +63,17 @@
 
     @Composable
     override fun SceneScope.Content(modifier: Modifier) {
-        CommunalHub(
-            modifier = modifier,
+        val backgroundType by
+            viewModel.communalBackground.collectAsStateWithLifecycle(
+                initialValue = CommunalBackgroundType.ANIMATED
+            )
+
+        CommunalScene(
+            backgroundType = backgroundType,
+            colors = communalColors,
+            content = communalContent,
             viewModel = viewModel,
-            interactionHandler = interactionHandler,
-            widgetSection = widgetSection,
-            dialogFactory = dialogFactory,
+            modifier = modifier.horizontalNestedScrollToScene(),
         )
     }
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt
index ecb3d8c..c25a45d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt
@@ -52,6 +52,7 @@
 import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
 import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerMessageAreaViewModel
 import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel
+import com.android.systemui.log.LongPressHandlingViewLogger
 import com.android.systemui.res.R
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 
@@ -97,6 +98,7 @@
             Box {
                 DeviceEntryIcon(
                     viewModel = alternateBouncerDependencies.udfpsIconViewModel,
+                    logger = alternateBouncerDependencies.logger,
                     modifier =
                         Modifier.width { udfpsLocation.width }
                             .height { udfpsLocation.height }
@@ -151,13 +153,14 @@
 @Composable
 private fun DeviceEntryIcon(
     viewModel: AlternateBouncerUdfpsIconViewModel,
+    logger: LongPressHandlingViewLogger,
     modifier: Modifier = Modifier,
 ) {
     AndroidView(
         modifier = modifier,
         factory = { context ->
             val view =
-                DeviceEntryIconView(context, null).apply {
+                DeviceEntryIconView(context, null, logger = logger).apply {
                     id = R.id.alternate_bouncer_udfps_icon_view
                     contentDescription =
                         context.resources.getString(R.string.accessibility_fingerprint_label)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt
index 4129c25..a525f36 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt
@@ -18,7 +18,6 @@
 
 import android.content.Context
 import android.util.DisplayMetrics
-import android.view.View
 import android.view.WindowManager
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
@@ -45,9 +44,11 @@
 import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryBackgroundViewModel
 import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryForegroundViewModel
 import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LongPressHandlingViewLogger
+import com.android.systemui.log.dagger.LongPressTouchLog
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.res.R
-import com.android.systemui.shade.NotificationPanelView
 import com.android.systemui.statusbar.VibratorHelper
 import dagger.Lazy
 import javax.inject.Inject
@@ -66,7 +67,7 @@
     private val deviceEntryBackgroundViewModel: Lazy<DeviceEntryBackgroundViewModel>,
     private val falsingManager: Lazy<FalsingManager>,
     private val vibratorHelper: Lazy<VibratorHelper>,
-    private val notificationPanelView: NotificationPanelView,
+    @LongPressTouchLog private val logBuffer: LogBuffer,
 ) {
     @Composable
     fun SceneScope.LockIcon(overrideColor: Color? = null, modifier: Modifier = Modifier) {
@@ -74,29 +75,30 @@
             return
         }
 
-        notificationPanelView.findViewById<View?>(R.id.lock_icon_view)?.let {
-            notificationPanelView.removeView(it)
-        }
-
         val context = LocalContext.current
 
         AndroidView(
             factory = { context ->
                 val view =
                     if (DeviceEntryUdfpsRefactor.isEnabled) {
-                        DeviceEntryIconView(context, null).apply {
-                            id = R.id.device_entry_icon_view
-                            DeviceEntryIconViewBinder.bind(
-                                applicationScope,
-                                this,
-                                deviceEntryIconViewModel.get(),
-                                deviceEntryForegroundViewModel.get(),
-                                deviceEntryBackgroundViewModel.get(),
-                                falsingManager.get(),
-                                vibratorHelper.get(),
-                                overrideColor,
+                        DeviceEntryIconView(
+                                context,
+                                null,
+                                logger = LongPressHandlingViewLogger(logBuffer, tag = TAG)
                             )
-                        }
+                            .apply {
+                                id = R.id.device_entry_icon_view
+                                DeviceEntryIconViewBinder.bind(
+                                    applicationScope,
+                                    this,
+                                    deviceEntryIconViewModel.get(),
+                                    deviceEntryForegroundViewModel.get(),
+                                    deviceEntryBackgroundViewModel.get(),
+                                    falsingManager.get(),
+                                    vibratorHelper.get(),
+                                    overrideColor,
+                                )
+                            }
                     } else {
                         // KeyguardBottomAreaRefactor.isEnabled
                         LockIconView(context, null).apply {
@@ -185,6 +187,10 @@
 
         return IntRect(center, radius)
     }
+
+    companion object {
+        private const val TAG = "LockSection"
+    }
 }
 
 private val LockIconElementKey = ElementKey("LockIcon")
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt
index 4b3a39b..897a861 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt
@@ -23,11 +23,13 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.nestedscroll.NestedScrollSource
 import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.unit.IntOffset
 import com.android.compose.nestedscroll.PriorityNestedScrollConnection
+import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight
+import kotlin.math.max
 import kotlin.math.roundToInt
+import kotlin.math.tanh
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 
@@ -36,6 +38,7 @@
     coroutineScope: CoroutineScope,
     canScrollForward: () -> Boolean
 ): Modifier {
+    val screenHeight = LocalRawScreenHeight.current
     val overscrollOffset = remember { Animatable(0f) }
     val stackNestedScrollConnection = remember {
         NotificationStackNestedScrollConnection(
@@ -43,7 +46,13 @@
             canScrollForward = canScrollForward,
             onScroll = { offsetAvailable ->
                 coroutineScope.launch {
-                    overscrollOffset.snapTo(overscrollOffset.value + offsetAvailable * 0.3f)
+                    val maxProgress = screenHeight * 0.2f
+                    val tilt = 3f
+                    var offset =
+                        overscrollOffset.value +
+                            maxProgress * tanh(x = offsetAvailable / (maxProgress * tilt))
+                    offset = max(offset, -1f * maxProgress)
+                    overscrollOffset.snapTo(offset)
                 }
             },
             onStop = { velocityAvailable ->
@@ -79,13 +88,7 @@
             offsetAvailable < 0f && offsetBeforeStart < 0f && !canScrollForward()
         },
         canStartPostFling = { velocityAvailable -> velocityAvailable < 0f && !canScrollForward() },
-        canContinueScroll = { source ->
-            if (source == NestedScrollSource.SideEffect) {
-                stackOffset() > STACK_OVERSCROLL_FLING_MIN_OFFSET
-            } else {
-                true
-            }
-        },
+        canContinueScroll = { stackOffset() > 0f },
         canScrollOnFling = true,
         onStart = { offsetAvailable -> onStart(offsetAvailable) },
         onScroll = { offsetAvailable ->
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
index a2beba8..91ecfc1 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
@@ -667,4 +667,3 @@
 private val DEBUG_BOX_COLOR = Color(0f, 1f, 0f, 0.2f)
 private const val HUN_SNOOZE_POSITIONAL_THRESHOLD_FRACTION = 0.25f
 private const val HUN_SNOOZE_VELOCITY_THRESHOLD = -70f
-internal const val STACK_OVERSCROLL_FLING_MIN_OFFSET = -100f
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index 3cb0d8a..df101c5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -128,7 +128,11 @@
                 }
             },
     ) {
-        SceneTransitionLayout(state = state, modifier = modifier.fillMaxSize()) {
+        SceneTransitionLayout(
+            state = state,
+            modifier = modifier.fillMaxSize(),
+            swipeSourceDetector = viewModel.edgeDetector,
+        ) {
             sceneByKey.forEach { (sceneKey, scene) ->
                 scene(
                     key = sceneKey,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToCommunalTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToCommunalTransition.kt
index 5401936..826a255 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToCommunalTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToCommunalTransition.kt
@@ -19,14 +19,19 @@
 import androidx.compose.animation.core.tween
 import com.android.compose.animation.scene.Edge
 import com.android.compose.animation.scene.TransitionBuilder
+import com.android.systemui.communal.ui.compose.AllElements
+import com.android.systemui.communal.ui.compose.Communal
 import com.android.systemui.scene.shared.model.Scenes
 
 fun TransitionBuilder.lockscreenToCommunalTransition() {
-    spec = tween(durationMillis = 500)
+    spec = tween(durationMillis = 1000)
 
-    // Translate lockscreen to the left.
+    // Translate lockscreen to the start direction.
     translate(Scenes.Lockscreen.rootElementKey, Edge.Start)
 
-    // Translate communal from the right.
-    translate(Scenes.Communal.rootElementKey, Edge.End)
+    // Translate communal hub grid from the end direction.
+    translate(Communal.Elements.Grid, Edge.End)
+
+    // Fade all communal hub elements.
+    timestampRange(startMillis = 167, endMillis = 334) { fade(AllElements) }
 }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index 24fef71..007b84a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -190,14 +190,12 @@
     private fun computeSwipes(startedPosition: Offset?, pointersDown: Int): Swipes {
         val fromSource =
             startedPosition?.let { position ->
-                layoutImpl.swipeSourceDetector
-                    .source(
-                        layoutImpl.lastSize,
-                        position.round(),
-                        layoutImpl.density,
-                        orientation,
-                    )
-                    ?.resolve(layoutImpl.layoutDirection)
+                layoutImpl.swipeSourceDetector.source(
+                    layoutImpl.lastSize,
+                    position.round(),
+                    layoutImpl.density,
+                    orientation,
+                )
             }
 
         val upOrLeft =
@@ -397,14 +395,8 @@
             return 0f
         }
 
-        fun animateTo(targetContent: T) {
-            swipeAnimation.animateOffset(
-                initialVelocity = velocity,
-                targetContent = targetContent,
-            )
-        }
-
         val fromContent = swipeAnimation.fromContent
+        val consumedVelocity: Float
         if (canChangeContent) {
             // If we are halfway between two contents, we check what the target will be based on the
             // velocity and offset of the transition, then we launch the animation.
@@ -429,18 +421,16 @@
                 } else {
                     fromContent
                 }
-
-            animateTo(targetContent = targetContent)
+            consumedVelocity = swipeAnimation.animateOffset(velocity, targetContent = targetContent)
         } else {
             // We are doing an overscroll preview animation between scenes.
             check(fromContent == swipeAnimation.currentContent) {
                 "canChangeContent is false but currentContent != fromContent"
             }
-            animateTo(targetContent = fromContent)
+            consumedVelocity = swipeAnimation.animateOffset(velocity, targetContent = fromContent)
         }
 
-        // The onStop animation consumes any remaining velocity.
-        return velocity
+        return consumedVelocity
     }
 
     /**
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt
index 97c0cef..edd697b 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt
@@ -54,23 +54,23 @@
         position: IntOffset,
         density: Density,
         orientation: Orientation,
-    ): Edge? {
+    ): Edge.Resolved? {
         val axisSize: Int
         val axisPosition: Int
-        val topOrLeft: Edge
-        val bottomOrRight: Edge
+        val topOrLeft: Edge.Resolved
+        val bottomOrRight: Edge.Resolved
         when (orientation) {
             Orientation.Horizontal -> {
                 axisSize = layoutSize.width
                 axisPosition = position.x
-                topOrLeft = Edge.Left
-                bottomOrRight = Edge.Right
+                topOrLeft = Edge.Resolved.Left
+                bottomOrRight = Edge.Resolved.Right
             }
             Orientation.Vertical -> {
                 axisSize = layoutSize.height
                 axisPosition = position.y
-                topOrLeft = Edge.Top
-                bottomOrRight = Edge.Bottom
+                topOrLeft = Edge.Resolved.Top
+                bottomOrRight = Edge.Resolved.Bottom
             }
         }
 
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index 061613f..004bb40 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -379,6 +379,10 @@
         return this to UserActionResult(toScene = scene)
     }
 
+    infix fun to(overlay: OverlayKey): Pair<UserAction, UserActionResult> {
+        return this to UserActionResult(toOverlay = overlay)
+    }
+
     /** Resolve this into a [Resolved] user action given [layoutDirection]. */
     internal abstract fun resolve(layoutDirection: LayoutDirection): Resolved
 
@@ -475,7 +479,7 @@
         position: IntOffset,
         density: Density,
         orientation: Orientation,
-    ): SwipeSource?
+    ): SwipeSource.Resolved?
 }
 
 /** The result of performing a [UserAction]. */
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
index 2a09a77..966bda4 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
@@ -312,11 +312,16 @@
 
     fun isAnimatingOffset(): Boolean = offsetAnimation != null
 
+    /**
+     * Animate the offset to a [targetContent], using the [initialVelocity] and an optional [spec]
+     *
+     * @return the velocity consumed
+     */
     fun animateOffset(
         initialVelocity: Float,
         targetContent: T,
         spec: AnimationSpec<Float>? = null,
-    ) {
+    ): Float {
         check(!isAnimatingOffset()) { "SwipeAnimation.animateOffset() can only be called once" }
 
         val initialProgress = progress
@@ -374,7 +379,7 @@
         if (skipAnimation) {
             // Unblock the job.
             offsetAnimationRunnable.complete(null)
-            return
+            return 0f
         }
 
         val isTargetGreater = targetOffset > animatable.value
@@ -424,6 +429,9 @@
                 /* Ignore. */
             }
         }
+
+        // This animation always consumes the whole available velocity
+        return initialVelocity
     }
 
     /** An exception thrown during the animation to stop it immediately. */
diff --git a/packages/SystemUI/compose/scene/src/com/android/systemui/communal/ui/compose/CommunalSwipeDetector.kt b/packages/SystemUI/compose/scene/src/com/android/systemui/communal/ui/compose/CommunalSwipeDetector.kt
index 3fda9b8..41b015a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/systemui/communal/ui/compose/CommunalSwipeDetector.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/systemui/communal/ui/compose/CommunalSwipeDetector.kt
@@ -33,7 +33,7 @@
  * SwipeSourceDetector} to enable fullscreen swipe handling to transition to and from the glanceable
  * hub.
  */
-class CommunalSwipeDetector(private var lastDirection: SwipeSource? = null) :
+class CommunalSwipeDetector(private var lastDirection: SwipeSource.Resolved? = null) :
     SwipeSourceDetector, SwipeDetector {
     companion object {
         private const val TRAVEL_RATIO_THRESHOLD = .5f
@@ -44,15 +44,15 @@
         position: IntOffset,
         density: Density,
         orientation: Orientation
-    ): SwipeSource? {
+    ): SwipeSource.Resolved? {
         return lastDirection
     }
 
     override fun detectSwipe(change: PointerInputChange): Boolean {
         if (change.positionChange().x > 0) {
-            lastDirection = Edge.Left
+            lastDirection = Edge.Resolved.Left
         } else {
-            lastDirection = Edge.Right
+            lastDirection = Edge.Resolved.Right
         }
 
         // Determine whether the ratio of the distance traveled horizontally to the distance
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index 79f82c9..5b59356 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -1111,7 +1111,7 @@
         assertTransition(fromScene = SceneA, toScene = SceneB, progress = 1f)
 
         // Release the finger.
-        dragController.onDragStopped(velocity = -velocityThreshold)
+        dragController.onDragStopped(velocity = -velocityThreshold, expectedConsumed = false)
 
         // Exhaust all coroutines *without advancing the clock*. Given that we are at progress >=
         // 100% and that the overscroll on scene B is doing nothing, we are already idle.
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt
index cceaf57..dea9283 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt
@@ -34,7 +34,7 @@
 
     @Test
     fun horizontalEdges() {
-        fun horizontalEdge(position: Int): Edge? =
+        fun horizontalEdge(position: Int): Edge.Resolved? =
             detector.source(
                 layoutSize,
                 position = IntOffset(position, 0),
@@ -42,17 +42,17 @@
                 Orientation.Horizontal,
             )
 
-        assertThat(horizontalEdge(0)).isEqualTo(Edge.Left)
-        assertThat(horizontalEdge(30)).isEqualTo(Edge.Left)
+        assertThat(horizontalEdge(0)).isEqualTo(Edge.Resolved.Left)
+        assertThat(horizontalEdge(30)).isEqualTo(Edge.Resolved.Left)
         assertThat(horizontalEdge(31)).isEqualTo(null)
         assertThat(horizontalEdge(69)).isEqualTo(null)
-        assertThat(horizontalEdge(70)).isEqualTo(Edge.Right)
-        assertThat(horizontalEdge(100)).isEqualTo(Edge.Right)
+        assertThat(horizontalEdge(70)).isEqualTo(Edge.Resolved.Right)
+        assertThat(horizontalEdge(100)).isEqualTo(Edge.Resolved.Right)
     }
 
     @Test
     fun verticalEdges() {
-        fun verticalEdge(position: Int): Edge? =
+        fun verticalEdge(position: Int): Edge.Resolved? =
             detector.source(
                 layoutSize,
                 position = IntOffset(0, position),
@@ -60,11 +60,11 @@
                 Orientation.Vertical,
             )
 
-        assertThat(verticalEdge(0)).isEqualTo(Edge.Top)
-        assertThat(verticalEdge(30)).isEqualTo(Edge.Top)
+        assertThat(verticalEdge(0)).isEqualTo(Edge.Resolved.Top)
+        assertThat(verticalEdge(30)).isEqualTo(Edge.Resolved.Top)
         assertThat(verticalEdge(31)).isEqualTo(null)
         assertThat(verticalEdge(69)).isEqualTo(null)
-        assertThat(verticalEdge(70)).isEqualTo(Edge.Bottom)
-        assertThat(verticalEdge(100)).isEqualTo(Edge.Bottom)
+        assertThat(verticalEdge(70)).isEqualTo(Edge.Resolved.Bottom)
+        assertThat(verticalEdge(100)).isEqualTo(Edge.Resolved.Bottom)
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
index e2bdc49..bb15208 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
@@ -30,10 +30,12 @@
 import com.android.systemui.classifier.FalsingCollectorFake
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
+import com.android.systemui.haptics.msdl.msdlPlayer
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.policy.DevicePostureController
 import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_HALF_OPENED
 import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED
+import com.android.systemui.testKosmos
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.whenever
@@ -89,6 +91,9 @@
 
     @Captor lateinit var postureCallbackCaptor: ArgumentCaptor<DevicePostureController.Callback>
 
+    private val kosmos = testKosmos()
+    private val msdlPlayer = kosmos.msdlPlayer
+
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
@@ -112,7 +117,8 @@
                 mKeyguardMessageAreaControllerFactory,
                 mPostureController,
                 fakeFeatureFlags,
-                mSelectedUserInteractor
+                mSelectedUserInteractor,
+                msdlPlayer,
             )
         mKeyguardPatternView.onAttachedToWindow()
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/MirrorWindowControlTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/MirrorWindowControlTest.java
index 8f9b7c8..12c866f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/MirrorWindowControlTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/MirrorWindowControlTest.java
@@ -30,11 +30,11 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.WindowManager;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
 import com.android.systemui.SysuiTestCase;
 
 import org.junit.Before;
@@ -48,7 +48,7 @@
 @RunWith(AndroidJUnit4.class)
 public class MirrorWindowControlTest extends SysuiTestCase {
 
-    @Mock WindowManager mWindowManager;
+    @Mock ViewCaptureAwareWindowManager mWindowManager;
     View mView;
     int mViewWidth;
     int mViewHeight;
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/CaptioningRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/CaptioningRepositoryTest.kt
index dd85d9b..fc57757 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/CaptioningRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/CaptioningRepositoryTest.kt
@@ -20,11 +20,15 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.android.systemui.user.data.repository.userRepository
+import com.android.systemui.user.utils.FakeUserScopedService
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -39,10 +43,11 @@
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
-@Suppress("UnspecifiedRegisterReceiverFlag")
 @RunWith(AndroidJUnit4::class)
 class CaptioningRepositoryTest : SysuiTestCase() {
 
+    private val kosmos = testKosmos()
+
     @Captor
     private lateinit var listenerCaptor: ArgumentCaptor<CaptioningManager.CaptioningChangeListener>
 
@@ -50,34 +55,33 @@
 
     private lateinit var underTest: CaptioningRepository
 
-    private val testScope = TestScope()
-
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
 
         underTest =
-            CaptioningRepositoryImpl(
-                captioningManager,
-                testScope.testScheduler,
-                testScope.backgroundScope
-            )
+            with(kosmos) {
+                CaptioningRepositoryImpl(
+                    FakeUserScopedService(captioningManager),
+                    userRepository,
+                    testScope.testScheduler,
+                    applicationCoroutineScope,
+                )
+            }
     }
 
     @Test
     fun isSystemAudioCaptioningEnabled_change_repositoryEmits() {
-        testScope.runTest {
-            `when`(captioningManager.isEnabled).thenReturn(false)
-            val isSystemAudioCaptioningEnabled = mutableListOf<Boolean>()
-            underTest.isSystemAudioCaptioningEnabled
-                .onEach { isSystemAudioCaptioningEnabled.add(it) }
-                .launchIn(backgroundScope)
+        kosmos.testScope.runTest {
+            `when`(captioningManager.isSystemAudioCaptioningEnabled).thenReturn(false)
+            val models by collectValues(underTest.captioningModel.filterNotNull())
             runCurrent()
 
+            `when`(captioningManager.isSystemAudioCaptioningEnabled).thenReturn(true)
             triggerOnSystemAudioCaptioningChange()
             runCurrent()
 
-            assertThat(isSystemAudioCaptioningEnabled)
+            assertThat(models.map { it.isSystemAudioCaptioningEnabled })
                 .containsExactlyElementsIn(listOf(false, true))
                 .inOrder()
         }
@@ -85,18 +89,16 @@
 
     @Test
     fun isSystemAudioCaptioningUiEnabled_change_repositoryEmits() {
-        testScope.runTest {
-            `when`(captioningManager.isSystemAudioCaptioningUiEnabled).thenReturn(false)
-            val isSystemAudioCaptioningUiEnabled = mutableListOf<Boolean>()
-            underTest.isSystemAudioCaptioningUiEnabled
-                .onEach { isSystemAudioCaptioningUiEnabled.add(it) }
-                .launchIn(backgroundScope)
+        kosmos.testScope.runTest {
+            `when`(captioningManager.isEnabled).thenReturn(false)
+            val models by collectValues(underTest.captioningModel.filterNotNull())
             runCurrent()
 
+            `when`(captioningManager.isSystemAudioCaptioningUiEnabled).thenReturn(true)
             triggerSystemAudioCaptioningUiChange()
             runCurrent()
 
-            assertThat(isSystemAudioCaptioningUiEnabled)
+            assertThat(models.map { it.isSystemAudioCaptioningUiEnabled })
                 .containsExactlyElementsIn(listOf(false, true))
                 .inOrder()
         }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java
index 09aa2868..ca23228 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java
@@ -17,11 +17,11 @@
 package com.android.systemui.accessibility.hearingaid;
 
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.bluetooth.BluetoothDevice;
 import android.testing.TestableLooper;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -51,6 +51,8 @@
     @Rule
     public MockitoRule mockito = MockitoJUnit.rule();
 
+    private static final int TEST_LAUNCH_SOURCE_ID = 1;
+
     private final FakeExecutor mMainExecutor = new FakeExecutor(new FakeSystemClock());
     private final FakeExecutor mBackgroundExecutor = new FakeExecutor(new FakeSystemClock());
     @Mock
@@ -70,7 +72,7 @@
 
     @Before
     public void setUp() {
-        when(mDialogFactory.create(anyBoolean())).thenReturn(mDialogDelegate);
+        when(mDialogFactory.create(anyBoolean(), anyInt())).thenReturn(mDialogDelegate);
         when(mDialogDelegate.createDialog()).thenReturn(mDialog);
 
         mManager = new HearingDevicesDialogManager(
@@ -86,21 +88,22 @@
     public void showDialog_existHearingDevice_showPairNewDeviceFalse() {
         when(mDevicesChecker.isAnyPairedHearingDevice()).thenReturn(true);
 
-        mManager.showDialog(mExpandable);
+        mManager.showDialog(mExpandable, TEST_LAUNCH_SOURCE_ID);
         mBackgroundExecutor.runAllReady();
         mMainExecutor.runAllReady();
 
-        verify(mDialogFactory).create(eq(/* showPairNewDevice= */ false));
+        verify(mDialogFactory).create(eq(/* showPairNewDevice= */ false),
+                eq(TEST_LAUNCH_SOURCE_ID));
     }
 
     @Test
     public void showDialog_noHearingDevice_showPairNewDeviceTrue() {
         when(mDevicesChecker.isAnyPairedHearingDevice()).thenReturn(false);
 
-        mManager.showDialog(mExpandable);
+        mManager.showDialog(mExpandable, TEST_LAUNCH_SOURCE_ID);
         mBackgroundExecutor.runAllReady();
         mMainExecutor.runAllReady();
 
-        verify(mDialogFactory).create(eq(/* showPairNewDevice= */ true));
+        verify(mDialogFactory).create(eq(/* showPairNewDevice= */ true), eq(TEST_LAUNCH_SOURCE_ID));
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
index b7d99d2..65825b2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -97,6 +97,8 @@
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
+import com.google.android.msdl.domain.MSDLPlayer;
+
 import dagger.Lazy;
 
 import org.junit.Before;
@@ -185,6 +187,8 @@
     private Resources mResources;
     @Mock
     private VibratorHelper mVibratorHelper;
+    @Mock
+    private MSDLPlayer mMSDLPlayer;
 
     private TestableContext mContextSpy;
     private Execution mExecution;
@@ -1066,7 +1070,7 @@
                     () -> mLogContextInteractor, () -> mPromptSelectionInteractor,
                     () -> mCredentialViewModel, () -> mPromptViewModel, mInteractionJankMonitor,
                     mHandler, mBackgroundExecutor, mUdfpsUtils, mVibratorHelper,
-                    mLazyViewCapture);
+                    mLazyViewCapture, mMSDLPlayer);
         }
 
         @Override
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
index 65236f0..e3b5f34 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
@@ -31,6 +31,8 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.telephony.data.repository.fakeTelephonyRepository
@@ -91,6 +93,8 @@
         kosmos.fakeTelephonyRepository.setHasTelephonyRadio(true)
 
         kosmos.telecomManager = telecomManager
+
+        kosmos.sceneInteractor.changeScene(Scenes.Bouncer, "")
     }
 
     @Test
@@ -130,6 +134,7 @@
             assertThat(metricsLogger.logs.element().category)
                 .isEqualTo(MetricsProto.MetricsEvent.ACTION_EMERGENCY_CALL)
             verify(activityTaskManager).stopSystemLockTaskMode()
+            assertThat(kosmos.sceneInteractor.currentScene.value).isEqualTo(Scenes.Lockscreen)
             verify(telecomManager).showInCallScreen(eq(false))
         }
 
@@ -156,6 +161,7 @@
             assertThat(metricsLogger.logs.element().category)
                 .isEqualTo(MetricsProto.MetricsEvent.ACTION_EMERGENCY_CALL)
             verify(activityTaskManager).stopSystemLockTaskMode()
+            assertThat(kosmos.sceneInteractor.currentScene.value).isEqualTo(Scenes.Lockscreen)
 
             // TODO(b/25189994): Test the activity has been started once we switch to the
             //  ActivityStarter interface here.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
index 53d82d7..956c129 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
@@ -95,6 +95,7 @@
         when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
         when(mKeyguardStateController.isShowing()).thenReturn(true);
         when(mFalsingDataProvider.isUnfolded()).thenReturn(false);
+        when(mFalsingDataProvider.isTouchScreenSource()).thenReturn(true);
         mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
                 mMetricsLogger, mClassifiers, mSingleTapClassifier, mLongTapClassifier,
                 mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
@@ -193,6 +194,13 @@
     }
 
     @Test
+    public void testSkipNonTouchscreenDevices() {
+        assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue();
+        when(mFalsingDataProvider.isTouchScreenSource()).thenReturn(false);
+        assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isFalse();
+    }
+
+    @Test
     public void testTrackpadGesture() {
         assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue();
         when(mFalsingDataProvider.isFromTrackpad()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
similarity index 81%
rename from packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
index 49c6239..df4b048 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -25,13 +26,20 @@
 import static org.mockito.Mockito.when;
 
 import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
+import android.hardware.input.IInputManager;
+import android.hardware.input.InputManagerGlobal;
+import android.os.RemoteException;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
 import android.util.DisplayMetrics;
+import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
+import com.android.systemui.Flags;
 import com.android.systemui.classifier.FalsingDataProvider.GestureFinalizedListener;
 import com.android.systemui.dock.DockManagerFake;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -56,11 +64,15 @@
     private FoldStateListener mFoldStateListener;
     private final DockManagerFake mDockManager = new DockManagerFake();
     private DisplayMetrics mDisplayMetrics;
+    private IInputManager mIInputManager;
+    private InputManagerGlobal.TestSession inputManagerGlobalTestSession;
 
     @Before
     public void setup() {
         super.setup();
         MockitoAnnotations.initMocks(this);
+        mIInputManager = mock(IInputManager.Stub.class);
+        inputManagerGlobalTestSession = InputManagerGlobal.createTestSession(mIInputManager);
         mDisplayMetrics = new DisplayMetrics();
         mDisplayMetrics.xdpi = 100;
         mDisplayMetrics.ydpi = 100;
@@ -73,6 +85,7 @@
     public void tearDown() {
         super.tearDown();
         mDataProvider.onSessionEnd();
+        inputManagerGlobalTestSession.close();
     }
 
     @Test
@@ -378,6 +391,79 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING)
+    public void test_isTouchscreenSource_flagOff_alwaysTrue() {
+        assertThat(mDataProvider.isTouchScreenSource()).isTrue();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING)
+    public void test_isTouchscreenSource_recentEventsEmpty_true() {
+        //send no events into the data provider
+        assertThat(mDataProvider.isTouchScreenSource()).isTrue();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING)
+    public void test_isTouchscreenSource_latestDeviceTouchscreen_true() throws RemoteException {
+        int deviceId = 999;
+
+        InputDevice device = new InputDevice.Builder()
+                .setSources(InputDevice.SOURCE_CLASS_TRACKBALL | InputDevice.SOURCE_TOUCHSCREEN)
+                .setId(deviceId)
+                .build();
+        when(mIInputManager.getInputDeviceIds()).thenReturn(new int[]{deviceId});
+        when(mIInputManager.getInputDevice(anyInt())).thenReturn(device);
+
+        MotionEvent event = MotionEvent.obtain(1, 0, MotionEvent.ACTION_UP, 1,
+                MotionEvent.PointerProperties.createArray(1),
+                MotionEvent.PointerCoords.createArray(1), 0, 0, 1.0f, 1.0f, deviceId, 0,
+                InputDevice.SOURCE_CLASS_NONE, 0, 0, 0);
+
+        mDataProvider.onMotionEvent(event);
+        boolean result = mDataProvider.isTouchScreenSource();
+        assertThat(result).isTrue();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING)
+    public void test_isTouchscreenSource_latestDeviceNonTouchscreen_false() throws RemoteException {
+        int deviceId = 9999;
+
+        InputDevice device = new InputDevice.Builder()
+                .setSources(InputDevice.SOURCE_CLASS_TRACKBALL)
+                .setId(deviceId)
+                .build();
+        when(mIInputManager.getInputDeviceIds()).thenReturn(new int[]{deviceId});
+        when(mIInputManager.getInputDevice(anyInt())).thenReturn(device);
+
+        MotionEvent event = MotionEvent.obtain(1, 0, MotionEvent.ACTION_UP, 1,
+                MotionEvent.PointerProperties.createArray(1),
+                MotionEvent.PointerCoords.createArray(1), 0, 0, 1.0f, 1.0f, deviceId, 0,
+                InputDevice.SOURCE_CLASS_NONE, 0, 0, 0);
+
+        mDataProvider.onMotionEvent(event);
+        boolean result = mDataProvider.isTouchScreenSource();
+        assertThat(result).isFalse();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING)
+    public void test_isTouchscreenSource_latestDeviceNull_true() {
+        // Do not mock InputManager for this test
+        inputManagerGlobalTestSession.close();
+
+        int nonExistentDeviceId = 9997;
+        MotionEvent event = MotionEvent.obtain(1, 0, MotionEvent.ACTION_UP, 1,
+                MotionEvent.PointerProperties.createArray(1),
+                MotionEvent.PointerCoords.createArray(1), 0, 0, 1.0f, 1.0f, nonExistentDeviceId, 0,
+                InputDevice.SOURCE_CLASS_NONE, 0, 0, 0);
+
+        mDataProvider.onMotionEvent(event);
+        assertThat(mDataProvider.isTouchScreenSource()).isTrue();
+    }
+
+    @Test
     public void test_UnfoldedState_Folded() {
         FalsingDataProvider falsingDataProvider = createWithFoldCapability(true);
         when(mFoldStateListener.getFolded()).thenReturn(true);
@@ -413,7 +499,7 @@
     }
 
     private FalsingDataProvider createWithFoldCapability(boolean foldable) {
-        return new FalsingDataProvider(
-                mDisplayMetrics, mBatteryController, mFoldStateListener, mDockManager, foldable);
+        return new FalsingDataProvider(mDisplayMetrics, mBatteryController, mFoldStateListener,
+                mDockManager, foldable);
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt
index bb400f2..f06cd6a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt
@@ -67,7 +67,8 @@
                 isAttachedToWindow = { isAttachedToWindow },
                 onLongPressDetected = onLongPressDetected,
                 onSingleTapDetected = onSingleTapDetected,
-                longPressDuration = { ViewConfiguration.getLongPressTimeout().toLong() }
+                longPressDuration = { ViewConfiguration.getLongPressTimeout().toLong() },
+                allowedTouchSlop = ViewConfiguration.getTouchSlop(),
             )
         underTest.isLongPressHandlingEnabled = true
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalDreamStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalDreamStartableTest.kt
index 3b0057d..e531e65 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalDreamStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalDreamStartableTest.kt
@@ -22,6 +22,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.domain.interactor.communalSceneInteractor
 import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
 import com.android.systemui.flags.fakeFeatureFlagsClassic
@@ -73,6 +74,7 @@
                     keyguardInteractor = kosmos.keyguardInteractor,
                     keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor,
                     dreamManager = dreamManager,
+                    communalSceneInteractor = kosmos.communalSceneInteractor,
                     bgScope = kosmos.applicationCoroutineScope,
                 )
                 .apply { start() }
@@ -158,6 +160,36 @@
             }
         }
 
+    @Test
+    fun shouldNotStartDreamWhenLaunchingWidget() =
+        testScope.runTest {
+            keyguardRepository.setKeyguardShowing(true)
+            keyguardRepository.setDreaming(false)
+            powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)
+            kosmos.communalSceneInteractor.setIsLaunchingWidget(true)
+            whenever(dreamManager.canStartDreaming(/* isScreenOn= */ true)).thenReturn(true)
+            runCurrent()
+
+            transition(from = KeyguardState.DREAMING, to = KeyguardState.GLANCEABLE_HUB)
+
+            verify(dreamManager, never()).startDream()
+        }
+
+    @Test
+    fun shouldNotStartDreamWhenOccluded() =
+        testScope.runTest {
+            keyguardRepository.setKeyguardShowing(true)
+            keyguardRepository.setDreaming(false)
+            powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)
+            keyguardRepository.setKeyguardOccluded(true)
+            whenever(dreamManager.canStartDreaming(/* isScreenOn= */ true)).thenReturn(true)
+            runCurrent()
+
+            transition(from = KeyguardState.DREAMING, to = KeyguardState.GLANCEABLE_HUB)
+
+            verify(dreamManager, never()).startDream()
+        }
+
     private suspend fun TestScope.transition(from: KeyguardState, to: KeyguardState) {
         kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
             from = from,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
index 34d926a..25c5336 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
@@ -27,6 +27,7 @@
 import com.android.systemui.contextualeducation.GestureType.ALL_APPS
 import com.android.systemui.contextualeducation.GestureType.BACK
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
 import com.android.systemui.education.data.model.GestureEduModel
 import com.android.systemui.education.data.repository.contextualEducationRepository
 import com.android.systemui.education.data.repository.fakeEduClock
@@ -62,6 +63,8 @@
 
     private val underTest: KeyboardTouchpadEduInteractor = kosmos.keyboardTouchpadEduInteractor
     private val eduClock = kosmos.fakeEduClock
+    private val minDurationForNextEdu =
+        KeyboardTouchpadEduInteractor.minIntervalBetweenEdu + 1.seconds
 
     @Before
     fun setup() {
@@ -93,7 +96,10 @@
             triggerMaxEducationSignals(BACK)
             // runCurrent() to trigger 1st education
             runCurrent()
+
+            eduClock.offset(minDurationForNextEdu)
             triggerMaxEducationSignals(BACK)
+
             assertThat(model?.educationUiType).isEqualTo(EducationUiType.Notification)
         }
 
@@ -115,6 +121,39 @@
         }
 
     @Test
+    fun no2ndEducationBeforeMinEduIntervalReached() =
+        testScope.runTest {
+            val models by collectValues(underTest.educationTriggered)
+            triggerMaxEducationSignals(BACK)
+            runCurrent()
+
+            // Offset a duration that is less than the required education interval
+            eduClock.offset(1.seconds)
+            triggerMaxEducationSignals(BACK)
+            runCurrent()
+
+            assertThat(models.filterNotNull().size).isEqualTo(1)
+        }
+
+    @Test
+    fun noNewEducationInfoAfterMaxEducationCountReached() =
+        testScope.runTest {
+            val models by collectValues(underTest.educationTriggered)
+            // Trigger 2 educations
+            triggerMaxEducationSignals(BACK)
+            runCurrent()
+            eduClock.offset(minDurationForNextEdu)
+            triggerMaxEducationSignals(BACK)
+            runCurrent()
+
+            // Try triggering 3rd education
+            eduClock.offset(minDurationForNextEdu)
+            triggerMaxEducationSignals(BACK)
+
+            assertThat(models.filterNotNull().size).isEqualTo(2)
+        }
+
+    @Test
     fun startNewUsageSessionWhen2ndSignalReceivedAfterSessionDeadline() =
         testScope.runTest {
             val model by
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt
index e075b7e..c4ac585 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.contextualeducation.GestureType
 import com.android.systemui.contextualeducation.GestureType.BACK
+import com.android.systemui.education.data.repository.fakeEduClock
 import com.android.systemui.education.domain.interactor.KeyboardTouchpadEduInteractor
 import com.android.systemui.education.domain.interactor.contextualEducationInteractor
 import com.android.systemui.education.domain.interactor.keyboardTouchpadEduInteractor
@@ -35,6 +36,7 @@
 import com.android.systemui.res.R
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
+import kotlin.time.Duration.Companion.seconds
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
@@ -56,6 +58,9 @@
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private val interactor = kosmos.contextualEducationInteractor
+    private val eduClock = kosmos.fakeEduClock
+    private val minDurationForNextEdu =
+        KeyboardTouchpadEduInteractor.minIntervalBetweenEdu + 1.seconds
     private lateinit var underTest: ContextualEduUiCoordinator
     @Mock private lateinit var toast: Toast
     @Mock private lateinit var notificationManager: NotificationManager
@@ -94,6 +99,7 @@
     fun showNotificationOn2ndEdu() =
         testScope.runTest {
             triggerEducation(BACK)
+            eduClock.offset(minDurationForNextEdu)
             triggerEducation(BACK)
             verify(notificationManager).notifyAsUser(any(), anyInt(), any(), any())
         }
@@ -110,7 +116,10 @@
         testScope.runTest {
             val notificationCaptor = ArgumentCaptor.forClass(Notification::class.java)
             triggerEducation(BACK)
+
+            eduClock.offset(minDurationForNextEdu)
             triggerEducation(BACK)
+
             verify(notificationManager)
                 .notifyAsUser(any(), anyInt(), notificationCaptor.capture(), any())
             verifyNotificationContent(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorTest.kt
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt
index c1dcf37..69ccc58 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt
@@ -41,7 +41,6 @@
 import com.android.systemui.media.controls.shared.model.MediaData
 import com.android.systemui.media.controls.util.fakeMediaControllerFactory
 import com.android.systemui.media.controls.util.mediaFlags
-import com.android.systemui.plugins.activityStarter
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.SbnBuilder
 import com.android.systemui.testKosmos
@@ -86,7 +85,6 @@
             context,
             testDispatcher,
             testScope,
-            kosmos.activityStarter,
             mediaControllerFactory,
             mediaFlags,
             kosmos.imageLoader,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt
index 6f11b2a..aaad0fc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt
@@ -185,7 +185,6 @@
 
             val networkModel =
                 WifiNetworkModel.Active(
-                    networkId = 1,
                     level = 4,
                     ssid = "test ssid",
                 )
@@ -221,7 +220,6 @@
 
             val networkModel =
                 WifiNetworkModel.Active(
-                    networkId = 1,
                     level = 4,
                     ssid = "test ssid",
                     hotspotDeviceType = WifiNetworkModel.HotspotDeviceType.NONE,
@@ -546,7 +544,6 @@
     private fun setWifiNetworkWithHotspot(hotspot: WifiNetworkModel.HotspotDeviceType) {
         val networkModel =
             WifiNetworkModel.Active(
-                networkId = 1,
                 level = 4,
                 ssid = "test ssid",
                 hotspotDeviceType = hotspot,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt
index 4e58069..5bd3645 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.qs.tiles.base.interactor.QSTileInput
 import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
 import com.android.systemui.recordissue.RecordIssueDialogDelegate
+import com.android.systemui.screenrecord.RecordingController
 import com.android.systemui.settings.UserContextProvider
 import com.android.systemui.settings.userTracker
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil
@@ -40,12 +41,16 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.Mock
 import org.mockito.Mockito.mock
+import org.mockito.MockitoAnnotations
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class IssueRecordingUserActionInteractorTest : SysuiTestCase() {
 
+    @Mock private lateinit var recordingController: RecordingController
+
     val user = UserHandle(1)
     val kosmos = Kosmos().also { it.testCase = this }
 
@@ -56,6 +61,7 @@
 
     @Before
     fun setup() {
+        MockitoAnnotations.initMocks(this)
         hasCreatedDialogDelegate = false
         with(kosmos) {
             val factory =
@@ -84,7 +90,8 @@
                     dialogTransitionAnimator,
                     panelInteractor,
                     userTracker,
-                    factory
+                    factory,
+                    recordingController,
                 )
         }
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt
index 91d8e2a..de3dc57 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt
@@ -25,7 +25,9 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.internal.R
+import com.android.settingslib.notification.modes.TestModeBuilder
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.SysuiTestableContext
 import com.android.systemui.common.shared.model.asIcon
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
@@ -62,7 +64,12 @@
         context.orCreateTestableResources.apply {
             addOverride(MODES_DRAWABLE_ID, MODES_DRAWABLE)
             addOverride(R.drawable.ic_zen_mode_type_bedtime, BEDTIME_DRAWABLE)
-            addOverride(R.drawable.ic_zen_mode_type_driving, DRIVING_DRAWABLE)
+        }
+
+        val customPackageContext = SysuiTestableContext(context)
+        context.prepareCreatePackageContext(CUSTOM_PACKAGE, customPackageContext)
+        customPackageContext.orCreateTestableResources.apply {
+            addOverride(CUSTOM_DRAWABLE_ID, CUSTOM_DRAWABLE)
         }
     }
 
@@ -146,35 +153,41 @@
             assertThat(tileData?.icon).isEqualTo(MODES_ICON)
             assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
 
-            // Add an active mode: icon should be the mode icon. No iconResId, because we don't
-            // really know that it's a system icon.
+            // Add an active mode with a default icon: icon should be the mode icon, and the
+            // iconResId is also populated, because we know it's a system icon.
             zenModeRepository.addMode(
-                id = "Bedtime",
+                id = "Bedtime with default icon",
                 type = AutomaticZenRule.TYPE_BEDTIME,
                 active = true
             )
             runCurrent()
             assertThat(tileData?.icon).isEqualTo(BEDTIME_ICON)
-            assertThat(tileData?.iconResId).isNull()
+            assertThat(tileData?.iconResId).isEqualTo(R.drawable.ic_zen_mode_type_bedtime)
 
-            // Add another, less-prioritized mode: icon should remain the first mode icon
+            // Add another, less-prioritized mode that has a *custom* icon: for now, icon should
+            // remain the first mode icon
             zenModeRepository.addMode(
-                id = "Driving",
-                type = AutomaticZenRule.TYPE_DRIVING,
-                active = true
+                TestModeBuilder()
+                    .setId("Driving with custom icon")
+                    .setType(AutomaticZenRule.TYPE_DRIVING)
+                    .setPackage(CUSTOM_PACKAGE)
+                    .setIconResId(CUSTOM_DRAWABLE_ID)
+                    .setActive(true)
+                    .build()
             )
             runCurrent()
             assertThat(tileData?.icon).isEqualTo(BEDTIME_ICON)
-            assertThat(tileData?.iconResId).isNull()
+            assertThat(tileData?.iconResId).isEqualTo(R.drawable.ic_zen_mode_type_bedtime)
 
             // Deactivate more important mode: icon should be the less important, still active mode
-            zenModeRepository.deactivateMode("Bedtime")
+            // And because it's a package-provided icon, iconResId is not populated.
+            zenModeRepository.deactivateMode("Bedtime with default icon")
             runCurrent()
-            assertThat(tileData?.icon).isEqualTo(DRIVING_ICON)
+            assertThat(tileData?.icon).isEqualTo(CUSTOM_ICON)
             assertThat(tileData?.iconResId).isNull()
 
             // Deactivate remaining mode: back to the default modes icon
-            zenModeRepository.deactivateMode("Driving")
+            zenModeRepository.deactivateMode("Driving with custom icon")
             runCurrent()
             assertThat(tileData?.icon).isEqualTo(MODES_ICON)
             assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
@@ -241,15 +254,17 @@
 
     private companion object {
         val TEST_USER = UserHandle.of(1)!!
+        const val CUSTOM_PACKAGE = "com.some.mode.owner.package"
 
         val MODES_DRAWABLE_ID = R.drawable.ic_zen_priority_modes
+        const val CUSTOM_DRAWABLE_ID = 12345
 
         val MODES_DRAWABLE = TestStubDrawable("modes_icon")
         val BEDTIME_DRAWABLE = TestStubDrawable("bedtime")
-        val DRIVING_DRAWABLE = TestStubDrawable("driving")
+        val CUSTOM_DRAWABLE = TestStubDrawable("custom")
 
         val MODES_ICON = MODES_DRAWABLE.asIcon()
         val BEDTIME_ICON = BEDTIME_DRAWABLE.asIcon()
-        val DRIVING_ICON = DRIVING_DRAWABLE.asIcon()
+        val CUSTOM_ICON = CUSTOM_DRAWABLE.asIcon()
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt
index f7bdcb8..c3d45db 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt
@@ -18,7 +18,6 @@
 
 import android.app.Flags
 import android.graphics.drawable.TestStubDrawable
-import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -109,26 +108,7 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_MODES_UI_ICONS)
-    fun state_withEnabledFlag_noIconResId() {
-        val icon = TestStubDrawable("res123").asIcon()
-        val model =
-            ModesTileModel(
-                isActivated = false,
-                activeModes = emptyList(),
-                icon = icon,
-                iconResId = 123 // Should not be populated, but is ignored even if present
-            )
-
-        val state = underTest.map(config, model)
-
-        assertThat(state.icon()).isEqualTo(icon)
-        assertThat(state.iconRes).isNull()
-    }
-
-    @Test
-    @DisableFlags(Flags.FLAG_MODES_UI_ICONS)
-    fun state_withDisabledFlag_includesIconResId() {
+    fun state_modelHasIconResId_includesIconResId() {
         val icon = TestStubDrawable("res123").asIcon()
         val model =
             ModesTileModel(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index ec79cc6..d180460 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -21,6 +21,8 @@
 import android.app.StatusBarManager
 import android.hardware.face.FaceManager
 import android.os.PowerManager
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
 import android.view.Display
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -28,6 +30,8 @@
 import com.android.compose.animation.scene.SceneKey
 import com.android.internal.logging.uiEventLoggerFake
 import com.android.internal.policy.IKeyguardDismissCallback
+import com.android.keyguard.AuthInteractionProperties
+import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
@@ -48,6 +52,7 @@
 import com.android.systemui.deviceentry.shared.model.FailedFaceAuthenticationStatus
 import com.android.systemui.deviceentry.shared.model.SuccessFaceAuthenticationStatus
 import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.haptics.msdl.fakeMSDLPlayer
 import com.android.systemui.haptics.vibratorHelper
 import com.android.systemui.keyevent.data.repository.fakeKeyEventRepository
 import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
@@ -95,6 +100,7 @@
 import com.android.systemui.statusbar.sysuiStatusBarStateController
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.mock
+import com.google.android.msdl.data.model.MSDLToken
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -137,6 +143,8 @@
     private val powerInteractor = kosmos.powerInteractor
     private val fakeTrustRepository = kosmos.fakeTrustRepository
     private val uiEventLoggerFake = kosmos.uiEventLoggerFake
+    private val msdlPlayer = kosmos.fakeMSDLPlayer
+    private val authInteractionProperties = AuthInteractionProperties()
 
     private lateinit var underTest: SceneContainerStartable
 
@@ -654,6 +662,7 @@
         }
 
     @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun playSuccessHaptics_onSuccessfulLockscreenAuth_udfps() =
         testScope.runTest {
             val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
@@ -680,6 +689,31 @@
         }
 
     @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun playSuccessMSDLHaptics_onSuccessfulLockscreenAuth_udfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playSuccessHaptic by
+                collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+            setupBiometricAuth(hasUdfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            unlockWithFingerprintAuth()
+
+            assertThat(playSuccessHaptic).isNotNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.UNLOCK)
+            assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties)
+
+            updateFingerprintAuthStatus(isSuccess = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+        }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun playSuccessHaptics_onSuccessfulLockscreenAuth_sfps() =
         testScope.runTest {
             val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
@@ -707,6 +741,32 @@
         }
 
     @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun playSuccessMSDLHaptics_onSuccessfulLockscreenAuth_sfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playSuccessHaptic by
+                collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+            setupBiometricAuth(hasSfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            allowHapticsOnSfps()
+            unlockWithFingerprintAuth()
+
+            assertThat(playSuccessHaptic).isNotNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.UNLOCK)
+            assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties)
+
+            updateFingerprintAuthStatus(isSuccess = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+        }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun playErrorHaptics_onFailedLockscreenAuth_udfps() =
         testScope.runTest {
             val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
@@ -727,6 +787,27 @@
         }
 
     @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun playMSDLErrorHaptics_onFailedLockscreenAuth_udfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+            setupBiometricAuth(hasUdfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            updateFingerprintAuthStatus(isSuccess = false)
+
+            assertThat(playErrorHaptic).isNotNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.FAILURE)
+            assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties)
+        }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun playErrorHaptics_onFailedLockscreenAuth_sfps() =
         testScope.runTest {
             val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
@@ -747,6 +828,27 @@
         }
 
     @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun playMSDLErrorHaptics_onFailedLockscreenAuth_sfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+            setupBiometricAuth(hasSfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            updateFingerprintAuthStatus(isSuccess = false)
+
+            assertThat(playErrorHaptic).isNotNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.FAILURE)
+            assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties)
+        }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun skipsSuccessHaptics_whenPowerButtonDown_sfps() =
         testScope.runTest {
             val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
@@ -774,6 +876,32 @@
         }
 
     @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun skipsMSDLSuccessHaptics_whenPowerButtonDown_sfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playSuccessHaptic by
+                collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+            setupBiometricAuth(hasSfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            allowHapticsOnSfps(isPowerButtonDown = true)
+            unlockWithFingerprintAuth()
+
+            assertThat(playSuccessHaptic).isNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(msdlPlayer.latestTokenPlayed).isNull()
+            assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
+
+            updateFingerprintAuthStatus(isSuccess = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+        }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun skipsSuccessHaptics_whenPowerButtonRecentlyPressed_sfps() =
         testScope.runTest {
             val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
@@ -801,6 +929,32 @@
         }
 
     @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun skipsMSDLSuccessHaptics_whenPowerButtonRecentlyPressed_sfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playSuccessHaptic by
+                collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+            setupBiometricAuth(hasSfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            allowHapticsOnSfps(lastPowerPress = 50)
+            unlockWithFingerprintAuth()
+
+            assertThat(playSuccessHaptic).isNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(msdlPlayer.latestTokenPlayed).isNull()
+            assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
+
+            updateFingerprintAuthStatus(isSuccess = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+        }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun skipsErrorHaptics_whenPowerButtonDown_sfps() =
         testScope.runTest {
             val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
@@ -822,6 +976,28 @@
         }
 
     @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun skipsMSDLErrorHaptics_whenPowerButtonDown_sfps() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+            setupBiometricAuth(hasSfps = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            kosmos.fakeKeyEventRepository.setPowerButtonDown(true)
+            updateFingerprintAuthStatus(isSuccess = false)
+
+            assertThat(playErrorHaptic).isNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(msdlPlayer.latestTokenPlayed).isNull()
+            assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
+        }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun skipsFaceErrorHaptics_nonSfps_coEx() =
         testScope.runTest {
             val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
@@ -842,6 +1018,26 @@
         }
 
     @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun skipsMSDLFaceErrorHaptics_nonSfps_coEx() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+            setupBiometricAuth(hasUdfps = true, hasFace = true)
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+            underTest.start()
+            updateFaceAuthStatus(isSuccess = false)
+
+            assertThat(playErrorHaptic).isNull()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(msdlPlayer.latestTokenPlayed).isNull()
+            assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
+        }
+
+    @Test
     fun hydrateSystemUiState() =
         testScope.runTest {
             val transitionStateFlow = prepareState()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
index 4b132c4..a0bb017 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
@@ -18,9 +18,12 @@
 
 package com.android.systemui.scene.ui.viewmodel
 
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
 import android.view.MotionEvent
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.DefaultEdgeDetector
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.classifier.domain.interactor.falsingInteractor
 import com.android.systemui.classifier.fakeFalsingManager
@@ -37,6 +40,10 @@
 import com.android.systemui.scene.shared.model.Overlays
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
+import com.android.systemui.shade.data.repository.fakeShadeRepository
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.shared.model.ShadeMode
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
@@ -60,6 +67,7 @@
     private val testScope by lazy { kosmos.testScope }
     private val sceneInteractor by lazy { kosmos.sceneInteractor }
     private val fakeSceneDataSource by lazy { kosmos.fakeSceneDataSource }
+    private val fakeShadeRepository by lazy { kosmos.fakeShadeRepository }
     private val sceneContainerConfig by lazy { kosmos.sceneContainerConfig }
     private val falsingManager by lazy { kosmos.fakeFalsingManager }
 
@@ -75,6 +83,8 @@
                 sceneInteractor = sceneInteractor,
                 falsingInteractor = kosmos.falsingInteractor,
                 powerInteractor = kosmos.powerInteractor,
+                shadeInteractor = kosmos.shadeInteractor,
+                splitEdgeDetector = kosmos.splitEdgeDetector,
                 logger = kosmos.sceneLogger,
                 motionEventHandlerReceiver = { motionEventHandler ->
                     this@SceneContainerViewModelTest.motionEventHandler = motionEventHandler
@@ -287,4 +297,48 @@
 
             assertThat(actionableContentKey).isEqualTo(Overlays.QuickSettingsShade)
         }
+
+    @Test
+    @DisableFlags(DualShade.FLAG_NAME)
+    fun edgeDetector_singleShade_usesDefaultEdgeDetector() =
+        testScope.runTest {
+            val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
+            fakeShadeRepository.setShadeLayoutWide(false)
+            assertThat(shadeMode).isEqualTo(ShadeMode.Single)
+
+            assertThat(underTest.edgeDetector).isEqualTo(DefaultEdgeDetector)
+        }
+
+    @Test
+    @DisableFlags(DualShade.FLAG_NAME)
+    fun edgeDetector_splitShade_usesDefaultEdgeDetector() =
+        testScope.runTest {
+            val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
+            fakeShadeRepository.setShadeLayoutWide(true)
+            assertThat(shadeMode).isEqualTo(ShadeMode.Split)
+
+            assertThat(underTest.edgeDetector).isEqualTo(DefaultEdgeDetector)
+        }
+
+    @Test
+    @EnableFlags(DualShade.FLAG_NAME)
+    fun edgeDetector_dualShade_narrowScreen_usesSplitEdgeDetector() =
+        testScope.runTest {
+            val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
+            fakeShadeRepository.setShadeLayoutWide(false)
+
+            assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+            assertThat(underTest.edgeDetector).isEqualTo(kosmos.splitEdgeDetector)
+        }
+
+    @Test
+    @EnableFlags(DualShade.FLAG_NAME)
+    fun edgeDetector_dualShade_wideScreen_usesSplitEdgeDetector() =
+        testScope.runTest {
+            val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
+            fakeShadeRepository.setShadeLayoutWide(true)
+
+            assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+            assertThat(underTest.edgeDetector).isEqualTo(kosmos.splitEdgeDetector)
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorTest.kt
new file mode 100644
index 0000000..3d76d28
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorTest.kt
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2024 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.scene.ui.viewmodel
+
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.End
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Resolved.Bottom
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Resolved.Left
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Resolved.Right
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Resolved.TopLeft
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Resolved.TopRight
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Start
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.TopEnd
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.TopStart
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertFailsWith
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class SplitEdgeDetectorTest : SysuiTestCase() {
+
+    private val edgeSize = 40
+    private val screenWidth = 800
+    private val screenHeight = 600
+
+    private var edgeSplitFraction = 0.7f
+
+    private val underTest =
+        SplitEdgeDetector(
+            topEdgeSplitFraction = { edgeSplitFraction },
+            edgeSize = edgeSize.dp,
+        )
+
+    @Test
+    fun source_noEdge_detectsNothing() {
+        val detectedEdge =
+            swipeVerticallyFrom(
+                x = screenWidth / 2,
+                y = screenHeight / 2,
+            )
+        assertThat(detectedEdge).isNull()
+    }
+
+    @Test
+    fun source_swipeVerticallyOnTopLeft_detectsTopLeft() {
+        val detectedEdge =
+            swipeVerticallyFrom(
+                x = 1,
+                y = edgeSize - 1,
+            )
+        assertThat(detectedEdge).isEqualTo(TopLeft)
+    }
+
+    @Test
+    fun source_swipeHorizontallyOnTopLeft_detectsLeft() {
+        val detectedEdge =
+            swipeHorizontallyFrom(
+                x = 1,
+                y = edgeSize - 1,
+            )
+        assertThat(detectedEdge).isEqualTo(Left)
+    }
+
+    @Test
+    fun source_swipeVerticallyOnTopRight_detectsTopRight() {
+        val detectedEdge =
+            swipeVerticallyFrom(
+                x = screenWidth - 1,
+                y = edgeSize - 1,
+            )
+        assertThat(detectedEdge).isEqualTo(TopRight)
+    }
+
+    @Test
+    fun source_swipeHorizontallyOnTopRight_detectsRight() {
+        val detectedEdge =
+            swipeHorizontallyFrom(
+                x = screenWidth - 1,
+                y = edgeSize - 1,
+            )
+        assertThat(detectedEdge).isEqualTo(Right)
+    }
+
+    @Test
+    fun source_swipeVerticallyToLeftOfSplit_detectsTopLeft() {
+        val detectedEdge =
+            swipeVerticallyFrom(
+                x = (screenWidth * edgeSplitFraction).toInt() - 1,
+                y = edgeSize - 1,
+            )
+        assertThat(detectedEdge).isEqualTo(TopLeft)
+    }
+
+    @Test
+    fun source_swipeVerticallyToRightOfSplit_detectsTopRight() {
+        val detectedEdge =
+            swipeVerticallyFrom(
+                x = (screenWidth * edgeSplitFraction).toInt() + 1,
+                y = edgeSize - 1,
+            )
+        assertThat(detectedEdge).isEqualTo(TopRight)
+    }
+
+    @Test
+    fun source_edgeSplitFractionUpdatesDynamically() {
+        val middleX = (screenWidth * 0.5f).toInt()
+        val topY = 0
+
+        // Split closer to the right; middle of screen is considered "left".
+        edgeSplitFraction = 0.6f
+        assertThat(swipeVerticallyFrom(x = middleX, y = topY)).isEqualTo(TopLeft)
+
+        // Split closer to the left; middle of screen is considered "right".
+        edgeSplitFraction = 0.4f
+        assertThat(swipeVerticallyFrom(x = middleX, y = topY)).isEqualTo(TopRight)
+
+        // Illegal fraction.
+        edgeSplitFraction = 1.2f
+        assertFailsWith<IllegalArgumentException> { swipeVerticallyFrom(x = middleX, y = topY) }
+
+        // Illegal fraction.
+        edgeSplitFraction = -0.3f
+        assertFailsWith<IllegalArgumentException> { swipeVerticallyFrom(x = middleX, y = topY) }
+    }
+
+    @Test
+    fun source_swipeVerticallyOnBottom_detectsBottom() {
+        val detectedEdge =
+            swipeVerticallyFrom(
+                x = screenWidth / 3,
+                y = screenHeight - (edgeSize / 2),
+            )
+        assertThat(detectedEdge).isEqualTo(Bottom)
+    }
+
+    @Test
+    fun source_swipeHorizontallyOnBottom_detectsNothing() {
+        val detectedEdge =
+            swipeHorizontallyFrom(
+                x = screenWidth / 3,
+                y = screenHeight - (edgeSize - 1),
+            )
+        assertThat(detectedEdge).isNull()
+    }
+
+    @Test
+    fun source_swipeHorizontallyOnLeft_detectsLeft() {
+        val detectedEdge =
+            swipeHorizontallyFrom(
+                x = edgeSize - 1,
+                y = screenHeight / 2,
+            )
+        assertThat(detectedEdge).isEqualTo(Left)
+    }
+
+    @Test
+    fun source_swipeVerticallyOnLeft_detectsNothing() {
+        val detectedEdge =
+            swipeVerticallyFrom(
+                x = edgeSize - 1,
+                y = screenHeight / 2,
+            )
+        assertThat(detectedEdge).isNull()
+    }
+
+    @Test
+    fun source_swipeHorizontallyOnRight_detectsRight() {
+        val detectedEdge =
+            swipeHorizontallyFrom(
+                x = screenWidth - edgeSize + 1,
+                y = screenHeight / 2,
+            )
+        assertThat(detectedEdge).isEqualTo(Right)
+    }
+
+    @Test
+    fun source_swipeVerticallyOnRight_detectsNothing() {
+        val detectedEdge =
+            swipeVerticallyFrom(
+                x = screenWidth - edgeSize + 1,
+                y = screenHeight / 2,
+            )
+        assertThat(detectedEdge).isNull()
+    }
+
+    @Test
+    fun resolve_startInLtr_resolvesLeft() {
+        val resolvedEdge = Start.resolve(LayoutDirection.Ltr)
+        assertThat(resolvedEdge).isEqualTo(Left)
+    }
+
+    @Test
+    fun resolve_startInRtl_resolvesRight() {
+        val resolvedEdge = Start.resolve(LayoutDirection.Rtl)
+        assertThat(resolvedEdge).isEqualTo(Right)
+    }
+
+    @Test
+    fun resolve_endInLtr_resolvesRight() {
+        val resolvedEdge = End.resolve(LayoutDirection.Ltr)
+        assertThat(resolvedEdge).isEqualTo(Right)
+    }
+
+    @Test
+    fun resolve_endInRtl_resolvesLeft() {
+        val resolvedEdge = End.resolve(LayoutDirection.Rtl)
+        assertThat(resolvedEdge).isEqualTo(Left)
+    }
+
+    @Test
+    fun resolve_topStartInLtr_resolvesTopLeft() {
+        val resolvedEdge = TopStart.resolve(LayoutDirection.Ltr)
+        assertThat(resolvedEdge).isEqualTo(TopLeft)
+    }
+
+    @Test
+    fun resolve_topStartInRtl_resolvesTopRight() {
+        val resolvedEdge = TopStart.resolve(LayoutDirection.Rtl)
+        assertThat(resolvedEdge).isEqualTo(TopRight)
+    }
+
+    @Test
+    fun resolve_topEndInLtr_resolvesTopRight() {
+        val resolvedEdge = TopEnd.resolve(LayoutDirection.Ltr)
+        assertThat(resolvedEdge).isEqualTo(TopRight)
+    }
+
+    @Test
+    fun resolve_topEndInRtl_resolvesTopLeft() {
+        val resolvedEdge = TopEnd.resolve(LayoutDirection.Rtl)
+        assertThat(resolvedEdge).isEqualTo(TopLeft)
+    }
+
+    private fun swipeVerticallyFrom(x: Int, y: Int): SceneContainerEdge.Resolved? {
+        return swipeFrom(x, y, Orientation.Vertical)
+    }
+
+    private fun swipeHorizontallyFrom(x: Int, y: Int): SceneContainerEdge.Resolved? {
+        return swipeFrom(x, y, Orientation.Horizontal)
+    }
+
+    private fun swipeFrom(x: Int, y: Int, orientation: Orientation): SceneContainerEdge.Resolved? {
+        return underTest.source(
+            layoutSize = IntSize(width = screenWidth, height = screenHeight),
+            position = IntOffset(x, y),
+            density = Density(1f),
+            orientation = orientation,
+        )
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
index 3283ea1..9464c75 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
@@ -24,7 +24,6 @@
 import android.platform.test.flag.junit.FlagsParameterization
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.parameterizeSceneContainerFlag
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -39,6 +38,7 @@
 import com.android.systemui.power.data.repository.fakePowerRepository
 import com.android.systemui.power.shared.model.WakeSleepReason
 import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.shade.data.repository.fakeShadeRepository
 import com.android.systemui.shade.data.repository.shadeRepository
 import com.android.systemui.shade.shadeTestUtil
 import com.android.systemui.shade.shared.flag.DualShade
@@ -66,18 +66,18 @@
 @SmallTest
 @RunWith(ParameterizedAndroidJunit4::class)
 class ShadeInteractorImplTest(flags: FlagsParameterization) : SysuiTestCase() {
-    val kosmos = testKosmos()
-    val testScope = kosmos.testScope
-    val configurationRepository by lazy { kosmos.fakeConfigurationRepository }
-    val deviceProvisioningRepository by lazy { kosmos.fakeDeviceProvisioningRepository }
-    val disableFlagsRepository by lazy { kosmos.fakeDisableFlagsRepository }
-    val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
-    val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
-    val powerRepository by lazy { kosmos.fakePowerRepository }
-    val shadeTestUtil by lazy { kosmos.shadeTestUtil }
-    val userRepository by lazy { kosmos.fakeUserRepository }
-    val userSetupRepository by lazy { kosmos.fakeUserSetupRepository }
-    val dozeParameters by lazy { kosmos.dozeParameters }
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+    private val deviceProvisioningRepository by lazy { kosmos.fakeDeviceProvisioningRepository }
+    private val disableFlagsRepository by lazy { kosmos.fakeDisableFlagsRepository }
+    private val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
+    private val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
+    private val powerRepository by lazy { kosmos.fakePowerRepository }
+    private val shadeRepository by lazy { kosmos.fakeShadeRepository }
+    private val shadeTestUtil by lazy { kosmos.shadeTestUtil }
+    private val userRepository by lazy { kosmos.fakeUserRepository }
+    private val userSetupRepository by lazy { kosmos.fakeUserSetupRepository }
+    private val dozeParameters by lazy { kosmos.dozeParameters }
 
     lateinit var underTest: ShadeInteractorImpl
 
@@ -497,4 +497,24 @@
 
             assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
         }
+
+    @Test
+    fun getTopEdgeSplitFraction_narrowScreen_splitInHalf() =
+        testScope.runTest {
+            // Ensure isShadeLayoutWide is collected.
+            val isShadeLayoutWide by collectLastValue(underTest.isShadeLayoutWide)
+            shadeRepository.setShadeLayoutWide(false)
+
+            assertThat(underTest.getTopEdgeSplitFraction()).isEqualTo(0.5f)
+        }
+
+    @Test
+    fun getTopEdgeSplitFraction_wideScreen_leftSideLarger() =
+        testScope.runTest {
+            // Ensure isShadeLayoutWide is collected.
+            val isShadeLayoutWide by collectLastValue(underTest.isShadeLayoutWide)
+            shadeRepository.setShadeLayoutWide(true)
+
+            assertThat(underTest.getTopEdgeSplitFraction()).isGreaterThan(0.5f)
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt
index 840aa92..26e1a4d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt
@@ -26,6 +26,7 @@
 import com.android.settingslib.notification.data.repository.updateNotificationPolicy
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.DisableSceneContainer
 import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.andSceneContainer
@@ -36,6 +37,7 @@
 import com.android.systemui.power.data.repository.fakePowerRepository
 import com.android.systemui.power.shared.model.WakefulnessState
 import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.shadeTestUtil
 import com.android.systemui.statusbar.data.repository.fakeRemoteInputRepository
 import com.android.systemui.statusbar.notification.data.repository.FakeHeadsUpRowRepository
@@ -51,6 +53,7 @@
 import com.android.systemui.util.ui.value
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -153,7 +156,7 @@
     fun shouldShowEmptyShadeView_trueWhenNoNotifs() =
         testScope.runTest {
             val shouldShowEmptyShadeView by collectLastValue(underTest.shouldShowEmptyShadeView)
-            val shouldIncludeFooterView by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldIncludeFooterView by collectFooterViewVisibility()
 
             // WHEN has no notifs
             activeNotificationListRepository.setActiveNotifs(count = 0)
@@ -196,7 +199,7 @@
     fun shouldShowEmptyShadeView_trueWhenQsExpandedInSplitShade() =
         testScope.runTest {
             val shouldShowEmptyShadeView by collectLastValue(underTest.shouldShowEmptyShadeView)
-            val shouldIncludeFooterView by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldIncludeFooterView by collectFooterViewVisibility()
 
             // WHEN has no notifs
             activeNotificationListRepository.setActiveNotifs(count = 0)
@@ -217,7 +220,7 @@
     fun shouldShowEmptyShadeView_trueWhenLockedShade() =
         testScope.runTest {
             val shouldShowEmptyShadeView by collectLastValue(underTest.shouldShowEmptyShadeView)
-            val shouldIncludeFooterView by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldIncludeFooterView by collectFooterViewVisibility()
 
             // WHEN has no notifs
             activeNotificationListRepository.setActiveNotifs(count = 0)
@@ -315,7 +318,7 @@
     @Test
     fun shouldIncludeFooterView_trueWhenShade() =
         testScope.runTest {
-            val shouldIncludeFooterView by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldIncludeFooterView by collectFooterViewVisibility()
             val shouldShowEmptyShadeView by collectLastValue(underTest.shouldShowEmptyShadeView)
 
             // WHEN has notifs
@@ -333,7 +336,7 @@
     @Test
     fun shouldIncludeFooterView_trueWhenLockedShade() =
         testScope.runTest {
-            val shouldIncludeFooterView by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldIncludeFooterView by collectFooterViewVisibility()
             val shouldShowEmptyShadeView by collectLastValue(underTest.shouldShowEmptyShadeView)
 
             // WHEN has notifs
@@ -351,7 +354,7 @@
     @Test
     fun shouldIncludeFooterView_falseWhenKeyguard() =
         testScope.runTest {
-            val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldInclude by collectFooterViewVisibility()
 
             // WHEN has notifs
             activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -366,7 +369,7 @@
     @Test
     fun shouldIncludeFooterView_falseWhenUserNotSetUp() =
         testScope.runTest {
-            val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldInclude by collectFooterViewVisibility()
 
             // WHEN has notifs
             activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -384,7 +387,7 @@
     @Test
     fun shouldIncludeFooterView_falseWhenStartingToSleep() =
         testScope.runTest {
-            val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldInclude by collectFooterViewVisibility()
 
             // WHEN has notifs
             activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -402,7 +405,7 @@
     @Test
     fun shouldIncludeFooterView_falseWhenQsExpandedDefault() =
         testScope.runTest {
-            val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldInclude by collectFooterViewVisibility()
 
             // WHEN has notifs
             activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -421,7 +424,7 @@
     @Test
     fun shouldIncludeFooterView_trueWhenQsExpandedSplitShade() =
         testScope.runTest {
-            val shouldIncludeFooterView by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldIncludeFooterView by collectFooterViewVisibility()
             val shouldShowEmptyShadeView by collectLastValue(underTest.shouldShowEmptyShadeView)
 
             // WHEN has notifs
@@ -444,7 +447,7 @@
     @Test
     fun shouldIncludeFooterView_falseWhenRemoteInputActive() =
         testScope.runTest {
-            val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldInclude by collectFooterViewVisibility()
 
             // WHEN has notifs
             activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -462,7 +465,7 @@
     @Test
     fun shouldIncludeFooterView_animatesWhenShade() =
         testScope.runTest {
-            val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldInclude by collectFooterViewVisibility()
 
             // WHEN has notifs
             activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -478,7 +481,7 @@
     @Test
     fun shouldIncludeFooterView_notAnimatingOnKeyguard() =
         testScope.runTest {
-            val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+            val shouldInclude by collectFooterViewVisibility()
 
             // WHEN has notifs
             activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -492,6 +495,22 @@
         }
 
     @Test
+    @EnableSceneContainer
+    fun shouldShowFooterView_falseWhenShadeIsClosed() =
+        testScope.runTest {
+            val shouldShow by collectLastValue(underTest.shouldShowFooterView)
+
+            // WHEN shade is closed
+            fakeKeyguardRepository.setStatusBarState(StatusBarState.SHADE)
+            shadeTestUtil.setShadeExpansion(0f)
+            runCurrent()
+
+            // THEN footer is hidden
+            assertThat(shouldShow?.value).isFalse()
+        }
+
+    @Test
+    @DisableSceneContainer
     fun shouldHideFooterView_trueWhenShadeIsClosed() =
         testScope.runTest {
             val shouldHide by collectLastValue(underTest.shouldHideFooterView)
@@ -506,6 +525,7 @@
         }
 
     @Test
+    @DisableSceneContainer
     fun shouldHideFooterView_falseWhenShadeIsOpen() =
         testScope.runTest {
             val shouldHide by collectLastValue(underTest.shouldHideFooterView)
@@ -520,6 +540,7 @@
         }
 
     @Test
+    @DisableSceneContainer
     fun shouldHideFooterView_falseWhenQSPartiallyOpen() =
         testScope.runTest {
             val shouldHide by collectLastValue(underTest.shouldHideFooterView)
@@ -642,4 +663,10 @@
 
             assertThat(animationsEnabled).isTrue()
         }
+
+    private fun TestScope.collectFooterViewVisibility() =
+        collectLastValue(
+            if (SceneContainerFlag.isEnabled) underTest.shouldShowFooterView
+            else underTest.shouldIncludeFooterView
+        )
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
index 84c728c..b9ca8fc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
@@ -93,7 +93,7 @@
     fun ssid_carrierMergedNetwork_outputsNull() =
         testScope.runTest {
             wifiRepository.setWifiNetwork(
-                WifiNetworkModel.CarrierMerged(networkId = 1, subscriptionId = 2, level = 1)
+                WifiNetworkModel.CarrierMerged(subscriptionId = 2, level = 1)
             )
 
             var latest: String? = "default"
@@ -106,53 +106,10 @@
         }
 
     @Test
-    fun ssid_isPasspointAccessPoint_outputsPasspointName() =
-        testScope.runTest {
-            wifiRepository.setWifiNetwork(
-                WifiNetworkModel.Active(
-                    networkId = 1,
-                    level = 1,
-                    isPasspointAccessPoint = true,
-                    passpointProviderFriendlyName = "friendly",
-                )
-            )
-
-            var latest: String? = null
-            val job = underTest.ssid.onEach { latest = it }.launchIn(this)
-            runCurrent()
-
-            assertThat(latest).isEqualTo("friendly")
-
-            job.cancel()
-        }
-
-    @Test
-    fun ssid_isOnlineSignUpForPasspoint_outputsPasspointName() =
-        testScope.runTest {
-            wifiRepository.setWifiNetwork(
-                WifiNetworkModel.Active(
-                    networkId = 1,
-                    level = 1,
-                    isOnlineSignUpForPasspointAccessPoint = true,
-                    passpointProviderFriendlyName = "friendly",
-                )
-            )
-
-            var latest: String? = null
-            val job = underTest.ssid.onEach { latest = it }.launchIn(this)
-            runCurrent()
-
-            assertThat(latest).isEqualTo("friendly")
-
-            job.cancel()
-        }
-
-    @Test
     fun ssid_unknownSsid_outputsNull() =
         testScope.runTest {
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.Active(
-                    networkId = 1,
                     level = 1,
                     ssid = WifiManager.UNKNOWN_SSID,
                 )
@@ -172,7 +129,6 @@
         testScope.runTest {
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.Active(
-                    networkId = 1,
                     level = 1,
                     ssid = "MyAwesomeWifiNetwork",
                 )
@@ -234,11 +190,9 @@
         testScope.runTest {
             val wifiNetwork =
                 WifiNetworkModel.Active(
-                    networkId = 45,
                     isValidated = true,
                     level = 3,
                     ssid = "AB",
-                    passpointProviderFriendlyName = "friendly"
                 )
             wifiRepository.setWifiNetwork(wifiNetwork)
 
@@ -346,7 +300,6 @@
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.Active(
                     ssid = "ssid 2",
-                    networkId = 1,
                     level = 2,
                 )
             )
@@ -367,7 +320,6 @@
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.Active(
                     ssid = "ssid 2",
-                    networkId = 1,
                     level = 2,
                 )
             )
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
index dc24cf7..72a45b9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
@@ -115,9 +115,7 @@
             val latestKeyguard by collectLastValue(keyguard.wifiIcon)
             val latestQs by collectLastValue(qs.wifiIcon)
 
-            wifiRepository.setWifiNetwork(
-                WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 1)
-            )
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(isValidated = true, level = 1))
 
             assertThat(latestHome).isInstanceOf(WifiIcon.Visible::class.java)
             assertThat(latestHome).isEqualTo(latestKeyguard)
@@ -132,7 +130,6 @@
             // Even WHEN the network has a valid hotspot type
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.Active(
-                    NETWORK_ID,
                     isValidated = true,
                     level = 1,
                     hotspotDeviceType = WifiNetworkModel.HotspotDeviceType.LAPTOP,
@@ -194,9 +191,7 @@
             whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
             createAndSetViewModel()
 
-            wifiRepository.setWifiNetwork(
-                WifiNetworkModel.Active(NETWORK_ID, ssid = null, level = 1)
-            )
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(ssid = null, level = 1))
 
             val activityIn by collectLastValue(underTest.isActivityInViewVisible)
             val activityOut by collectLastValue(underTest.isActivityOutViewVisible)
@@ -219,9 +214,7 @@
             whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
             createAndSetViewModel()
 
-            wifiRepository.setWifiNetwork(
-                WifiNetworkModel.Active(NETWORK_ID, ssid = null, level = 1)
-            )
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(ssid = null, level = 1))
 
             val activityIn by collectLastValue(underTest.isActivityInViewVisible)
             val activityOut by collectLastValue(underTest.isActivityOutViewVisible)
@@ -470,8 +463,6 @@
     }
 
     companion object {
-        private const val NETWORK_ID = 2
-        private val ACTIVE_VALID_WIFI_NETWORK =
-            WifiNetworkModel.Active(NETWORK_ID, ssid = "AB", level = 1)
+        private val ACTIVE_VALID_WIFI_NETWORK = WifiNetworkModel.Active(ssid = "AB", level = 1)
     }
 }
diff --git a/packages/SystemUI/res/layout/notification_template_en_route_contracted.xml b/packages/SystemUI/res/layout/notification_template_en_route_contracted.xml
index 59cfecc..e7a40d1 100644
--- a/packages/SystemUI/res/layout/notification_template_en_route_contracted.xml
+++ b/packages/SystemUI/res/layout/notification_template_en_route_contracted.xml
@@ -16,7 +16,7 @@
 
 <com.android.systemui.statusbar.notification.row.ui.view.EnRouteView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/status_bar_latest_event_content"
+    android:id="@*android:id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_weight="1"
diff --git a/packages/SystemUI/res/layout/notification_template_en_route_expanded.xml b/packages/SystemUI/res/layout/notification_template_en_route_expanded.xml
new file mode 100644
index 0000000..ca6d66a
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_template_en_route_expanded.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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
+  -->
+<com.android.systemui.statusbar.notification.row.ui.view.EnRouteView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@*android:id/status_bar_latest_event_content"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:clipChildren="false"
+    android:tag="big"
+    >
+
+    <LinearLayout
+        android:id="@*android:id/notification_action_list_margin_target"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="@*android:dimen/notification_content_margin"
+        android:orientation="vertical"
+        >
+
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:layout_gravity="top"
+            >
+
+            <include layout="@*android:layout/notification_template_header" />
+
+            <LinearLayout
+                android:id="@*android:id/notification_main_column"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="@*android:dimen/notification_content_margin_start"
+                android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
+                android:layout_marginTop="@*android:dimen/notification_content_margin_top"
+                android:orientation="vertical"
+                >
+
+                <include layout="@*android:layout/notification_template_part_line1" />
+
+                <include layout="@*android:layout/notification_template_text_multiline" />
+
+                <include
+                    android:layout_width="match_parent"
+                    android:layout_height="@*android:dimen/notification_progress_bar_height"
+                    android:layout_marginTop="@*android:dimen/notification_progress_margin_top"
+                    layout="@*android:layout/notification_template_progress"
+                    />
+            </LinearLayout>
+
+            <include layout="@*android:layout/notification_template_right_icon" />
+        </FrameLayout>
+
+        <ViewStub
+            android:layout="@*android:layout/notification_material_reply_text"
+            android:id="@*android:id/notification_material_reply_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            />
+
+        <include
+            layout="@*android:layout/notification_template_smart_reply_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@*android:dimen/notification_content_margin_start"
+            android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
+            android:layout_marginTop="@*android:dimen/notification_content_margin"
+            />
+
+        <include layout="@*android:layout/notification_material_action_list" />
+    </LinearLayout>
+</com.android.systemui.statusbar.notification.row.ui.view.EnRouteView>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index a1be54c..2a669de 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> en ander oop apps het hierdie skermskoot bespeur."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Voeg by nota"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Sluit skakel in"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Skermopnemer"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Verwerk tans skermopname"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Deurlopende kennisgewing vir \'n skermopnamesessie"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Sluimerskerm"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Moenie Steur Nie"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioriteitmodusse"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Geen saamgebinde toestelle beskikbaar nie"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tik om ’n toestel te koppel of ontkoppel"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Gebruik Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Gekoppel"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Oudiodeling"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tik om oor te skakel of oudio te deel"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gestoor"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ontkoppel"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiveer"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Maak Instellings oop"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Ander toestel"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Wissel oorsig"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteitmodusse"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Klaar"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Instellings"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Aan"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Die diens wat hierdie funksie verskaf, sal toegang hê tot al die inligting wat op jou skerm sigbaar is of op jou toestel gespeel word terwyl dit opneem of uitsaai. Dit sluit in inligting soos wagwoorde, betalingbesonderhede, foto’s, boodskappe en oudio wat jy speel."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Deel of neem ’n app op"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Deel jou skerm met <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Deel een app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Deel hele skerm"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Deel een app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Deel hele skerm"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Wanneer jy jou hele skerm deel, is enigiets op jou skerm sigbaar aan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Wanneer jy ’n app deel, is enigiets wat in die app wys of speel, sigbaar aan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Deel skerm"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Vou ikoon in"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Vou ikoon uit"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"of"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Teruggebaar"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Tuisgebaar"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Handelingsleutel"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 23f3766..f7f9763 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> እና ሌሎች ክፍት መተግበሪያዎች ይህን ቅጽበታዊ ገፅ ዕይታ ለይተዋል።"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ወደ ማስታወሻ አክል"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"አገናኝ አካትት"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g><xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"የማያ መቅረጫ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"የማያ ገፅ ቀረጻን በማሰናዳት ላይ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ለአንድ የማያ ገፅ ቀረጻ ክፍለ-ጊዜ በመካሄድ ያለ ማሳወቂያ"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"የማያ ገፅ ማቆያ"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ኤተርኔት"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"አትረብሽ"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"ቅድሚያ ሁነታዎች"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ብሉቱዝ"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ምንም የተጣመሩ መሣሪያዎች አይገኝም"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"መሣሪያን ለማገናኘት ወይም ግንኙነቱን ለማቋረጥ መታ ያድርጉ"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ብሉቱዝን ይጠቀሙ"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ተገናኝቷል"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"የድምጽ ማጋራት"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ኦዲዮ ለመቀየር ወይም ለማጋራት መታ ያድርጉ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ተቀምጧል"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ግንኙነትን አቋርጥ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ያግብሩ"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ቅንብሮችን ክፈት"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"ሌላ መሣሪያ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"አጠቃላይ እይታን ቀያይር"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ቅድሚያ ሁነታዎች"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ተከናውኗል"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ቅንብሮች"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"በርቷል"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ይህን ተግባር የሚያቀርበው አገልግሎት በእርስዎ ማያ ገጽ ላይ ለሚታየው ወይም በሚቀረጽበት ወይም cast በሚደረግበት ጊዜ በእርስዎ መሣሪያ ላይ ለሚጫወተው ሁሉም መረጃ መዳረሻ ይኖረዋል። ይህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ ፎቶዎች፣ መልዕክቶች እና እርስዎ የሚያጫውቱትን ኦዲዮ የመሳሰለ መረጃን ያካትታል።"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"መተግበሪያን ያጋሩ ወይም ይቅረጹ"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"ማያ ገፅዎን ለ<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ያጋራሉ?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"አንድ መተግበሪያ ያጋሩ"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"መላውን ማያ ገፅ ያጋሩ"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"አንድ መተግበሪያ ያጋሩ"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"መላውን ማያ ገፅ ያጋሩ"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"እርስዎ ሙሉ ማያ ገፅዎን ሲያጋሩ በማያ ገፅዎ ላይ ያለው ማንኛውም ነገር ለ<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ይታያል። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"መተግበሪያን ሲያጋሩ በዚያ መተግበሪያ ውስጥ የሚታይ ወይም የሚጫወት ማንኛውም ነገር ለ<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ይታያል። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ማያ ገፅ አጋራ"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"መሰብሰቢያ አዶ"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"መዘርጊያ አዶ"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ወይም"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"የተመለስ ምልክት"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"የቤት ምልክት"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"የተግባር ቁልፍ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 0ac0d03..5d6b908 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"رصَد تطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\" والتطبيقات المفتوحة الأخرى لقطة الشاشة هذه."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"إضافة إلى الملاحظة"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"تضمين الرابط"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"‫<xliff:g id="APPNAME">%1$s</xliff:g> ‏<xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"مسجّل الشاشة"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"جارٍ معالجة تسجيل الشاشة"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"إشعار مستمر لجلسة تسجيل شاشة"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"شاشة الاستراحة"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"عدم الإزعاج"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"الأوضاع ذات الأولوية"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"بلوتوث"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"لا يتوفر أي أجهزة مقترنة"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"انقر للاتصال بجهاز أو قطع الاتصال به"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"استخدام البلوتوث"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"متّصل"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"مشاركة الصوت"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"انقر لتبديل مصدر الصوت أو مشاركته"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"محفوظ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"إلغاء الربط"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"تفعيل"</string>
@@ -386,13 +387,13 @@
     <string name="qs_record_issue_start" msgid="2979831312582567056">"بدء"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"إيقاف"</string>
     <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"تقرير خطأ"</string>
-    <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ما هو الجانب الذي تأثّر في تجربة استخدام الجهاز؟"</string>
+    <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"بأي جانب من تجربة استخدام الجهاز تتعلّق المشكلة؟"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"اختيار نوع المشكلة"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"تسجيل الشاشة"</string>
     <string name="performance" msgid="6552785217174378320">"الأداء"</string>
     <string name="user_interface" msgid="3712869377953950887">"واجهة المستخدم"</string>
-    <string name="thermal" msgid="6758074791325414831">"الأداء الحراري"</string>
-    <string name="custom" msgid="3337456985275158299">"مخصّص"</string>
+    <string name="thermal" msgid="6758074791325414831">"ارتفاع حرارة الجهاز"</string>
+    <string name="custom" msgid="3337456985275158299">"الإعدادات المخصّصة"</string>
     <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"إعدادات التتبع المخصصة"</string>
     <string name="restore_default" msgid="5259420807486239755">"استعادة الإعدادات التلقائية"</string>
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"وضع \"التصفح بيد واحدة\""</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"فتح الإعدادات"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"جهاز آخر"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تبديل \"النظرة العامة\""</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"الأوضاع ذات الأولوية"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"تم"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"الإعدادات"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"مفعَّل"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ستتمكن الخدمة التي تقدّم هذه الوظيفة من الوصول إلى كل المحتوى المعروض على شاشتك أو الذي يتم تشغيله على جهازك أثناء التسجيل أو البثّ. ويشمل ذلك معلومات، مثل كلمات المرور وتفاصيل الدفع والصور والرسائل والمقاطع الصوتية التي تشغِّلها."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"مشاركة محتوى تطبيق أو تسجيله"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"هل تريد مشاركة الشاشة مع تطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"؟"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"مشاركة تطبيق واحد"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"مشاركة الشاشة بأكملها"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"مشاركة تطبيق واحد"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"مشاركة الشاشة بأكملها"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"أثناء مشاركة محتوى الشاشة بالكامل، سيكون كل المحتوى المعروض على شاشتك مرئيًا لتطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\". لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"أثناء مشاركة محتوى تطبيق، سيكون كل المحتوى المعروض أو الذي يتم تشغيله في ذلك التطبيق مرئيًا لتطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\". لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"مشاركة الشاشة"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"رمز التصغير"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"رمز التوسيع"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"أو"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"إيماءة الرجوع"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"إيماءة الانتقال إلى الشاشة الرئيسية"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"مفتاح الإجراء"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index a770c61..2e8a552 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> আৰু আন খোলা এপ্‌সমূহে এই স্ক্ৰীনশ্বটটো চিনাক্ত কৰিছে।"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"টোকাত যোগ দিয়ক"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"লিংক অন্তৰ্ভুক্ত কৰক"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"স্ক্ৰীন ৰেকৰ্ডাৰ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রীন ৰেকৰ্ডিঙৰ প্ৰক্ৰিয়াকৰণ হৈ আছে"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীন ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"স্ক্ৰীন ছেভাৰ"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ইথাৰনেট"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"অসুবিধা নিদিব"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"অগ্ৰাধিকাৰপ্ৰাপ্ত ম’ড"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ব্লুটুথ"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"কোনো যোৰা লগোৱা ডিভাইচ উপলব্ধ নহয়।"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ডিভাইচ সংযোগ কৰিবলৈ অথবা সংযোগ বিচ্ছিন্ন কৰিবলৈ টিপক"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ব্লুটুথ ব্যৱহাৰ কৰক"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"সংযুক্ত আছে"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"অডিঅ’ শ্বেয়াৰ কৰা"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"অডিঅ’ সলনি কৰিবলৈ বা শ্বেয়াৰ কৰিলৈ টিপক"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ছেভ কৰা হৈছে"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"সংযোগ বিচ্ছিন্ন কৰক"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"সক্ৰিয় কৰক"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ছেটিং খোলক"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"অন্য ডিভাইচ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"অৱলোকন ট’গল কৰক"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"অগ্ৰাধিকাৰপ্ৰাপ্ত ম’ডসমূহ"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"কৰা হ’ল"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ছেটিং"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"অন আছে"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"এই সুবিধাটো প্ৰদান কৰা সেৱাটোৱে আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকৰ্ডিং অথবা কাষ্টিঙৰ সময়ত আপোনাৰ ডিভাইচত প্লে’ কৰা আটাইবোৰ তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, ফট’, বাৰ্তাসমূহ আৰু আপুনি প্লে’ কৰা অডিঅ’ৰ দৰে তথ্য অন্তৰ্ভুক্ত হয়।"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"এটা এপ্ শ্বেয়াৰ অথবা ৰেকৰ্ড কৰক"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ সৈতে আপোনাৰ স্ক্ৰীন শ্বেয়াৰ কৰিবনে?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"এটা এপ্‌ শ্বেয়াৰ কৰক"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"গোটেই স্ক্ৰীনখন শ্বেয়াৰ কৰক"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"এটা এপ্‌ শ্বেয়াৰ কৰক"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"গোটেই স্ক্ৰীনখন শ্বেয়াৰ কৰক"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"আপুনি আপোনাৰ গোটেই স্ক্ৰীনখন শ্বেয়াৰ কৰি থাকোঁতে, আপোনাৰ স্ক্ৰীনত থকা যিকোনো বস্তু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ত দৃশ্যমান হয়। সেয়ে পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"আপুনি কোনো এপ্‌ শ্বেয়াৰ কৰি থাকোঁতে সেই এপ্‌টোত দেখুওৱা বা প্লে’ কৰা যিকোনো বস্তু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ত দৃশ্যমান হয়। সেয়ে পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"স্ক্ৰীন শ্বেয়াৰ কৰক"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"সংকোচন কৰাৰ চিহ্ন"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"বিস্তাৰ কৰাৰ চিহ্ন"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"অথবা"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"উভতি যাওক নিৰ্দেশ"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"গৃহ স্ক্ৰীনলৈ যোৱাৰ নিৰ্দেশ"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"কাৰ্য কী"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index cd7bbaf..b011ca64 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> və digər açıq tətbiqlər bu skrinşotu aşkarladı."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Qeydə əlavə edin"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Keçid daxil edin"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g><xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Ekran yazıcısı"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran çəkilişi emal edilir"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekranın video çəkimi ərzində silinməyən bildiriş"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Ekran qoruyucu"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Narahat etməyin"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritet rejimləri"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Heç bir cütlənmiş cihaz əlçatan deyil"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toxunaraq cihaza qoşulun, yaxud əlaqəni ayırın"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-u açın"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Qoşulub"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio paylaşma"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Dəyişmək və ya audio paylaşmaq üçün toxunun"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Yadda saxlandı"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"əlaqəni kəsin"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivləşdirin"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Ayarları açın"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Digər cihaz"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"İcmala Keçin"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritet rejimləri"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hazırdır"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ayarlar"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Aktiv"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Bu funksiyanı təmin edən xidmətin qeydəalma və ya yayım zamanı ekranda görünən, yaxud cihazda oxudulan məlumatlara girişi olacaq. Bura parol, ödəniş detalları, foto, mesaj və oxudulan audio kimi məlumatlar daxildir."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Tətbiq paylaşın və ya qeydə alın"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ekran <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilə paylaşılsın?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Bir tətbiq paylaşın"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Bütün ekranı paylaşın"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Bir tətbiq paylaşın"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Bütün ekranı paylaşın"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Bütün ekranı paylaşdığınız zaman ekrandakı hər şey <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> üçün görünən olacaq. Parol, ödəniş məlumatı, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Tətbiq paylaşdığınız zaman həmin tətbiqdə göstərilən və ya işə salınan hər şey <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> üçün görünən olacaq. Parol, ödəniş məlumatı, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ekranı paylaşın"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"İkonanı yığcamlaşdırın"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"İkonanı genişləndirin"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"və ya"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Geri jesti"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Əsas ekran jesti"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Əməliyyat düyməsi"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 25ecce5..c581fd5 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> i druge otvorene aplikacije su otkrile ovaj snimak ekrana."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj u belešku"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Uvrsti link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Snimač ekrana"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađujemo video snimka ekrana"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obaveštenje o sesiji snimanja ekrana je aktivno"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Čuvar ekrana"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Eternet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne uznemiravaj"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritetni režimi"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nije dostupan nijedan upareni uređaj"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Dodirnite da biste povezali uređaj ili prekinuli vezu"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Koristi Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Deljenje zvuka"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Dodirnite da biste prebacili ili delili zvuk"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sačuvano"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekinite vezu"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivirajte"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Otvori Podešavanja"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Drugi uređaj"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Uključi/isključi pregled"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetni režimi"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotovo"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Podešavanja"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Usluga koja pruža ovu funkciju će imati pristup svim informacijama koje se prikazuju na ekranu ili reprodukuju sa uređaja tokom snimanja ili prebacivanja. To obuhvata informacije poput lozinki, informacija o plaćanju, slika, poruka i zvuka koji puštate."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Delite ili snimite aplikaciju"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Želite da delite ekran sa aplikacijom <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Deli jednu aplikaciju"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Deli ceo ekran"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Deli jednu aplikaciju"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Deli ceo ekran"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kada delite ceo ekran, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vidi sve što je na njemu. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, audio i video sadržaj."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kada delite aplikaciju, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vidi sav sadržaj koji se prikazuje ili pušta u njoj. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, audio i video sadržaj."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Deli ekran"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona za skupljanje"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona za proširivanje"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ili"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Pokret za vraćanje"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pokret za početnu stranicu"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Taster radnji"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 5ea0621..31854f6 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> і іншыя адкрытыя праграмы выявілі гэты здымак экрана."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Дадаць у нататку"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Дадаць спасылку"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Запіс экрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Апрацоўваецца запіс экрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Бягучае апавяшчэнне для сеанса запісу экрана"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Экранная застаўка"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не турбаваць"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Прыярытэтныя рэжымы"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Няма даступных спалучаных прылад"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Націсніце, каб падключыць або адключыць прыладу"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Выкарыстоўваць Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Падключана"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Абагульванне аўдыя"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Націсніце, каб пераключыць або абагуліць аўдыя"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Захавана"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"адключыць"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"актываваць"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Адкрыць налады"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Іншая прылада"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Уключыць/выключыць агляд"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Прыярытэтныя рэжымы"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Гатова"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Налады"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Уключана"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Падчас запісу ці трансляцыі служба, якая забяспечвае работу гэтай функцыі, будзе мець доступ да ўсёй інфармацыі, адлюстраванай на экране вашай прылады, ці той, якая праз яе прайграецца. Гэтая інфармацыя ўключае паролі, плацежных рэквізітаў, фота, паведамленні і аўдыя, якое вы прайграяце."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Абагульванне або запіс праграмы"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Абагуліць экран з праграмай \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Абагуліць адну праграму"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Абагуліць увесь экран"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Абагуліць адну праграму"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Абагуліць увесь экран"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Калі вы абагульваеце ўвесь экран, праграма \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" можа бачыць усё, што адбываецца на экране. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Калі вы абагульваеце праграму, праграма \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" можа бачыць усё, што паказваецца ці прайграецца ў гэтай праграме. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Абагуліць экран"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Значок \"Згарнуць\""</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Значок \"Разгарнуць\""</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"або"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Жэст для вяртання на папярэдні экран"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жэст для вяртання на галоўны экран"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Клавіша дзеяння"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index ee11863..64ecfd3 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> и други отворени приложения установиха заснемането на тази екранна снимка."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Добавяне към бележката"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Включване на връзката"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Запис на екрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Записът на екрана се обработва"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущо известие за сесия за записване на екрана"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Скрийнсейвър"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не безпокойте"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Приоритетни режими"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Няма налични сдвоени устройства"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Докоснете, за да свържете устройство или да прекъснете връзката му"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Използване на Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Установена е връзка"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Споделяне на звука"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Докоснете, за да превключите или споделите аудио"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Запазено"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекратяване на връзката"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активиране"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Към настройките"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Друго устройство"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Превключване на общия преглед"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Приоритетни режими"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Настройки"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Вкл."</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Услугата, предоставяща тази функция, ще има достъп до цялата информация, която е видима на екрана или възпроизвеждана от устройството ви по време на записване или предаване. Това включва различна информация, като например пароли, подробности за начини на плащане, снимки, съобщения и възпроизвеждано аудио."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Споделяне или записване на приложение"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Да се сподели ли екранът ви с(ъс) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Споделяне на едно приложение"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Споделяне на целия екран"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Споделяне на едно приложение"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Споделяне на целия екран"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Когато споделяте целия си екран, всичко, което се показва на него, е видимо за <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Когато споделяте приложение, всичко, което се показва или възпроизвежда в него, е видимо за <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Споделяне на екрана"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Икона за свиване"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Икона за разгъване"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"или"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Жест за връщане назад"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жест за преминаване към началния екран"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Клавиш за действия"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 2536cb7..f62ee9e 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> এবং খোলা থাকা অন্য অ্যাপ এই স্ক্রিনশট শনাক্ত করেছে।"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"নোটে যোগ করুন"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"লিঙ্ক যোগ করুন"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"স্ক্রিন রেকর্ডার"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রিন রেকর্ডিং প্রসেস হচ্ছে"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রিন রেকর্ডিং সেশন চলার বিজ্ঞপ্তি"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"স্ক্রিন সেভার"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ইথারনেট"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"বিরক্ত করবে না"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"প্রায়োরিটি মোড"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ব্লুটুথ"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"চেনা কোনও ডিভাইস নেই"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"কোনও ডিভাইস কানেক্ট বা ডিসকানেক্ট করতে ট্যাপ করুন"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ব্লুটুথ ব্যবহার করুন"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"কানেক্ট করা আছে"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"অডিও শেয়ারিং"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"অডিও শেয়ার বা পরিবর্তন করতে ট্যাপ করুন"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"সেভ করা আছে"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ডিসকানেক্ট করুন"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"চালু করুন"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"সেটিংস খুলুন"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"অন্য ডিভাইস"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"\'এক নজরে\' বৈশিষ্ট্যটি চালু বা বন্ধ করুন"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"প্রায়োরিটি মোড"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"হয়ে গেছে"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"সেটিংস"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"চালু আছে"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"যে পরিষেবা এই ফাংশন প্রদান করছে, সেটি রেকর্ড বা কাস্ট করার সময় আপনার স্ক্রিনে দৃশ্যমান বা ডিভাইসে চালানো হয়েছে এমন সব তথ্য অ্যাক্সেস করতে পারবে। এর মধ্যে আপনার পাসওয়ার্ড, পেমেন্টের বিবরণ, ফটো, মেসেজ এবং আপনার চালানো অডিও সম্পর্কিত তথ্য রয়েছে।"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"কোনও অ্যাপ শেয়ার বা রেকর্ড করুন"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-এর সাথে আপনার স্ক্রিন শেয়ার করবেন?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"একটি অ্যাপ শেয়ার করুন"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"সম্পূর্ণ স্ক্রিন শেয়ার করুন"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"একটি অ্যাপ শেয়ার করুন"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"সম্পূর্ণ স্ক্রিন শেয়ার করুন"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"আপনার সম্পূর্ণ স্ক্রিন শেয়ার করার সময়, স্ক্রিনে থাকা সব কিছু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> দেখতে পাবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ের ক্ষেত্রে সতর্ক থাকুন।"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"কোনও অ্যাপ শেয়ার করার সময়, সেই অ্যাপে দেখা ও চালানো হয় এমন সব কিছু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> দেখতে পাবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ের ক্ষেত্রে সতর্ক থাকুন।"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"স্ক্রিন শেয়ার করুন"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"আইকন আড়াল করুন"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"আইকন বড় করুন"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"অথবা"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ফিরে যাওয়ার জেসচার"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"হোমপেজে যাওয়ার জেসচার"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"অ্যাকশন কী"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 43ae5c7..51416ef 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> i druge otvorene aplikacije su otkrile ovaj snimak ekrana."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj u bilješku"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Uključi link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Snimač ekrana"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađivanje snimka ekrana"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obavještenje za sesiju snimanja ekrana je u toku"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Čuvar ekrana"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne ometaj"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritetni načini rada"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nema dostupnih uparenih uređaja"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Dodirnite da povežete ili prekinete povezanost uređaja"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Koristi Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Dijeljenje zvuka"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Dodirnite da uključite ili dijelite zvučni zapis"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sačuvano"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekid veze"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviranje"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Otvori Postavke"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Drugi uređaj"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pregled uključivanja/isključivanja"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetni načini rada"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotovo"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Postavke"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Usluga koja pruža ovu funkciju će imati pristup svim informacijama koje su vidljive na ekranu ili koje se reproduciraju s uređaja tokom snimanja ili emitiranja. To uključuje informacije kao što su lozinke, detalji o plaćanju, fotografije, poruke i zvuk koji reproducirate."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Dijelite ili snimajte aplikaciju"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Dijeliti ekran s aplikacijom <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Dijeli jednu aplikaciju"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Dijeli cijeli ekran"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Dijeli jednu aplikaciju"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Dijeli cijeli ekran"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kada dijelite cijeli ekran, sve što je na ekranu će biti vidljivo aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kada dijelite aplikaciju, sve što se prikazuje ili reproducira u toj aplikaciji će biti vidljivo aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Dijeli ekran"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona sužavanja"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona proširivanja"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ili"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Pokret za povratak"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pokret za povratak na početni ekran"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tipka radnji"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 187e75e..182fe02 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> i altres aplicacions obertes han detectat aquesta captura de pantalla."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Afegeix a una nota"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Inclou l\'enllaç"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Gravació de pantalla"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processant gravació de pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificació en curs d\'una sessió de gravació de la pantalla"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Estalvi de pantalla"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"No molestis"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modes prioritaris"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No hi ha dispositius vinculats  disponibles"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toca per connectar o desconnectar un dispositiu"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Utilitza el Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connectat"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartició d\'àudio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Toca per canviar o compartir l\'àudio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Desat"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconnecta"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activa"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Obre Configuració"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Un altre dispositiu"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activa o desactiva Aplicacions recents"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modes prioritaris"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Fet"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuració"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Activat"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"El servei que ofereix aquesta funció tindrà accés a tota la informació visible a la teva pantalla o que es reprodueix al dispositiu mentre graves o emets contingut, com ara les contrasenyes, les dades de pagament, les fotos, els missatges i àudio que reprodueixis."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Comparteix o grava una aplicació"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vols compartir la pantalla amb <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Comparteix una aplicació"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Comparteix tota la pantalla"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Comparteix una aplicació"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Comparteix tota la pantalla"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quan comparteixes tota la pantalla, qualsevol cosa que es mostra en pantalla és visible a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quan comparteixes una aplicació, qualsevol cosa que es mostra o que es reprodueix en aquesta aplicació és visible a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Comparteix la pantalla"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Replega la icona"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Desplega la icona"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gest Enrere"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gest Inici"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla d\'acció"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 13e0377..cebb175 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> a ostatní otevřené aplikace objevily tento snímek obrazovky."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Přidat do poznámky"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Zahrnout odkaz"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Nahrávání obrazovky"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Záznam obrazovky se zpracovává"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Trvalé oznámení o relaci nahrávání"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Spořič obrazovky"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Nerušit"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Režimy priority"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nejsou dostupná žádná spárovaná zařízení"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Klepnutím zařízení připojíte nebo odpojíte"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Používat Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Připojeno"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Sdílení zvuku"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Klepnutím přepnete nebo nasdílíte zvuk"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Uloženo"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"odpojit"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivovat"</string>
@@ -391,7 +392,7 @@
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Záznam obrazovky"</string>
     <string name="performance" msgid="6552785217174378320">"Výkon"</string>
     <string name="user_interface" msgid="3712869377953950887">"Uživatelské rozhraní"</string>
-    <string name="thermal" msgid="6758074791325414831">"Termovize"</string>
+    <string name="thermal" msgid="6758074791325414831">"Teplota"</string>
     <string name="custom" msgid="3337456985275158299">"Vlastní"</string>
     <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Vlastní nastavení trasování"</string>
     <string name="restore_default" msgid="5259420807486239755">"Obnovit výchozí"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Otevřít nastavení"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Další zařízení"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Přepnout přehled"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Režimy priority"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hotovo"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavení"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Zapnuto"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Služba, která tuto funkci poskytuje, bude mít při nahrávání nebo odesílání přístup ke všem informacím, které jsou viditelné na obrazovce nebo které jsou přehrávány ze zařízení. Týká se to i hesel, údajů o platbě, fotek, zpráv a přehrávaných zvuků."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Sdílení nebo nahrání aplikace"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Sdílet obrazovku s aplikací <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Sdílet jednu aplikaci"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Sdílet celou obrazovku"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Sdílet jednu aplikaci"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Sdílet celou obrazovku"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Při sdílení celé obrazovky vidí aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vše, co se na obrazovce nachází nebo děje. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Při sdílení aplikace vidí aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vše, co se ve sdílené aplikaci nachází nebo děje. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Sdílet obrazovku"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona sbalení"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona rozbalení"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"nebo"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto zpět"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto domů"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Akční klávesa"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 4ba9fe9..974083e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> og andre åbne apps har registreret dette screenshot."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Føj til note"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Inkluder link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Skærmoptagelse"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skærmoptagelse"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Konstant notifikation om skærmoptagelse"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Pauseskærm"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Forstyr ikke"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Tilstande med prioritet"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Der er ingen tilgængelige parrede enheder"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tryk for at oprette eller afbryde forbindelse til en enhed"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Brug Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Der er oprettet forbindelse"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Lyddeling"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tryk for at skifte eller dele lyd"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gemt"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"afbryd forbindelse"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivér"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Åbn Indstillinger"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Anden enhed"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå Oversigt til/fra"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Tilstande med prioritet"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Udfør"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Indstillinger"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Til"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Tjenesten, der tilbyder denne funktion, får adgang til alle de oplysninger, der er synlige på din skærm, eller som afspilles på din enhed, når du optager eller caster. Dette omfatter oplysninger som f.eks. adgangskoder, betalingsoplysninger, billeder, beskeder og afspillet lyd."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Del eller optag en app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vil du dele din skærm med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Del én app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Del hele skærmen"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Del én app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Del hele skærmen"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Når du deler hele skærmen, er alt på din skærm synligt for <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Vær derfor forsigtig med f.eks. adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Når du deler en app, er alt, der vises eller afspilles i den pågældende app, synligt for <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Vær derfor forsigtig med f.eks. adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Del skærm"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikon for Skjul"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikon for Udvid"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"eller"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Bevægelse for at gå tilbage"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Bevægelse for at gå til startskærm"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Handlingstast"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 7a8d06c..11dd46e 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> und andere geöffnete Apps haben diesen Screenshot erkannt."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Zu Notiz hinzufügen"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Link einschließen"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Bildschirmaufzeichnung"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Bildschirmaufzeichnung…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Fortlaufende Benachrichtigung für eine Bildschirmaufzeichnung"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Bildschirmschoner"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Bitte nicht stören"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritätsmodi"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Keine gekoppelten Geräte verfügbar"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Zum Verbinden oder Trennen eines Geräts tippen"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth verwenden"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Verbunden"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audiofreigabe"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Zum Wechseln oder Teilen des Audiostreams tippen"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gespeichert"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"Verknüpfung aufheben"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivieren"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Einstellungen öffnen"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Sonstiges Gerät"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Übersicht ein-/ausblenden"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritätsmodi"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Fertig"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Einstellungen"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"An"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Der Anbieter dieser App erhält Zugriff auf alle Informationen, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden, während du aufnimmst oder streamst. Dazu gehören beispielsweise Passwörter, Zahlungsdetails, Fotos, Nachrichten und Audioinhalte."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"App teilen oder aufnehmen"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Bildschirm mit <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> teilen?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Eine App streamen"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Gesamten Bildschirm teilen"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Eine App teilen"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Gesamten Bildschirm teilen"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Wenn du den gesamten Bildschirm teilst, ist für <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> alles auf dem Bildschirm sichtbar. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Wenn du eine App streamst, ist für <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> alles sichtbar, was in dieser App angezeigt oder abgespielt wird. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Bildschirm teilen"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Symbol „Minimieren“"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Symbol „Maximieren“"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"oder"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Touch-Geste „Zurück“"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Touch-Geste „Startbildschirm“"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Aktionstaste"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 015d625..433137c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Η εφαρμογή <xliff:g id="APPNAME">%1$s</xliff:g> και άλλες ανοικτές εφαρμογές εντόπισαν το στιγμιότυπο οθόνης."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Προσθήκη σε σημείωση"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Συμπερίληψη συνδέσμου"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Εγγραφή οθόνης"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Επεξεργασία εγγραφής οθόνης"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ειδοποίηση σε εξέλιξη για μια περίοδο λειτουργίας εγγραφής οθόνης"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Προφύλαξη οθόνης"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Μην ενοχλείτε"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Λειτουργίες προτεραιότητας"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Δεν υπάρχουν διαθέσιμες συσκευές σε σύζευξη"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Πατήστε για σύνδεση ή αποσύνδεση μιας συσκευής"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Χρήση Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Συνδέθηκε"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Κοινή χρήση ήχου"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Πατήστε για εναλλαγή ή κοινή χρήση ήχου"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Αποθηκεύτηκε"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"αποσύνδεση"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ενεργοποίηση"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Άνοιγμα Ρυθμίσεων"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Άλλη συσκευή"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Εναλλαγή επισκόπησης"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Λειτουργίες προτεραιότητας"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Τέλος"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ρυθμίσεις"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Ενεργό"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Η υπηρεσία που παρέχει αυτήν τη λειτουργία θα έχει πρόσβαση σε όλες τις πληροφορίες που εμφανίζονται στην οθόνη σας ή που αναπαράγονται από τη συσκευή σας κατά την εγγραφή ή τη μετάδοση. Αυτό περιλαμβάνει πληροφορίες όπως κωδικούς πρόσβασης, στοιχεία πληρωμής, φωτογραφίες, μηνύματα και ήχο που αναπαράγετε."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Κοινή χρήση ή εγγραφή εφαρμογής"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Κοινή χρήση της οθόνης με την εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>;"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Κοινή χρήση μίας εφαρμογής"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Κοινή χρήση ολόκληρης της οθόνης"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Κοινή χρήση μίας εφαρμογής"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Κοινή χρήση ολόκληρης της οθόνης"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Όταν μοιράζεστε ολόκληρη την οθόνη, οτιδήποτε εμφανίζεται στην οθόνη σας είναι ορατό στην εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Όταν μοιράζεστε μια εφαρμογή, οτιδήποτε εμφανίζεται ή αναπαράγεται σε αυτή την εφαρμογή, είναι ορατό στην εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Κοινή χρήση οθόνης"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Εικονίδιο σύμπτυξης"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Εικονίδιο ανάπτυξης"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ή"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Κίνηση επιστροφής"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Κίνηση μετάβασης στην αρχική οθόνη"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Πλήκτρο ενέργειας"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index bab9a50..cb9dfe5 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Include link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Screen recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Screen saver"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Do Not Disturb"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Priority modes"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No paired devices available"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tap to connect or disconnect a device"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio sharing"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tap to switch or share audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Open settings"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Share or record an app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Share one app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Share entire screen"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you\'re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you\'re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 67ce124..3d4c31f 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Include link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Screen Recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -291,7 +292,7 @@
     <string name="start_dreams" msgid="9131802557946276718">"Screen saver"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Do Not Disturb"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Priority modes"</string>
+    <string name="quick_settings_modes_label" msgid="879156359479504244">"Modes"</string>
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No paired devices available"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tap to connect or disconnect a device"</string>
@@ -300,8 +301,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio Sharing"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tap to switch or share audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
@@ -433,7 +433,7 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Open Settings"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string>
+    <string name="zen_modes_dialog_title" msgid="8854640808100096934">"Modes"</string>
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
@@ -534,8 +534,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Share or record an app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Share one app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Share entire screen"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you’re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you’re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string>
@@ -1387,6 +1391,12 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string>
+    <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"Navigate using your keyboard"</string>
+    <string name="launch_keyboard_tutorial_notification_content" msgid="2880339951512757918">"Learn keyboards shortcuts"</string>
+    <string name="launch_touchpad_tutorial_notification_title" msgid="2243780062772196901">"Navigate using your touchpad"</string>
+    <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Learn touchpad gestures"</string>
+    <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigate using your keyboard and touchpad"</string>
+    <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Learn touchpad gestures, keyboards shortcuts, and more"</string>
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index bab9a50..cb9dfe5 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Include link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Screen recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Screen saver"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Do Not Disturb"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Priority modes"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No paired devices available"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tap to connect or disconnect a device"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio sharing"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tap to switch or share audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Open settings"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Share or record an app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Share one app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Share entire screen"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you\'re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you\'re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index bab9a50..cb9dfe5 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Include link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Screen recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Screen saver"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Do Not Disturb"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Priority modes"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No paired devices available"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tap to connect or disconnect a device"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio sharing"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tap to switch or share audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Open settings"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Share or record an app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Share one app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Share entire screen"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you\'re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you\'re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 4317f86..eb94d59 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="APPNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and other open apps detected this screenshot.‎‏‎‎‏‎"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‏‎Add to note‎‏‎‎‏‎"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎Include link‎‏‎‎‏‎"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="APPNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎<xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‎‎Screen Recorder‎‏‎‎‏‎"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‎‎Processing screen recording‎‏‎‎‏‎"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‎‎‎‎‏‏‎‎‎‏‏‏‏‎‏‏‏‏‎Ongoing notification for a screen record session‎‏‎‎‏‎"</string>
@@ -291,7 +292,7 @@
     <string name="start_dreams" msgid="9131802557946276718">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎‏‏‎‏‏‎‏‏‏‎‎Screen saver‎‏‎‎‏‎"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎Ethernet‎‏‎‎‏‎"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‏‏‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎Do Not Disturb‎‏‎‎‏‎"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‏‎Priority modes‎‏‎‎‏‎"</string>
+    <string name="quick_settings_modes_label" msgid="879156359479504244">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‏‏‎‏‎‎‎Modes‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‏‏‏‎‎‎‏‎‎‏‎Bluetooth‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‎‎‏‎‎‏‎‎No paired devices available‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‏‎‎‎‏‎‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‏‎‎Tap to connect or disconnect a device‎‏‎‎‏‎"</string>
@@ -300,8 +301,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎Use Bluetooth‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎Connected‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‎‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‏‎‎Audio Sharing‎‏‎‎‏‎"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎Tap to switch or share audio‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‎‏‏‎‎‏‎‏‎Saved‎‏‎‎‏‎"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‏‏‏‎‎disconnect‎‏‎‎‏‎"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‎activate‎‏‎‎‏‎"</string>
@@ -433,7 +433,7 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎Open Settings‎‏‎‎‏‎"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‎‎‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎Other device‎‏‎‎‏‎"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‎‎‎‏‏‏‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‎‎‎‏‏‎Toggle Overview‎‏‎‎‏‎"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎Priority modes‎‏‎‎‏‎"</string>
+    <string name="zen_modes_dialog_title" msgid="8854640808100096934">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎Modes‎‏‎‎‏‎"</string>
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‎Done‎‏‎‎‏‎"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‎‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎Settings‎‏‎‎‏‎"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‏‎‏‏‎‎‏‏‏‎‎‏‎‏‎‎‎‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‏‎‎‏‏‏‏‏‎On‎‏‎‎‏‎"</string>
@@ -534,8 +534,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‎‎The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.‎‏‎‎‏‎"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎Share or record an app‎‏‎‎‏‎"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‎Share your screen with ‎‏‎‎‏‏‎<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‎‏‏‏‎‏‎‎‏‎‎‏‏‎‏‏‎‏‎‎‎Share one app‎‏‎‎‏‎"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‎Share entire screen‎‏‎‎‏‎"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‎Share one app‎‏‎‎‏‎"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‎‏‏‏‎‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‎Share entire screen‎‏‎‎‏‎"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎When you’re sharing your entire screen, anything on your screen is visible to ‎‏‎‎‏‏‎<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‎‏‎‎‏‏‏‎. So be careful with things like passwords, payment details, messages, photos, and audio and video.‎‏‎‎‏‎"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎When you’re sharing an app, anything shown or played in that app is visible to ‎‏‎‎‏‏‎<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‎‏‎‎‏‏‏‎. So be careful with things like passwords, payment details, messages, photos, and audio and video.‎‏‎‎‏‎"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎‎‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‎‏‎‏‏‎Share screen‎‏‎‎‏‎"</string>
@@ -1387,6 +1391,12 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎Collapse icon‎‏‎‎‏‎"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‏‏‎‎‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‎‎Expand icon‎‏‎‎‏‎"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‎‎or‎‏‎‎‏‎"</string>
+    <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎Navigate using your keyboard‎‏‎‎‏‎"</string>
+    <string name="launch_keyboard_tutorial_notification_content" msgid="2880339951512757918">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‎‎‏‏‏‏‎‎Learn keyboards shortcuts‎‏‎‎‏‎"</string>
+    <string name="launch_touchpad_tutorial_notification_title" msgid="2243780062772196901">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‎‎‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‏‎Navigate using your touchpad‎‏‎‎‏‎"</string>
+    <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‏‏‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‎Learn touchpad gestures‎‏‎‎‏‎"</string>
+    <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎Navigate using your keyboard and touchpad‎‏‎‎‏‎"</string>
+    <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‎‎‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‎‏‎Learn touchpad gestures, keyboards shortcuts, and more‎‏‎‎‏‎"</string>
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‏‏‎‏‎‎Back gesture‎‏‎‎‏‎"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎Home gesture‎‏‎‎‏‎"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‎‏‏‎Action key‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index b9cfbaa..2af8bd1 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> y otras apps en ejecución detectaron que tomaste una captura de pantalla."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Agregar a la nota"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Incluir vínculo"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Grabadora de pantalla"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación constante para una sesión de grabación de pantalla"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Protector pantalla"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"No interrumpir"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modos prioritarios"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No hay dispositivos sincronizados disponibles"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Presiona para conectar o desconectar un dispositivo"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Uso compartido de audio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Presiona para cambiar o compartir el audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Abrir Configuración"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Otro dispositivo"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Ocultar o mostrar Recientes"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritarios"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Listo"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuración"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"El servicio que brinda esta función tendrá acceso a toda la información que sea visible en la pantalla o que reproduzcas en el dispositivo durante una grabación o transmisión. Se incluyen contraseñas, detalles de pagos, fotos, mensajes y audio que reproduzcas."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Comparte o graba una app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"¿Quieres compartir pantalla con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartir una app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartir pantalla completa"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Compartir una app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Compartir pantalla completa"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Cuando compartes la pantalla completa, todo lo que se muestre es visible en <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Cuando compartes una app, todo lo que se muestre o reproduzca en ella será visible en <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartir pantalla"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícono de contraer"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícono de expandir"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto atrás"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto para ir a la pantalla principal"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de acción"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index b392959..2e823ed 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> y otras aplicaciones abiertas han detectado esta captura de pantalla."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Añadir a nota"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Incluir enlace"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Grabación de pantalla"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación de pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación continua de una sesión de grabación de la pantalla"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Salvapantallas"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"No molestar"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modos prioritarios"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No hay dispositivos vinculados disponibles"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toca para conectar o desconectar un dispositivo"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartir audio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Toca para cambiar o compartir el audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Abrir Ajustes"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Otro dispositivo"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Mostrar u ocultar aplicaciones recientes"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritarios"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hecho"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ajustes"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"El servicio que ofrece esta función tendrá acceso a toda la información que se muestre en la pantalla o se reproduzca en el dispositivo mientras grabas o envías contenido, incluidos contraseñas, detalles de pagos, fotos, mensajes y audio que reproduzcas."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Compartir o grabar una aplicación"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"¿Compartir tu pantalla con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartir una aplicación"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartir toda la pantalla"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Compartir una aplicación"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Compartir toda la pantalla"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Cuando compartes toda tu pantalla, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede ver todo lo que hay en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Cuando compartes una aplicación, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede ver todo lo que se muestra o reproduce en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartir pantalla"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icono de contraer"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icono de desplegar"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto para volver"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto para ir al inicio"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de acción"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index c56d101..09f461f 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ja muud avatud rakendused tuvastasid selle ekraanipildi."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Lisa märkmesse"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Kaasa link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Ekraanisalvesti"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekraanisalvestuse töötlemine"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pooleli märguanne ekraanikuva salvestamise seansi puhul"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Ekraanisäästja"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Mitte segada"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioriteetsed režiimid"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Ühtegi seotud seadet pole saadaval"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Puudutage seadme ühendamiseks või ühenduse katkestamiseks"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Kasuta Bluetoothi"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ühendatud"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Heli jagamine"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Puudutage helile lülitumiseks või selle jagamiseks"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvestatud"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"katkesta ühendus"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiveeri"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Ava menüü Seaded"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Muu seade"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Lehe Ülevaade sisse- ja väljalülitamine"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteetsed režiimid"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Valmis"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Seaded"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Sees"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Seda funktsiooni pakkuv teenus saab juurdepääsu kogu teabele, mis on teie ekraanikuval nähtav või mida seadmes salvestamise või ülekande ajal esitatakse. See hõlmab teavet, nagu paroolid, maksete üksikasjad, fotod, sõnumid ja esitatav heli."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Rakenduse jagamine või salvestamine"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Kas jagada teie ekraani rakendusega <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Jaga üht rakendust"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Jaga kogu ekraani"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Jaga ühte rakendust"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Jaga kogu ekraani"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kogu ekraanikuva jagamisel on kogu sellel kuvatav sisu nähtav rakendusele <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Rakenduse jagamisel on kogu rakenduses kuvatav või esitatav sisu nähtav rakendusele <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Jaga ekraani"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ahendamisikoon"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Laiendamisikoon"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"või"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Tagasiliikumisliigutus"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Avakuvale liikumise liigutus"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Toiminguklahv"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index ccebe2b..329b6e2 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> aplikazioak eta irekitako beste aplikazio batzuek pantaila-argazkia hauteman dute."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Gehitu oharrean"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Sartu esteka"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Pantaila-grabagailua"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pantaila-grabaketa prozesatzen"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pantailaren grabaketa-saioaren jakinarazpen jarraitua"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Pantaila-babeslea"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ez molestatzeko modua"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Lehentasunezko moduak"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetootha"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Ez dago parekatutako gailurik erabilgarri"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Sakatu hau gailu bat konektatu edo deskonektatzeko"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Erabili Bluetootha"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Konektatuta"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audioa partekatzea"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Audioa aldatu edo partekatzeko, sakatu hau"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gordeta"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"deskonektatu"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktibatu"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Ireki Ezarpenak"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Beste gailu bat"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aldatu ikuspegi orokorra"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Lehentasunezko moduak"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Eginda"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ezarpenak"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Aktibatuta"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Zerbait grabatzen edo igortzen duzunean, pantailan ikusgai dagoen edo gailuak erreproduzitzen duen informazio guztia erabili ahalko du funtzio hori eskaintzen duen zerbitzuak. Pasahitzak, ordainketen xehetasunak, argazkiak, mezuak eta erreproduzitzen dituzun audioak sartzen dira informazio horretan."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Partekatu edo grabatu aplikazio bat"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioarekin pantaila partekatu nahi duzu?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Partekatu aplikazio bat"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Partekatu pantaila osoa"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Aplikazio bat partekatu"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Pantaila osoa partekatu"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Pantaila osoa partekatzen ari zarenean, pantailan duzun guztia ikus dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Aplikazio bat partekatzen ari zarenean, aplikazio horretan agertzen den edo bertan erreproduzitzen ari den guztia ikusi dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Partekatu pantaila"</string>
@@ -1196,7 +1202,7 @@
     <string name="select_conversation_text" msgid="3376048251434956013">"Sakatu elkarrizketa bat orri nagusian gehitzeko"</string>
     <string name="no_conversations_text" msgid="5354115541282395015">"Azkenaldiko elkarrizketak agertuko dira hemen"</string>
     <string name="priority_conversations" msgid="3967482288896653039">"Lehentasunezko elkarrizketak"</string>
-    <string name="recent_conversations" msgid="8531874684782574622">"Azken elkarrizketak"</string>
+    <string name="recent_conversations" msgid="8531874684782574622">"Azkenaldiko elkarrizketak"</string>
     <string name="days_timestamp" msgid="5821854736213214331">"Duela <xliff:g id="DURATION">%1$s</xliff:g> egun"</string>
     <string name="one_week_timestamp" msgid="4925600765473875590">"Duela astebete"</string>
     <string name="two_weeks_timestamp" msgid="9111801081871962155">"Duela bi aste"</string>
@@ -1220,7 +1226,7 @@
     <string name="status_before_loading" msgid="1500477307859631381">"Laster agertuko da edukia"</string>
     <string name="missed_call" msgid="4228016077700161689">"Dei galdua"</string>
     <string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
-    <string name="people_tile_description" msgid="8154966188085545556">"Ikusi azken mezuak, dei galduak eta egoerei buruzko informazio eguneratua"</string>
+    <string name="people_tile_description" msgid="8154966188085545556">"Ikusi azkenaldiko mezuak, dei galduak eta egoerei buruzko informazio eguneratua"</string>
     <string name="people_tile_title" msgid="6589377493334871272">"Elkarrizketa"</string>
     <string name="paused_by_dnd" msgid="7856941866433556428">"Ez molestatzeko moduak pausatu du"</string>
     <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzaileak mezu bat bidali du: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Tolesteko ikonoa"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Zabaltzeko ikonoa"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"edo"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Atzera egiteko keinua"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Orri nagusira joateko keinua"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Ekintza-tekla"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 7e622cf..f845027 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> و سایر برنامه‌های باز این نماگرفت را تشخیص دادند."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"افزودن به یادداشت"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"اضافه کردن پیوند"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"‫<xliff:g id="APPNAME">%1$s</xliff:g> ‏<xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"ضبط‌کن صفحه‌نمایش"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"درحال پردازش ضبط صفحه‌نمایش"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"اعلان درحال انجام برای جلسه ضبط صفحه‌نمایش"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"محافظ صفحه"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"اترنت"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"مزاحم نشوید"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"حالت‌های اولویت‌دار"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"بلوتوث"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"هیچ دستگاه مرتبط شده‌ای موجود نیست"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"برای اتصال یا قطع اتصال دستگاه، تک‌ضرب بزنید"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"استفاده از بلوتوث"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"متصل"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"اشتراک صدا"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"برای فعال کردن و هم‌رسانی صدا، تک‌ضرب بزنید"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ذخیره‌شده"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"قطع اتصال"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"فعال کردن"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"باز کردن تنظیمات"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"دستگاه دیگر"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تغییر وضعیت نمای کلی"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"حالت‌های اولویت‌دار"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"تمام"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"تنظیمات"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"روشن"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"سرویس ارائه‌دهنده این عملکرد به همه اطلاعاتی که روی صفحه‌نمایش قابل‌مشاهد است و هنگام ضبط کردن یا پخش محتوا از دستگاهتان پخش می‌شود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژه‌ها، جزئیات پرداخت، عکس‌ها، پیام‌ها، و صداهایی که پخش می‌کنید می‌شود."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"هم‌رسانی یا ضبط برنامه"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"صفحه‌نمایش با <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> هم‌رسانی شود؟"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"هم‌رسانی یک برنامه"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"هم‌رسانی کل صفحه‌نمایش"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"هم‌رسانی کردن یک برنامه"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"هم‌رسانی کردن کل صفحه‌نمایش"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"وقتی کل صفحه‌نمایش را هم‌رسانی می‌کنید، هر چیزی که روی صفحه‌نمایش شما وجود داشته باشد برای <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> قابل‌مشاهده خواهد بود. درنتیجه مراقب چیزهایی مثل گذرواژه‌ها، جزئیات پرداخت، پیام‌ها، عکس‌ها، و صدا و تصویر باشید."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"وقتی برنامه‌ای را هم‌رسانی می‌کنید، هر چیزی که در آن برنامه نمایش داده شود یا پخش شود برای <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> قابل‌مشاهده خواهد بود. درنتیجه مراقب چیزهایی مثل گذرواژه‌ها، جزئیات پرداخت، پیام‌ها، عکس‌ها، و صدا و تصویر باشید."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"هم‌رسانی صفحه‌نمایش"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"نماد جمع کردن"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"نماد ازهم بازکردن"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"یا"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"اشاره برگشت"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"اشاره صفحه اصلی"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"دکمه کنش"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4d7f41a3..b9afcd5 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ja jotkin muut sovellukset havaitsivat tämän kuvakaappauksen."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Lisää muistiinpanoon"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Lisää linkki"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Näytön tallentaja"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Näytön tallennusta käsitellään"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pysyvä ilmoitus näytön tallentamisesta"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Näytönsäästäjä"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Älä häiritse"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioriteettitilat"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Laitepareja ei ole käytettävissä"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Muodosta yhteys laitteeseen tai katkaise yhteys napauttamalla"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Käytä Bluetoothia"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Yhdistetty"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audionjako"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Vaihda tai jaa audiota napauttamalla"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Tallennettu"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"katkaise yhteys"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivoi"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Avaa Asetukset"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Muu laite"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Näytä/piilota viimeisimmät"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteettitilat"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Valmis"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Asetukset"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Päällä"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Ominaisuuden tarjoavalla palvelulla on pääsy kaikkiin näytölläsi näkyviin tietoihin ja tietoihin laitteesi toistamasta sisällöstä tallennuksen tai striimauksen aikana. Näitä tietoja ovat esimerkiksi salasanat, maksutiedot, kuvat, viestit ja toistettava audiosisältö."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Jaa sovellus tai tallenna sen sisältöä"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Saako <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> nähdä näyttösi?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Jaa yksi sovellus"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Jaa koko näyttö"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Jaa yksi sovellus"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Jaa koko näyttö"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kun jaat koko näytön, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> näkee kaiken sen sisälllön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kun jaat sovelluksen, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> näkee kaiken sovelluksessa näkyvän tai toistetun sisällön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Jaa näyttö"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Tiivistyskuvake"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Laajennuskuvake"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"tai"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Takaisin-ele"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Etusivu-ele"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Toimintonäppäin"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 51dc60f..07e131e 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> et d\'autres applis ouvertes ont détecté cette capture d\'écran."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ajouter à une note"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Inclure le lien"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Enregistreur d\'écran"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Trait. de l\'enregist. d\'écran…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement d\'écran"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Écran de veille"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne pas déranger"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modes prioritaires"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Aucun des appareils associés n\'est disponible"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Touchez pour connecter ou déconnecter un appareil"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Utiliser le Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connecté"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Partage audio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Touchez pour passer d\'un appareil à l\'autre ou pour partager le contenu audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Enregistré"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"Déconnecter"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"Activer"</string>
@@ -309,7 +310,7 @@
     <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Les fonctionnalités comme Partage rapide et Localiser mon appareil utilisent le Bluetooth"</string>
     <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Le Bluetooth s\'activera demain matin"</string>
     <string name="quick_settings_bluetooth_audio_sharing_button" msgid="7545274861795853838">"Partager l\'audio"</string>
-    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="3069309588231072128">"Partage de l\'audio en cours…"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="3069309588231072128">"Partage de l\'audio en cours"</string>
     <string name="quick_settings_bluetooth_audio_sharing_button_accessibility" msgid="7604615019302091708">"entrer les paramètres de partage audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Ouvrir les paramètres"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Autre appareil"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Basculer l\'aperçu"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modes prioritaires"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"OK"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Paramètres"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Activé"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Le service offrant cette fonction aura accès à toute l\'information qui est visible sur votre écran ou lu sur votre appareil pendant que vous enregistrez ou diffusez. Cela comprend des renseignements comme les mots de passe, les détails du paiement, les photos, les messages et le contenu audio que vous faites jouer."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Partager ou enregistrer une appli"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Partager votre écran avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Partager une appli"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Partager l\'intégralité de l\'écran"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Partager une appli"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Partager l\'intégralité de l\'écran"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Lorsque vous partagez l\'intégralité de votre écran, tout ce qui s\'y trouve est visible par <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Par conséquent, soyez prudent avec les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Lorsque vous partagez une appli, tout ce qui s\'y affiche ou s\'y joue est visible par <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Par conséquent, soyez prudent avec les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Partager l\'écran"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icône Réduire"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icône Développer"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Geste de retour"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Geste d\'accès à l\'écran d\'accueil"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Touche d\'action"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index bd6c664..9d3bbd7 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> et d\'autres applis ouvertes ont détecté cette capture d\'écran."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ajouter à la note"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Inclure le lien"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Enregistreur d\'écran"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Enregistrement de l\'écran…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement de l\'écran"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Économiseur d\'écran"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne pas déranger"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modes prioritaires"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Aucun appareil associé disponible."</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Appuyez pour connecter ou déconnecter un appareil"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Utiliser le Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connecté"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Partage audio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Appuyez pour activer ou partager l\'audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Enregistré"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"dissocier"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activer"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Ouvrir les paramètres"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Autre appareil"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activer/Désactiver l\'écran Récents"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modes prioritaires"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"OK"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Paramètres"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Activé"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Le service qui fournit cette fonction aura accès à toutes les infos visibles sur votre écran ou lues depuis votre appareil pendant un enregistrement ou une diffusion de contenu. Il peut s\'agir de mots de passe, détails de mode de paiement, photos, messages ou encore contenus audio lus."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Partager ou enregistrer une appli"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Partager votre écran avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Partager une appli"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Partager tout l\'écran"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Partager une appli"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Partager tout l\'écran"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Lorsque vous partagez tout votre écran, l\'ensemble de son contenu est visible par <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Faites donc attention aux éléments tels que les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Lorsque vous partagez une appli, tout ce qui est affiché ou lu dans celle-ci est visible par <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Faites donc attention aux éléments tels que les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Partager l\'écran"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icône Réduire"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icône Développer"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Geste Retour"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Geste Accueil"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Touche d\'action"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 81e96d6..6281570 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e outras aplicacións abertas detectaron esta captura de pantalla."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Engadir a unha nota"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Incluír ligazón"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Gravadora da pantalla"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando gravación pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación de actividade en curso sobre unha sesión de gravación de pantalla"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Protector pantalla"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Non molestar"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modos de prioridade"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Non hai dispositivos vinculados dispoñibles"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toca para conectar ou desconectar un dispositivo"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Estableceuse a conexión"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio compartido"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Toca para cambiar ou compartir o audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gardouse"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Abrir Configuración"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activar/desactivar Visión xeral"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos de prioridade"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Feito"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuración"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"O servizo que proporciona esta función terá acceso a toda a información visible na pantalla ou reproducida desde o teu dispositivo mentres graves ou emitas contido. Isto inclúe datos como contrasinais, detalles de pago, fotos, mensaxes e o audio que reproduzas."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Compartir ou gravar unha aplicación"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Queres compartir a pantalla con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartir unha aplicación"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartir toda a pantalla"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Compartir unha aplicación"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Compartir toda a pantalla"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Se compartes toda a pantalla, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> poderá ver todo o contido que apareza nela. Ten coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como co contido de audio e de vídeo."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Se compartes toda a pantalla, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> poderá ver todo o contido que apareza ou se reproduza nesa aplicación. Ten coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como co contido de audio e de vídeo."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartir pantalla"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icona de contraer"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icona de despregar"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Xesto para volver"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Xesto para ir ao inicio"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de acción"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index ffa8554..2be88f2 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> અને કામ કરતી અન્ય ઍપ દ્વારા આ સ્ક્રીનશૉટ લેવાયાની ભાળ મેળવવામાં આવી."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"નોંધમાં ઉમેરો"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"લિંક શામેલ કરો"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"સ્ક્રીન રેકોર્ડર"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"સ્ક્રીન રેકૉર્ડિંગ ચાલુ છે"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"સ્ક્રીન રેકોર્ડિંગ સત્ર માટે ચાલુ નોટિફિકેશન"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"સ્ક્રીન સેવર"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ઇથરનેટ"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"ખલેલ પાડશો નહીં"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"પ્રાધાન્યતાના મોડ"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"બ્લૂટૂથ"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"કોઈ જોડી કરેલ ઉપકરણો ઉપલબ્ધ નથી"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"કોઈ ડિવાઇસ કનેક્ટ કરવા કે ડિસ્કનેક્ટ કરવા માટે ટૅપ કરો"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"બ્લૂટૂથનો ઉપયોગ કરો"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"કનેક્ટેડ છે"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ઑડિયો શેરિંગ"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ઑડિયો પર સ્વિચ કરવા કે તેને શેર કરવા માટે બે વાર ટૅપ કરો"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"સાચવેલું"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ડિસ્કનેક્ટ કરો"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"સક્રિય કરો"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"સેટિંગ ખોલો"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"અન્ય ડિવાઇસ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ઝલકને ટૉગલ કરો"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"પ્રાધાન્યતાના મોડ"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"થઈ ગયું"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"સેટિંગ"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"ચાલુ"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"રેકોર્ડ અથવા કાસ્ટ કરતી વખતે, આ સુવિધા આપતી સેવાને તમારી સ્ક્રીન પર દેખાતી હોય અથવા તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય તેવી બધી માહિતીનો ઍક્સેસ હશે. જેમાં પાસવર્ડ, ચુકવણીની વિગતો, ફોટા, મેસેજ અને તમે વગાડો છો તે ઑડિયો જેવી માહિતીનો સમાવેશ થાય છે."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"કોઈ ઍપ શેર કરો અથવા રેકોર્ડ કરો"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> સાથે તમારી સ્ક્રીન શેર કરીએ?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"એક ઍપ શેર કરો"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"સંપૂર્ણ સ્ક્રીન શેર કરો"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"કોઈ ઍપ શેર કરો"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"સંપૂર્ણ સ્ક્રીન શેર કરો"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"જ્યારે તમે તમારી સંપૂર્ણ સ્ક્રીનને શેર કરી રહ્યાં હો, ત્યારે તમારી સ્ક્રીન પરની કોઈપણ વસ્તુ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ને દેખાય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"જ્યારે તમે કોઈ ઍપને શેર કરી રહ્યાં હો, ત્યારે તે ઍપ પર બતાવવામાં કે ચલાવવામાં આવતી હોય તેવી બધી વસ્તુ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ને દેખાય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"સ્ક્રીન શેર કરો"</string>
@@ -1223,7 +1229,7 @@
     <string name="people_tile_description" msgid="8154966188085545556">"તાજેતરના મેસેજ, ચૂકી ગયેલા કૉલ અને સ્ટેટસ અપડેટ જુઓ"</string>
     <string name="people_tile_title" msgid="6589377493334871272">"વાતચીત"</string>
     <string name="paused_by_dnd" msgid="7856941866433556428">"\'ખલેલ પાડશો નહીં\'ની સુવિધા દ્વારા થોભાવેલું"</string>
-    <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કોઈ સંદેશ મોકલવામાં આવ્યો: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
+    <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કોઈ મેસેજ મોકલવામાં આવ્યો: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
     <string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કોઈ છબી મોકલવામાં આવી"</string>
     <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા નવી સ્ટેટસ અપડેટ પોસ્ટ કરવામાં આવી: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
     <string name="person_available" msgid="2318599327472755472">"ઉપલબ્ધ છે"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"\'નાનું કરો\'નું આઇકન"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"\'મોટું કરો\'નું આઇકન"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"અથવા"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"પાછળ જવાનો સંકેત"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"હોમ સ્ક્રીન પર જવાનો સંકેત"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ઍક્શન કી"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index b56b30c..7c267bf 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> और खुले हुए अन्य ऐप्लिकेशन को इस स्क्रीनशॉट का पता चला है."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"नोट में जोड़ें"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"लिंक जोड़ें"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"स्क्रीन रिकॉर्डर"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रिकॉर्डिंग को प्रोसेस किया जा रहा है"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रिकॉर्ड सेशन के लिए जारी सूचना"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"स्क्रीन सेवर"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ईथरनेट"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"परेशान न करें"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"अहम मोड"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ब्लूटूथ"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"कोई भी युग्मित डिवाइस उपलब्ध नहीं"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"किसी डिवाइस को कनेक्ट या डिसकनेक्ट करने के लिए टैप करें"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ब्लूटूथ इस्तेमाल करें"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"कनेक्ट है"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ऑडियो शेयर करने की सुविधा"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ऑडियो को स्विच या शेयर करने के लिए टैप करें"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेव किया गया"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिसकनेक्ट करें"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"चालू करें"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"सेटिंग खोलें"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"अन्य डिवाइस"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"खास जानकारी टॉगल करें"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"अहम मोड"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"हो गया"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिंग"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"चालू है"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"रिकॉर्ड या कास्ट करते समय, इस सुविधा को उपलब्ध कराने वाली सेवा के पास आपकी स्क्रीन पर दिख रही जानकारी या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. जैसे, पासवर्ड, पेमेंट के तरीके की जानकारी, फ़ोटो, मैसेज, और डिवाइस पर चल रहा ऑडियो."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ऐप्लिकेशन शेयर करें या उसकी रिकॉर्डिंग करें"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"क्या आपको <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> पर अपनी स्क्रीन शेयर करनी है?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"एक ऐप्लिकेशन शेयर करें"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"पूरी स्क्रीन शेयर करें"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"एक ऐप्लिकेशन शेयर करें"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"पूरी स्क्रीन शेयर करें"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"जब पूरी स्क्रीन शेयर की जाती है, तो आपकी स्क्रीन पर दिख रहा पूरा कॉन्टेंट <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> पर दिखता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, ऑडियो, और वीडियो को लेकर सावधानी बरतें."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"जब कोई ऐप्लिकेशन शेयर किया जाता है, तो उस ऐप्लिकेशन में दिख रहा या चलाया जा रहा पूरा कॉन्टेंट <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> पर दिखता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, ऑडियो, और वीडियो को लेकर सावधानी बरतें."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"स्क्रीन शेयर करें"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"छोटा करने का आइकॉन"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"बड़ा करने का आइकॉन"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"या"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"पीछे जाने का जेस्चर"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"होम स्क्रीन पर जाने का जेस्चर"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ऐक्शन बटन"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index e1b2df2..bdf6e13 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> i druge otvorene aplikacije otkrile su ovu snimku zaslona."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj bilješci"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Uključi vezu"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Snimač zaslona"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrada snimanja zaslona"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Tekuća obavijest za sesiju snimanja zaslona"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Čuvar zaslona"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne uznemiravaj"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritetni načini"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Upareni uređaji nisu dostupni"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Dodirnite da biste povezali uređaj ili prekinuli vezu s njim"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Koristi Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Zajedničko slušanje"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Dodirnite za prebacivanje ili dijeljenje zvuka"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Spremljeno"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekini vezu"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviraj"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Otvori postavke"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Ostali uređaji"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Uključivanje/isključivanje pregleda"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetni načini"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotovo"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Postavke"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Usluga koja pruža ovu funkciju imat će pristup svim podacima koji su vidljivi na vašem zaslonu ili koji se reproduciraju s vašeg uređaja tijekom snimanja ili emitiranja. To uključuje podatke kao što su zaporke, podaci o plaćanju, fotografije, poruke i audiozapisi koje reproducirate."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Dijeljenje ili snimanje pomoću aplikacije"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Želite li dijeliti zaslon s aplikacijom <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Dijeljenje jedne aplikacije"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Dijeljenje cijelog zaslona"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Dijeljenje jedne aplikacije"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Dijeljenje cijelog zaslona"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kada dijelite cijeli zaslon, sve na zaslonu bit će vidljivo aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kada dijelite aplikaciju, sve što se prikazuje ili reproducira u toj aplikaciji bit će vidljivo aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Dijeljenje zaslona"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona za sažimanje"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona za proširivanje"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ili"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Pokret za povratak"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pokret za otvaranje početnog zaslona"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tipka za radnju"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index f4d34fcc..773d9ba 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> és más nyitott alkalmazások észlelték ezt a képernyőképet."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Hozzáadás jegyzethez"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Linkkel együtt"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Képernyőrögzítő"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Képernyőrögzítés feldolgozása"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Folyamatban lévő értesítés képernyőrögzítési munkamenethez"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Képernyővédő"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne zavarjanak"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritási módok"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nem áll rendelkezésre párosított eszköz"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Koppintson egy eszköz csatlakoztatásához vagy leválasztásához"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth használata"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Csatlakozva"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Hang megosztása"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Koppintással átkapcsolhatja vagy megoszthatja a hangot"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Mentve"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"leválasztás"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiválás"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Beállítások megnyitása"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Más eszköz"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Áttekintés be- és kikapcsolása"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritási módok"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Kész"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Beállítások"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Be"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"A funkciót biztosító szolgáltatás hozzáfér majd minden olyan információhoz, amely látható az Ön képernyőjén, illetve amelyet az Ön eszközéről játszanak le rögzítés vagy átküldés közben. Ez olyan információkat is tartalmaz, mint a jelszavak, a fizetési részletek, a fotók, az üzenetek és a lejátszott audiotartalmak."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Alkalmazás megosztása vagy rögzítése"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Megosztja a képernyőjét a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> alkalmazással?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Egyetlen alkalmazás megosztása"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"A teljes képernyő megosztása"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Egyetlen alkalmazás megosztása"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"A teljes képernyő megosztása"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"A teljes képernyő megosztása esetén a képernyő teljes tartalma látható lesz a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> számára. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Alkalmazás megosztása közben az adott appban megjelenített vagy lejátszott minden tartalom látható a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> számára. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Képernyő megosztása"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Összecsukás ikon"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Kibontás ikon"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"vagy"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Vissza kézmozdulat"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Kezdőképernyő kézmozdulat"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Műveletbillentyű"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 3b7855b..6a64c5d 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g>-ն ու բացված այլ հավելվածներ հայտնաբերել են այս սքրինշոթը։"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ավելացնել նշմանը"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Ներառել հղումը"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Էկրանի տեսագրում"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Էկրանի տեսագրության մշակում"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Էկրանի տեսագրման աշխատաշրջանի ընթացիկ ծանուցում"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Էկրանապահ"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Չանհանգստացնել"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Կարևոր ռեժիմներ"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Զուգակցված սարքեր չկան"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Հպեք՝ սարք միացնելու կամ անջատելու համար"</string>
@@ -300,15 +302,14 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Միացնել Bluetooth-ը"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Միացված է"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Աուդիոյի փոխանցում"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Հպեք՝ աուդիոն փոխանջատելու կամ դրանով կիսվելու համար"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Պահված է"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"անջատել"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ակտիվացնել"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="3345758139235739006">"Ավտոմատ միացնել վաղը"</string>
     <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Bluetooth-ն օգտագործում են, օրինակ, Quick Share և «Գտնել իմ սարքը» գործառույթները"</string>
     <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth-ը կմիանա վաղն առավոտյան"</string>
-    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="7545274861795853838">"Փոխանցել աուդիո"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="7545274861795853838">"Փոխանցել աուդիոն"</string>
     <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="3069309588231072128">"Աուդիոյի փոխանցում"</string>
     <string name="quick_settings_bluetooth_audio_sharing_button_accessibility" msgid="7604615019302091708">"անցնել աուդիոյի փոխանցման կարգավորումներ"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Բացել կարգավորումները"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Այլ սարք"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Միացնել/անջատել համատեսքը"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Կարևոր ռեժիմներ"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Պատրաստ է"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Կարգավորումներ"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Միացված է"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Տեսագրման և հեռարձակման ընթացքում ծառայությունների մատակարարին հասանելի կլինեն ձեր սարքի էկրանին ցուցադրվող տեղեկությունները և ձեր սարքով նվագարկվող նյութերը։ Սա ներառում է այնպիսի տեղեկություններ, ինչպիսիք են, օրինակ, գաղտնաբառերը, վճարային տվյալները, լուսանկարները, հաղորդագրությունները և նվագարկվող աուդիո ֆայլերը։"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Հավելվածի էկրանի ցուցադրում կամ տեսագրում"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ցուցադրե՞լ ձեր էկրանը <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածով"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Ցուցադրել մեկ հավելված"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Ցուցադրել ամբողջ էկրանը"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Ցուցադրել մեկ հավելված"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Ցուցադրել ամբողջ էկրանը"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Երբ ցուցադրում եք ամբողջ էկրանը, տեսանելի կլինի այն ամենը, ինչ ձեր էկրանին տեսանելի է <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Երբ դուք որևէ հավելված եք հեռարձակում, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին տեսանելի կլինի այն ամենը, ինչ ցուցադրվում կամ նվագարկվում է այդ հավելվածում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ցուցադրել էկրանը"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ծալել պատկերակը"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ծավալել պատկերակը"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"կամ"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"«Հետ» ժեստ"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Հիմնական էկրան անցնելու ժեստ"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Գործողության ստեղն"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 3ddd9f11..8c58012 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> dan aplikasi terbuka lainnya mendeteksi screenshot ini."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Tambahkan ke catatan"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Sertakan link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Perekam Layar"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses perekaman layar"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifikasi yang sedang berjalan untuk sesi rekaman layar"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Screensaver"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Jangan Ganggu"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Mode prioritas"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Perangkat yang disandingkan tak tersedia"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Ketuk untuk mulai atau berhenti menghubungkan perangkat"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Gunakan Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Terhubung"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Berbagi Audio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Ketuk untuk beralih atau berbagi audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Disimpan"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"berhenti hubungkan"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktifkan"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Buka Setelan"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Perangkat lainnya"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aktifkan Ringkasan"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Mode prioritas"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Selesai"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Setelan"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Aktif"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Layanan yang menyediakan fungsi ini akan memiliki akses ke semua informasi yang terlihat di layar atau diputar dari perangkat saat merekam atau melakukan transmisi. Ini mencakup informasi seperti sandi, detail pembayaran, foto, pesan, dan audio yang Anda putar."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Bagikan atau rekam aplikasi"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Bagikan layar dengan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Bagikan satu aplikasi"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Bagikan seluruh layar"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Bagikan satu aplikasi"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Bagikan seluruh layar"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"JIka Anda membagikan seluruh layar, semua hal yang ada di layar Anda akan terlihat oleh <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Jika Anda membagikan aplikasi, semua hal yang ditampilkan atau diputar di aplikasi tersebut akan terlihat oleh <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Bagikan layar"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikon ciutkan"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikon luaskan"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"atau"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gestur kembali"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gestur layar utama"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tombol tindakan"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 8c57ed1..6b3b6732 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> og önnur opin forrit greindu skjámyndina."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Bæta við glósu"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Hafa tengil með"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Skjáupptaka"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Vinnur úr skjáupptöku"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Áframhaldandi tilkynning fyrir skjáupptökulotu"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Skjávari"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ónáðið ekki"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Forgangsstillingar"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Engin pöruð tæki til staðar"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Ýttu til að tengja eða aftengja tæki"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Nota Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Tengt"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Hljóði deilt"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Ýttu til að skipta um eða deila hljóði"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Vistað"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"aftengja"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"virkja"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Opna stillingar"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Annað tæki"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kveikja/slökkva á yfirliti"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Forgangsstillingar"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Lokið"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Stillingar"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Kveikt"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Þjónustan sem býður upp á þennan eiginleika fær aðgang að öllum upplýsingum sem sjást á skjánum eða eru spilaðar í tækinu á meðan upptaka eða vörpun er í gangi, þar á meðal aðgangsorði, greiðsluupplýsingum, myndum, skilaboðum og hljóðefni sem þú spilar."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Deila eða taka upp forrit"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Deila skjánum með <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Deila einu forriti"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Deila öllum skjánum"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Deila einu forriti"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Deila öllum skjánum"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Þegar þú deilir öllum skjánum verður allt á skjánum sýnilegt <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og vídeó."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Þegar þú deilir forriti er allt sem sést eða er spilað í því forriti sýnilegt <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og vídeó."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Deila skjá"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Minnka tákn"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Stækka tákn"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"eða"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Bending til að fara til baka"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Bending til að fara á upphafsskjá"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Aðgerðalykill"</string>
diff --git a/packages/SystemUI/res/values-it-feminine/strings.xml b/packages/SystemUI/res/values-it-feminine/strings.xml
index 99b9361..e8dbc40 100644
--- a/packages/SystemUI/res/values-it-feminine/strings.xml
+++ b/packages/SystemUI/res/values-it-feminine/strings.xml
@@ -21,5 +21,4 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="zen_priority_introduction" msgid="3159291973383796646">"Non verrai disturbata da suoni e vibrazioni, ad eccezione di sveglie, promemoria, eventi, chiamate da contatti da te specificati ed elementi che hai scelto di continuare a riprodurre, inclusi video, musica e giochi."</string>
     <string name="zen_alarms_introduction" msgid="3987266042682300470">"Non verrai disturbata da suoni e vibrazioni, ad eccezione delle sveglie. Potrai comunque sentire qualunque cosa decidi di riprodurre, inclusi video, musica e giochi."</string>
-    <string name="empty_user_name" msgid="3389155775773578300">"Amiche"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it-masculine/strings.xml b/packages/SystemUI/res/values-it-masculine/strings.xml
index 5e78889..5a76304 100644
--- a/packages/SystemUI/res/values-it-masculine/strings.xml
+++ b/packages/SystemUI/res/values-it-masculine/strings.xml
@@ -21,5 +21,4 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="zen_priority_introduction" msgid="3159291973383796646">"Non verrai disturbato da suoni e vibrazioni, ad eccezione di sveglie, promemoria, eventi, chiamate da contatti da te specificati ed elementi che hai scelto di continuare a riprodurre, inclusi video, musica e giochi."</string>
     <string name="zen_alarms_introduction" msgid="3987266042682300470">"Non verrai disturbato da suoni e vibrazioni, ad eccezione delle sveglie. Potrai comunque sentire qualunque cosa decidi di riprodurre, inclusi video, musica e giochi."</string>
-    <string name="empty_user_name" msgid="3389155775773578300">"Amici"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it-neuter/strings.xml b/packages/SystemUI/res/values-it-neuter/strings.xml
index 0e1c227..09237f5 100644
--- a/packages/SystemUI/res/values-it-neuter/strings.xml
+++ b/packages/SystemUI/res/values-it-neuter/strings.xml
@@ -21,5 +21,4 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="zen_priority_introduction" msgid="3159291973383796646">"Non verrai disturbatə da suoni e vibrazioni, ad eccezione di sveglie, promemoria, eventi, chiamate da contatti da te specificati ed elementi che hai scelto di continuare a riprodurre, inclusi video, musica e giochi."</string>
     <string name="zen_alarms_introduction" msgid="3987266042682300470">"Non verrai disturbatə da suoni e vibrazioni, ad eccezione delle sveglie. Potrai comunque sentire qualunque cosa decidi di riprodurre, inclusi video, musica e giochi."</string>
-    <string name="empty_user_name" msgid="3389155775773578300">"Amicɜ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 559e529..958d67b 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e altre app aperte hanno rilevato questo screenshot."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Aggiungi alla nota"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Includi link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Registrazione dello schermo"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Elaborazione registrazione…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifica costante per una sessione di registrazione dello schermo"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Salvaschermo"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Non disturbare"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modalità priorità"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nessun dispositivo accoppiato disponibile"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tocca per connettere o disconnettere un dispositivo"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usa il Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Dispositivo connesso"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Condivisione audio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tocca per cambiare o condividere l\'audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Dispositivo salvato"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnetti"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"attiva"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Apri Impostazioni"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Altro dispositivo"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Attiva/disattiva la panoramica"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modalità priorità"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Fine"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Impostazioni"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Il servizio che offre questa funzione avrà accesso a tutte le informazioni visibili sul tuo schermo o riprodotte dal tuo dispositivo durante la registrazione o la trasmissione. Sono incluse informazioni quali password, dettagli sui pagamenti, foto, messaggi e audio riprodotto."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Condividi o registra un\'app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Condividere lo schermo con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Condividi un\'app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Condividi schermo intero"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Condividi un\'app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Condividi schermo intero"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quando condividi lo schermo intero, tutto ciò che è nella schermata è visibile a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Presta quindi attenzione a password, dati di pagamento, messaggi, foto, audio e video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quando condividi un\'app, tutto ciò che viene mostrato o riprodotto al suo interno è visibile a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Presta quindi attenzione a password, dati di pagamento, messaggi, foto, audio e video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Condividi schermo"</string>
@@ -1215,7 +1221,7 @@
     <string name="video_status" msgid="4548544654316843225">"Visione in corso"</string>
     <string name="audio_status" msgid="4237055636967709208">"Ascolto in corso"</string>
     <string name="game_status" msgid="1340694320630973259">"Gioco in corso"</string>
-    <string name="empty_user_name" msgid="3389155775773578300">"Persone amiche"</string>
+    <string name="empty_user_name" msgid="3389155775773578300">"Amico"</string>
     <string name="empty_status" msgid="5938893404951307749">"Chattiamo stasera."</string>
     <string name="status_before_loading" msgid="1500477307859631381">"I contenuti verranno mostrati a breve"</string>
     <string name="missed_call" msgid="4228016077700161689">"Chiamata persa"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icona Comprimi"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icona Espandi"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"oppure"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto Indietro"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto Home"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tasto azione"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 907f846..1161fa0 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"האפליקציה <xliff:g id="APPNAME">%1$s</xliff:g> ואפליקציות פתוחות נוספות זיהו את צילום המסך הזה."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"הוספה לפתק"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"הכנסת הקישור"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"מקליט המסך"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"מתבצע עיבוד של הקלטת מסך"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"התראה מתמשכת לסשן הקלטת מסך"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"שומר מסך"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"אתרנט"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"נא לא להפריע"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"מצבי עדיפות"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"אין מכשירים מותאמים זמינים"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"אפשר להקיש כדי להתחבר למכשיר או להתנתק ממנו"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"‏שימוש ב-Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"מחובר"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"שיתוף אודיו"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"צריך להקיש כדי להחליף מצב או לשתף אודיו"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"נשמר"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ניתוק"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"הפעלה"</string>
@@ -382,7 +383,7 @@
     <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="qs_record_issue_label" msgid="8166290137285529059">"תיעוד הבעיה"</string>
+    <string name="qs_record_issue_label" msgid="8166290137285529059">"תיעוד בעיה"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"קדימה"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"עצירה"</string>
     <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"דיווח על באג"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"פתיחת ההגדרות"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"מכשיר אחר"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"החלפת מצב של מסכים אחרונים"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"מצבי עדיפות"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"סיום"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"הגדרות"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"מצב מופעל"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"‏לשירות שמספק את הפונקציה הזו תהיה גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך בזמן הקלטה או הפעלת Cast – כולל פרטים כמו סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו שמושמע מהמכשיר."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"שיתוף או הקלטה של אפליקציה"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"לשתף את המסך שלך עם <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"שיתוף של אפליקציה אחת"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"שיתוף כל המסך"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"שיתוף של אפליקציה אחת"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"שיתוף כל המסך"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"כשמשתפים את כל המסך, כל מה שמופיע בו יהיה גלוי ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"כשמשתפים אפליקציה, כל מה שרואים או מפעילים בה יהיה גלוי ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"שיתוף המסך"</string>
@@ -720,8 +726,7 @@
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"לוויין, חיבור באיכות טובה"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"לוויין, יש חיבור זמין"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"תקשורת לוויינית למצב חירום"</string>
-    <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
-    <skip />
+    <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"‏שיחות חירום או SOS"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"פרופיל עבודה"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"מהנה בשביל חלק מהאנשים, אבל לא בשביל כולם"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"‏התכונה System UI Tuner מספקת לך דרכים נוספות להתאים אישית את ממשק המשתמש של Android. התכונות הניסיוניות האלה עשויות להשתנות, לא לעבוד כראוי או להיעלם בגרסאות עתידיות. יש להמשיך בזהירות."</string>
@@ -998,7 +1003,7 @@
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- תהיה לה אפשרות לקרוא מידע מאפליקציית <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="slice_permission_text_2" msgid="6758906940360746983">"- תהיה לה יכולת לנקוט פעולה בתוך <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="slice_permission_checkbox" msgid="4242888137592298523">"יש לאשר לאפליקציית <xliff:g id="APP">%1$s</xliff:g> להראות חלקים מכל אפליציה שהיא"</string>
-    <string name="slice_permission_allow" msgid="6340449521277951123">"אני רוצה לאשר"</string>
+    <string name="slice_permission_allow" msgid="6340449521277951123">"אישור"</string>
     <string name="slice_permission_deny" msgid="6870256451658176895">"אני לא מרשה"</string>
     <string name="auto_saver_title" msgid="6873691178754086596">"יש להקיש כדי לתזמן את מצב החיסכון בסוללה"</string>
     <string name="auto_saver_text" msgid="3214960308353838764">"מומלץ להפעיל את התכונה כשיש סבירות גבוהה שהסוללה תתרוקן"</string>
@@ -1388,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"סמל הכיווץ"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"סמל ההרחבה"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"או"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"תנועת חזרה"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"תנועת חזרה למסך הבית"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"מקש הפעולה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 54ba7b5..6436cdd 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> とその他の開いているアプリがこのスクリーンショットを検出しました。"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"メモに追加"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"リンクを含める"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"スクリーン レコーダー"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"画面の録画を処理しています"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"画面の録画セッション中の通知"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"スクリーン セーバー"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"イーサネット"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"サイレント モード"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"優先モード"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ペア設定されたデバイスがありません"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"タップしてデバイスを接続または接続解除します"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth を使用"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"接続しました"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音声の共有"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"タップして音声の切り替えや共有を行えます"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"保存済み"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"接続を解除"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"有効化"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"設定を開く"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"その他のデバイス"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"概要を切り替え"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"優先モード"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"完了"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"ON"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"この機能を提供するサービスは、録画中またはキャスト中に画面上に表示または再生される情報のすべてにアクセスできるようになります。これには、パスワード、お支払いの詳細、写真、メッセージ、音声などが含まれます。"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"アプリの共有または録画"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> と画面を共有しますか?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"1 つのアプリを共有"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"画面全体を共有"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"1 個のアプリを共有"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"画面全体を共有"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"画面全体を共有すると、画面に表示される内容が <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> にすべて公開されます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"アプリを共有すると、そのアプリで表示または再生される内容が <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> にすべて公開されます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"画面を共有"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"閉じるアイコン"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"開くアイコン"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"または"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"「戻る」ジェスチャー"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"「ホーム」ジェスチャー"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"アクションキー"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index bc0fa35..7d52760 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g>-მა და სხვა გახსნილმა აპებმა აღმოაჩინეს ეკრანის ეს ანაბეჭდი."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"დაამატეთ შენიშვნა"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"ბმულის დართვა"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"ეკრანის ჩამწერი"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ეკრანის ჩანაწერი მუშავდება"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"უწყვეტი შეტყობინება ეკრანის ჩაწერის სესიისთვის"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"ეკრანმზოგი"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ეთერნეტი"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"არ შემაწუხოთ"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"პრიორიტეტული რეჟიმები"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"დაწყვილებული მოწყობილობები მიუწვდომელია"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"შეეხეთ მოწყობილობის დასაკავშირებლად ან გასათიშად"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-ის გამოყენება"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"დაკავშირებული"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"აუდიოს გაზიარება"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"შეეხეთ აუდიოს გადასართავად ან გასაზიარებლად"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"შენახული"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"კავშირის გაწყვეტა"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"გააქტიურება"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"პარამეტრების გახსნა"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"სხვა მოწყობილობა"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"მიმოხილვის გადართვა"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"პრიორიტეტული რეჟიმები"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"მზადაა"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"პარამეტრები"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"ჩართული"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ამ ფუნქციის მომწოდებელ სერვისს ექნება წვდომა ყველა ინფორმაციაზე, რომელიც თქვენს ეკრანზე გამოჩნდება ან თქვენს მოწყობილობაზე დაიკვრება ჩაწერის ან ტრანსლირების განმავლობაში. აღნიშნული მოიცავს ისეთ ინფორმაციას, როგორიც არის პაროლები, გადახდის დეტალები, ფოტოები, შეტყობინებები და თქვენ მიერ დაკრული აუდიო."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"აპის გაზიარება ან ჩაწერა"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"გსურთ თქვენი ეკრანის <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-თან გაზიარება?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ერთი აპის გაზიარება"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"მთლიანი ეკრანის გაზიარება"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ერთი აპის გაზიარება"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"მთლიანი ეკრანის გაზიარება"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"მთლიანი ეკრანის გაზიარებისას <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ხედავს ყველაფერს, რაც თქვენს ეკრანზეა. ამიტომ სიფრთხილე გამოიჩინეთ ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"აპის გაზიარებისას <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ხედავს ყველაფერს, რაც ჩანს ან უკრავს ამ აპში. ამიტომ სიფრთხილე გამოიჩინეთ ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ეკრანის გაზიარება"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ხატულის ჩაკეცვა"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ხატულის გაფართოება"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ან"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"უკან დაბრუნების ჟესტი"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"მთავარ ეკრანზე გადასვლის ჟესტი"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"მოქმედების კლავიში"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index aa06784..7b32db1 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> және басқа да ашық қолданбалар осы скриншотты анықтады."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ескертпеге қосу"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Сілтеме қосу"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Экран жазғыш"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экран жазғыш бейнесін өңдеу"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды бейнеге жазудың ағымдағы хабарландыруы"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Скринсейвер"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Этернет"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Мазаламау"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Басымдық режимдері"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Жұптасқан құрылғылар жоқ"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Құрылғыны жалғау не ажырату үшін түртіңіз."</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-ты пайдалану"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Қосылды"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Аудио бөлісу"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Аудионы бөлісу немесе ауыстыру үшін түртіңіз."</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сақталды"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ажырату"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"іске қосу"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Параметрлерді ашу"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Басқа құрылғы"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Шолуды қосу/өшіру"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Басымдық режимдері"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Дайын"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Параметрлер"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Қосулы"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Осы функцияны ұсынатын қызмет экранда көрсетілетін немесе жазу не трансляциялау кезінде құрылғыда ойнатылған барлық ақпаратты пайдалана алады. Бұған құпия сөздер, төлем туралы мәліметтер, суреттер, хабарлар және ойнатылатын аудио сияқты ақпарат кіреді."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Қолданба экранын бөлісу не жазу"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Экранды <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасымен бөлісу керек пе?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Бір қолданбаны бөлісу"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Бүкіл экранды бөлісу"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Бір қолданбаны бөлісу"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Бүкіл экранды бөлісу"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Бүкіл экранды бөліскен кезде, ондағы барлық контент <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасында көрсетіледі. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды, фотосуреттерді және аудио мен бейнені ашқанда сақ болыңыз."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Қолданбаны бөліскен кезде, онда көрінетін не ойнатылатын барлық контент <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасында көрсетіледі. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды, фотосуреттерді және аудио мен бейнені ашқанда сақ болыңыз."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Экранды бөлісу"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Жию белгішесі"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Жаю белгішесі"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"немесе"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Артқа қайтару қимылы"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Негізгі бетке қайтару қимылы"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Әрекет пернесі"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index fd64db5..81664ca 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> និងកម្មវិធីដែលបើក​ផ្សេងទៀតបានរកឃើញ​រូបថតអេក្រង់នេះ។"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"បញ្ចូលទៅក្នុងកំណត់ចំណាំ"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"រួមបញ្ចូល​តំណ"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"មុខងារថត​វីដេអូអេក្រង់"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"កំពុង​ដំណើរការ​ការថតអេក្រង់"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ការជូនដំណឹង​ដែល​កំពុង​ដំណើរការ​សម្រាប់​រយៈពេលប្រើ​ការថត​សកម្មភាព​អេក្រង់"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"ធាតុរក្សាអេក្រង់"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"អ៊ីសឺរណិត"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"កុំ​រំខាន"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"មុខងារអាទិភាព"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ប៊្លូធូស"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"មិន​មាន​ឧបករណ៍​ផ្គូផ្គង​ដែល​អាច​ប្រើ​បាន"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ចុចដើម្បីភ្ជាប់ ឬផ្ដាច់ឧបករណ៍"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ប្រើប៊្លូធូស"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"បានភ្ជាប់"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ការស្ដាប់សំឡេងរួមគ្នា"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ចុចដើម្បីប្ដូរ ឬចែករំលែកសំឡេង"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"បាន​រក្សាទុក"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ផ្ដាច់"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"បើកដំណើរការ"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"បើកការកំណត់"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"ឧបករណ៍ផ្សេងទៀត"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"បិទ/បើក​ទិដ្ឋភាពរួម"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"មុខងារអាទិភាព"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"រួចរាល់"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ការកំណត់"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"បើក"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"សេវាកម្មដែលផ្ដល់មុខងារនេះ​នឹងមានសិទ្ធិ​ចូលប្រើ​ព័ត៌មាន​ទាំងអស់​ដែលអាច​មើលឃើញ​នៅលើ​អេក្រង់​របស់អ្នក ឬចាក់​ពីឧបករណ៍​របស់អ្នក នៅពេល​កំពុង​ថត ឬភ្ជាប់។ ព័ត៌មាន​នេះមាន​ដូចជា ពាក្យសម្ងាត់ ព័ត៌មាន​លម្អិត​អំពីការទូទាត់​ប្រាក់ រូបថត សារ និង​សំឡេង​ដែល​អ្នកចាក់​ជាដើម។"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ចែករំលែក ឬថតកម្មវិធី"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"បង្ហាញអេក្រង់របស់អ្នកជាមួយ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ឬ?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"បង្ហាញកម្មវិធី​មួយ"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"បង្ហាញអេក្រង់​ទាំង​មូល"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"បង្ហាញកម្មវិធី​មួយ"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"បង្ហាញអេក្រង់​ទាំង​មូល"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"នៅពេលអ្នកបង្ហាញអេក្រង់ទាំងមូលរបស់អ្នក <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> មើលឃើញអ្វីគ្រប់យ៉ាងនៅលើអេក្រង់របស់អ្នក។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"នៅពេលអ្នកបង្ហាញកម្មវិធីណាមួយ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> មើលឃើញអ្វីគ្រប់យ៉ាងដែលបង្ហាញ ឬចាក់ក្នុងកម្មវិធីនោះ។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"បង្ហាញ​អេក្រង់"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"រូបតំណាង \"បង្រួម\""</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"រូបតំណាង \"ពង្រីក\""</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ឬ"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ចលនាថយក្រោយ"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ចលនាទៅទំព័រដើម"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"គ្រាប់ចុចសកម្មភាព"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 94979b0..e1b119c 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -45,7 +45,7 @@
     <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ನಿಯಂತ್ರಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?\nಈ ಆ್ಯಪ್‌ಗೆ ರೆಕಾರ್ಡ್ ಅನುಮತಿಯನ್ನು ನೀಡಲಾಗಿಲ್ಲ, ಆದರೆ ಈ USB ಸಾಧನದ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಬಹುದು."</string>
     <string name="usb_accessory_confirm_prompt" msgid="5728408382798643421">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="6756649383432542382">"ಆಪ್‌ಗಳು USB ಪರಿಕರದಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುವುದಿಲ್ಲ. ಆ ಬಗ್ಗೆ <xliff:g id="URL">%1$s</xliff:g> ನಲ್ಲಿ ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
-    <string name="title_usb_accessory" msgid="1236358027511638648">"USB ಪರಿಕರ"</string>
+    <string name="title_usb_accessory" msgid="1236358027511638648">"USB ಆ್ಯಕ್ಸೆಸರಿ"</string>
     <string name="label_view" msgid="6815442985276363364">"ವೀಕ್ಷಿಸು"</string>
     <string name="always_use_device" msgid="210535878779644679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಸಂಪರ್ಕಗೊಂಡಾಗ ಯಾವಾಗಲೂ <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="always_use_accessory" msgid="1977225429341838444">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ಸಂಪರ್ಕಗೊಂಡಾಗ ಯಾವಾಗಲೂ <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ಹಾಗೂ ತೆರೆದಿರುವ ಇತರ ಆ್ಯಪ್‌ಗಳು ಈ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ಪತ್ತೆಹಚ್ಚಿವೆ."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ಟಿಪ್ಪಣಿಗೆ ಸೇರಿಸಿ"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"ಲಿಂಕ್ ಅನ್ನು ಸೇರಿಸಿ"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡರ್"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೆಶನ್‌ಗಾಗಿ ಚಾಲ್ತಿಯಲ್ಲಿರುವ ನೋಟಿಫಿಕೇಶನ್"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"ಸ್ಕ್ರೀನ್ ಸೇವರ್"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ಇಥರ್ನೆಟ್"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"ಆದ್ಯತೆಯ ಮೋಡ್‌ಗಳು"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ಬ್ಲೂಟೂತ್‌"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ಯಾವುದೇ ಜೋಡಿಸಲಾದ ಸಾಧನಗಳು ಲಭ್ಯವಿಲ್ಲ"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ಸಾಧನವನ್ನು ಕನೆಕ್ಟ್ ಅಥವಾ ಡಿಸ್‌ಕನೆಕ್ಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ಬ್ಲೂಟೂತ್ ಬಳಸಿ"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆ"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ಆಡಿಯೊವನ್ನು ಬದಲಾಯಿಸಲು ಅಥವಾ ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ಡಿಸ್‌ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"ಅನ್ಯ ಸಾಧನ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ಟಾಗಲ್ ನ ಅವಲೋಕನ"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ಆದ್ಯತೆಯ ಮೋಡ್‌ಗಳು"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ಮುಗಿದಿದೆ"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"ಆನ್ ಆಗಿದೆ"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ಈ ಕಾರ್ಯವನ್ನು ಒದಗಿಸುವ ಸೇವೆಗಳು, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಗೋಚರಿಸುವ ಅಥವಾ ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುವಾಗ ಅಥವಾ ಕ್ಯಾಸ್ಟ್ ಮಾಡುವಾಗ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡುವ ಎಲ್ಲಾ ಮಾಹಿತಿಗಳಿಗೆ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತವೆ. ಇದು ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಫೋಟೋಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ನೀವು ಪ್ಲೇ ಮಾಡುವ ಆಡಿಯೊದಂತಹ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ ಅಥವಾ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ ಅನ್ನು <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ನೊಂದಿಗೆ ಹಂಚಿಕೊಳ್ಳಬೇಕೇ?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ಒಂದು ಆ್ಯಪ್‌ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ಒಂದು ಆ್ಯಪ್‌ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ನಿಮ್ಮ ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್‌ ಅನ್ನು ನೀವು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿರುವ ಏನಾದರೂ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಗೆ ಗೋಚರಿಸುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಮತ್ತು ಆಡಿಯೋ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಬಗ್ಗೆ ಜಾಗರೂಕರಾಗಿರಿ."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್‌ನಲ್ಲಿ ತೋರಿಸಿರುವ ಅಥವಾ ಪ್ಲೇ ಮಾಡಿದ ಏನಾದರೂ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಗೆ ಗೋಚರಿಸುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಮತ್ತು ಆಡಿಯೋ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಬಗ್ಗೆ ಜಾಗರೂಕರಾಗಿರಿ."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ಸ್ಕ್ರೀನ್‌ ಹಂಚಿಕೊಳ್ಳಿ"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ಕುಗ್ಗಿಸುವ ಐಕಾನ್"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ವಿಸ್ತೃತಗೊಳಿಸುವ ಐಕಾನ್"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ಅಥವಾ"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ಹಿಂಬದಿ ಗೆಸ್ಚರ್"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ಹೋಮ್ ಗೆಸ್ಚರ್"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ಆ್ಯಕ್ಷನ್‌ ಕೀ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index e316ffd..27aa785 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> 및 기타 공개 앱에서 이 스크린샷을 감지했습니다."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"메모에 추가"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"링크 포함"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g><xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"화면 녹화"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"화면 녹화 처리 중"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"화면 녹화 세션에 관한 지속적인 알림"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"화면 보호기"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"이더넷"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"방해 금지 모드"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"우선순위 모드"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"블루투스"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"페어링된 기기가 없습니다"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"기기를 연결 또는 연결 해제하려면 탭하세요"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"블루투스 사용"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"연결됨"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"오디오 공유"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"오디오를 전환하거나 공유하려면 탭하세요"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"저장됨"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"연결 해제"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"실행"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"설정 열기"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"기타 기기"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"최근 사용 버튼 전환"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"우선순위 모드"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"완료"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"설정"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"사용"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"이 기능을 제공하는 서비스는 녹화 또는 전송 중에 화면에 표시되거나 기기에서 재생되는 모든 정보에 액세스할 수 있습니다. 여기에는 비밀번호, 결제 세부정보, 사진, 메시지, 사용자가 재생하는 오디오 등의 정보가 포함됩니다."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"앱 공유 또는 녹화"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"화면을 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 앱과 공유하시겠습니까?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"앱 하나 공유"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"전체 화면 공유"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"앱 하나 공유"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"전체 화면 공유"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"전체 화면을 공유하면 화면에 있는 모든 항목이 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에 표시됩니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"앱을 공유하면 앱에 표시되거나 앱에서 재생되는 모든 항목이 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에 표시됩니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"화면 공유"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"접기 아이콘"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"확장 아이콘"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"또는"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"뒤로 동작"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"홈 동작"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"작업 키"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index ec07794..306baa7 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> жана ачылып турган башка колдонмолор ушул скриншотту аныктады."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Кыска жазууга кошуу"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Шилтеме кошуу"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Экрандан видео жаздырып алуу"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экрандан жаздырылып алынган видео иштетилүүдө"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды жаздыруу сеансы боюнча учурдагы билдирме"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Көшөгө"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Тынчымды алба"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Маанилүүлүк режимдери"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Жупташкан түзмөктөр жок"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Түзмөктү туташтыруу же ажыратуу үчүн таптаңыз"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Иштетүү"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Туташты"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Чогуу угуу"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Аудиону которуштуруу же бөлүшүү үчүн таптаңыз"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сакталды"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ажыратуу"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"иштетүү"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Параметрлерди ачуу"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Башка түзмөк"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Назар режимин өчүрүү/күйгүзүү"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Маанилүүлүк режимдери"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Бүттү"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Параметрлер"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Күйүк"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Жаздырып же тышкы экранга чыгарып жатканда кызмат көрсөтүүчү экраныңыздагы бардык маалыматты же түзмөктө ойнотулуп жаткан нерселерди көрө алат. Буга сырсөздөр, төлөмдүн чоо-жайы, сүрөттөр, билдирүүлөр жана ойнотулган аудио кирет."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Колдонмону бөлүшүү же жаздыруу"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Экранды <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> менен бөлүшөсүзбү?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Бир колдонмону бөлүшүү"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Толук экранды бөлүшүү"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Бир колдонмону бөлүшүү"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Толук экранды бөлүшүү"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Бүтүндөй экранды бөлүшкөндө андагы бардык нерселер <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосуна көрүнөт. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Колдонмону бөлүшкөндө ал колдонмодо көрсөтүлүп же ойнотулуп жаткан нерселер <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосуна көрүнөт. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Экранды бөлүшүү"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Жыйыштыруу сүрөтчөсү"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Жайып көрсөтүү сүрөтчөсү"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"же"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Артка кайтуу жаңсоосу"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Башкы бетке өтүү жаңсоосу"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Аракет баскычы"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 5ac2a6f..75f579c 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ແລະ ແອັບອື່ນໆທີ່ເປີດຢູ່ກວດພົບຮູບໜ້າຈໍນີ້."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ເພີ່ມໃສ່ບັນທຶກ"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"ຮວມລິ້ງ"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"ໂປຣແກຣມບັນທຶກໜ້າຈໍ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ກຳລັງປະມວນຜົນການບັນທຶກໜ້າຈໍ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ການແຈ້ງເຕືອນສຳລັບເຊດຊັນການບັນທຶກໜ້າຈໍໃດໜຶ່ງ"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"ພາບພັກໜ້າຈໍ"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"ຫ້າມລົບກວນ"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"ໂໝດຄວາມສຳຄັນ"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ບໍ່​ມີ​ອຸ​ປະ​ກອນ​ທີ່​ສາ​ມາດ​ຈັບ​ຄູ່​ໄດ້"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ແຕະເພື່ອເຊື່ອມຕໍ່ ຫຼື ຕັດການເຊື່ອມຕໍ່ອຸປະກອນ"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ໃຊ້ Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ເຊື່ອມຕໍ່ແລ້ວ"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ການແບ່ງປັນສຽງ"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ແຕະເພື່ອສະຫຼັບ ຫຼື ແບ່ງປັນສຽງ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ບັນທຶກແລ້ວ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ຕັດການເຊື່ອມຕໍ່"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ເປີດນຳໃຊ້"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ເປີດການຕັ້ງຄ່າ"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"ອຸປະກອນອື່ນໆ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ສະຫຼັບພາບຮວມ"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ໂໝດຄວາມສຳຄັນ"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ແລ້ວໆ"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ການຕັ້ງຄ່າ"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"ເປີດ"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ບໍລິການທີ່ມີຟັງຊັນນີ້ຈະມີສິດເຂົ້າເຖິງຂໍ້ມູນທັງໝົດທີ່ປາກົດຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຈາກອຸປະກອນຂອງທ່ານໃນຂະນະທີ່ບັນທຶກ ຫຼື ສົ່ງສັນຍານ. ເຊິ່ງຈະຮວມທັງຂໍ້ມູນຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຮູບພາບ, ຂໍ້ຄວາມ ແລະ ສຽງທີ່ທ່ານຫຼິ້ນ."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ແບ່ງປັນ ຫຼື ບັນທຶກແອັບ"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"ແບ່ງປັນໜ້າຈໍຂອງທ່ານກັບ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ບໍ?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ແບ່ງປັນແອັບດຽວ"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"ແບ່ງປັນໜ້າຈໍທັງໝົດ"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ແບ່ງປັນແອັບດຽວ"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"ແບ່ງປັນໜ້າຈໍທັງໝົດ"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ເມື່ອທ່ານແບ່ງປັນໜ້າຈໍທັງໝົດຂອງທ່ານ, ຄົນອື່ນຈະເບິ່ງເຫັນທຸກຢ່າງທີ່ຢູ່ໜ້າຈໍຂອງທ່ານໃນ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ, ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ເມື່ອທ່ານແບ່ງປັນແອັບຂອງທ່ານ, ຄົນອື່ນຈະເບິ່ງເຫັນທຸກຢ່າງທີ່ສະແດງ ຫຼື ຫຼິ້ນໃນແອັບໃນ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ, ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ແບ່ງປັນໜ້າຈໍ"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ໄອຄອນຫຍໍ້ລົງ"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ໄອຄອນຂະຫຍາຍ"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ຫຼື"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ທ່າທາງສຳລັບກັບຄືນ"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ທ່າທາງສຳລັບໜ້າຫຼັກ"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ປຸ່ມຄຳສັ່ງ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 0516504..61516fe 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"„<xliff:g id="APPNAME">%1$s</xliff:g>“ ir kitos atidarytos programos aptiko šią ekrano kopiją."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Pridėti prie užrašo"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Įtraukti nuorodą"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"„<xliff:g id="APPNAME">%1$s</xliff:g>“ <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Ekrano vaizdo įrašytuvas"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Apdorojam. ekrano vaizdo įraš."</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Šiuo metu rodomas ekrano įrašymo sesijos pranešimas"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Ekrano užsklanda"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Eternetas"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Netrukdymo režimas"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioriteto režimai"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nėra pasiekiamų susietų įrenginių"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Palieskite, kad prijungtumėte ar atjungtumėte įrenginį"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"„Bluetooth“ naudojimas"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Prisijungta"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Garso įrašų bendrinimas"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Palieskite, jei norite perjungti arba bendrinti garsą"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Išsaugota"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"atjungti"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"suaktyvinti"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Atidaryti nustatymus"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Kitas įrenginys"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Perjungti apžvalgą"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteto režimai"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Atlikta"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nustatymai"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Įjungta"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Šią funkciją teikianti paslauga galės pasiekti visą informaciją, matomą ekrane ir leidžiamą iš įrenginio įrašant ar perduodant turinį. Tai apima įvairią informaciją, pvz., slaptažodžius, išsamią mokėjimo informaciją, nuotraukas, pranešimus ir leidžiamus garso įrašus."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Programos bendrinimas ar įrašymas"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Bendrinti ekraną su „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Bendrinti vieną programą"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Bendrinti visą ekraną"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Bendrinti vieną programą"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Bendrinti visą ekraną"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kai bendrinate visą ekraną, „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ matomas visas ekrano turinys. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kai bendrinate programą, „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ matomas visas toje programoje rodomas ar leidžiamas turinys. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Bendrinti ekraną"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Sutraukimo piktograma"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Išskleidimo piktograma"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"arba"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Grįžimo atgal gestas"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pagrindinio ekrano gestas"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Veiksmų klavišas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index baf03e2..1b48d3f 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> un citas atvērtas lietotnes konstatēja, ka tika veikts ekrānuzņēmums."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Pievienot piezīmei"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Iekļaut saiti"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Ekrāna ierakstītājs"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekrāna ieraksta apstrāde"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Aktīvs paziņojums par ekrāna ierakstīšanas sesiju"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Ekrānsaudzētājs"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Tīkls Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Režīms “Netraucēt”"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritātes režīmi"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nav pieejama neviena pārī savienota ierīce."</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Lai pievienotu vai atvienotu kādu ierīci, pieskarieties."</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Izmantot Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Savienojums izveidots"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio kopīgošana"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Pieskarieties, lai pārslēgtu vai kopīgotu audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saglabāta"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"atvienot"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivizēt"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Atvērt iestatījumus"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Cita ierīce"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pārskata pārslēgšana"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritātes režīmi"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gatavs"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Iestatījumi"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Ieslēgts"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Pakalpojums, kas nodrošina šo funkciju, iegūs piekļuvi visai informācijai, kas ierakstīšanas vai apraides laikā tiks rādīta jūsu ekrānā vai atskaņota jūsu ierīcē. Atļauja attiecas uz tādu informāciju kā paroles, maksājumu informācija, fotoattēli, ziņojumi un jūsu atskaņotais audio saturs."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Lietotnes kopīgošana vai ierakstīšana"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vai kopīgot ekrānu ar lietotni <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Kopīgot vienu lietotni"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Kopīgot visu ekrānu"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Kopīgot vienu lietotni"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Kopīgot visu ekrānu"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kopīgojot visu ekrānu, lietotnei <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ir pieejams viss ekrāna saturs. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kopīgojot lietotni, lietotnei <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ir pieejams viss kopīgotajā lietotnē parādītais vai atskaņotais saturs. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Kopīgot ekrānu"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Sakļaušanas ikona"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Izvēršanas ikona"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"vai"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Žests pāriešanai atpakaļ"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Žests pāriešanai uz sākumu"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Darbību taustiņš"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 24bdae3..1c853df 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> и други отворени апликации ја открија оваа слика од екранот."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Додај во белешка"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Опфати линк"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Снимач на екран"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Се обработува снимка од екран"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Тековно известување за сесија за снимање на екранот"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Штедач на екран"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Етернет"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не вознемирувај"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Приоритетни режими"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Нема достапни спарени уреди"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Допрете за да воспоставите или да прекинете врска со уред"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Користи Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Поврзано"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Споделување аудио"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Допрете за да префрлите или споделите аудио"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Зачувано"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекини врска"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активирај"</string>
@@ -391,7 +392,7 @@
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Снимање екран"</string>
     <string name="performance" msgid="6552785217174378320">"Изведба"</string>
     <string name="user_interface" msgid="3712869377953950887">"Кориснички интерфејс"</string>
-    <string name="thermal" msgid="6758074791325414831">"Термално"</string>
+    <string name="thermal" msgid="6758074791325414831">"Прегревање"</string>
     <string name="custom" msgid="3337456985275158299">"Приспособено"</string>
     <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Приспособени поставки за следење"</string>
     <string name="restore_default" msgid="5259420807486239755">"Врати на стандардно"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Отворете „Поставки“"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Друг уред"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Вклучи/исклучи преглед"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Приоритетни режими"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Поставки"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Вклучено"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Услугата што ја обезбедува функцијава ќе има пристап до сите податоци што се видливи на екранот или пуштени од вашиот уред додека се снима или емитува. Ова вклучува податоци како лозинките, деталите за плаќање, фотографиите, пораките и аудиото што го пуштате."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Споделете или снимете апликација"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Да се сподели вашиот екран со <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Споделете една апликација"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Споделете го целиот екран"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Споделете една апликација"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Споделете го целиот екран"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Додека го споделувате целиот екран, сè на екранот е видливо за <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Додека споделувате апликација, сѐ што се прикажува или пушта на таа апликација е видливо за <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Сподели екран"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Икона за собирање"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Икона за проширување"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"или"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Движење за назад"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Движење за почетен екран"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Копче за дејство"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 32f840e..ef63d67 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> എന്ന ആപ്പും തുറന്നിരിക്കുന്ന മറ്റ് ആപ്പും ഈ സ്ക്രീൻഷോട്ട് തിരിച്ചറിഞ്ഞു."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"കുറിപ്പിലേക്ക് ചേർക്കുക"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"ലിങ്ക് ഉൾപ്പെടുത്തുക"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"സ്ക്രീൻ റെക്കോർഡർ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"സ്ക്രീൻ റെക്കോർഡിംഗ് പ്രോസസുചെയ്യുന്നു"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ഒരു സ്ക്രീൻ റെക്കോർഡിംഗ് സെഷനായി നിലവിലുള്ള അറിയിപ്പ്"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"സ്ക്രീൻ സേവർ"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ഇതർനെറ്റ്"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"ശല്യപ്പെടുത്തരുത്"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"മുൻഗണനാ മോഡുകൾ"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ജോടിയാക്കിയ ഉപകരണങ്ങളൊന്നും ലഭ്യമല്ല"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ഒരു ഉപകരണം കണക്റ്റ് ചെയ്യാനോ വിച്ഛേദിക്കാനോ ടാപ്പ് ചെയ്യുക"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth ഉപയോഗിക്കുക"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"കണക്‌റ്റ് ചെയ്‌തു"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ഓഡിയോ പങ്കിടൽ"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ഓഡിയോ മാറാനോ പങ്കിടാനോ ടാപ്പ് ചെയ്യുക"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"സംരക്ഷിച്ചു"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"വിച്ഛേദിക്കുക"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"സജീവമാക്കുക"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ക്രമീകരണം തുറക്കുക"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"മറ്റ് ഉപകരണം"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"അവലോകനം മാറ്റുക"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"മുൻഗണനാ മോഡുകൾ"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ശരി"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ക്രമീകരണം"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"ഓണാണ്"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"റെക്കോർഡ് ചെയ്യുമ്പോഴോ കാസ്‌റ്റ് ചെയ്യുമ്പോഴോ നിങ്ങളുടെ ഉപകരണത്തിൽ നിന്ന് പ്ലേ ചെയ്യുന്നതോ നിങ്ങളുടെ സ്‌ക്രീനിൽ ദൃശ്യമാകുന്നതോ ആയ എല്ലാ വിവരങ്ങളിലേക്കും ഈ ഫംഗ്‌ഷൻ ലഭ്യമാക്കുന്ന സേവനത്തിന് ആക്‌സസ് ഉണ്ടായിരിക്കും. നിങ്ങൾ പ്ലേ ചെയ്യുന്ന ഓഡിയോ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, പാസ്‌വേഡുകൾ എന്നിവ പോലുള്ള വിവരങ്ങൾ ഇതിൽ ഉൾപ്പെടുന്നു."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ഒരു ആപ്പ് പങ്കിടുക അല്ലെങ്കിൽ റെക്കോർഡ് ചെയ്യുക"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"നിങ്ങളുടെ സ്ക്രീൻ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതുമായി പങ്കിടണോ?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ഒരു ആപ്പ് പങ്കിടുക"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"സ്ക്രീൻ മുഴുവനായി പങ്കിടുക"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ആപ്പ് പങ്കിടുക"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"സ്ക്രീൻ പൂർണമായും പങ്കിടുക"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"നിങ്ങളുടെ സ്ക്രീൻ മുഴുവനായി പങ്കിടുമ്പോൾ, സ്ക്രീനിലെ എല്ലാ കാര്യങ്ങളും <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് ദൃശ്യമാകും. അതിനാൽ പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങളിൽ ശ്രദ്ധ പുലർത്തുക."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"നിങ്ങളുടെ ആപ്പ് പങ്കിടുമ്പോൾ, ആ ആപ്പിൽ കാണിക്കുന്നതോ പ്ലേ ചെയ്യുന്നതോ ആയ എല്ലാ കാര്യങ്ങളും <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് ദൃശ്യമാകും. അതിനാൽ പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങളിൽ ശ്രദ്ധ പുലർത്തുക."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"സ്‌ക്രീൻ പങ്കിടുക"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ചുരുക്കൽ ഐക്കൺ"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"വികസിപ്പിക്കൽ ഐക്കൺ"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"അല്ലെങ്കിൽ"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"\'മടങ്ങുക\' ജെസ്ച്ചർ"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ഹോം ജെസ്‌ച്ചർ"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ആക്ഷൻ കീ"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index d229589..ff8c52b 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> болон бусад нээлттэй апп энэ дэлгэцийн агшныг илрүүлсэн."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Тэмдэглэлд нэмэх"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Холбоосыг оруулах"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Дэлгэцийн үйлдэл бичигч"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Дэлгэц бичлэг боловсруулж байна"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Дэлгэц бичих горимын үргэлжилж буй мэдэгдэл"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Дэлгэц амраагч"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Этернет"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Бүү саад бол"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Чухал байдлаар нь ангилах горим"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Хослуулсан төхөөрөмж байхгүй"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Төхөөрөмжийг холбох эсвэл салгахын тулд товшино уу"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-г ашиглах"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Холбогдсон"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Аудио хуваалцах"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Аудиог сэлгэх эсвэл хуваалцахын тулд товшино уу"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Хадгалсан"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"салгах"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"идэвхжүүлэх"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Тохиргоог нээх"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Бусад төхөөрөмж"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Тоймыг асаах/унтраах"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Чухал байдлаар нь ангилах горим"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Болсон"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Тохиргоо"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Асаалттай"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Энэ функцийг олгож буй үйлчилгээ нь бичлэг хийж эсвэл дамжуулж байх үед таны дэлгэцэд харуулсан эсвэл төхөөрөмжөөс тань тоглуулсан бүх мэдээлэлд хандах эрхтэй. Үүнд нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг болон таны тоглуулдаг аудио зэрэг мэдээлэл багтана."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Апп хуваалцах эсвэл бичих"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Дэлгэцээ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-тай хуваалцах уу?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Нэг апп хуваалцах"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Дэлгэцийг бүтнээр нь хуваалцах"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Нэг апп хуваалцах"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Дэлгэцийг бүтнээр нь хуваалцах"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Таныг дэлгэцээ бүхэлд нь хуваалцаж байхад дэлгэц дээр тань байгаа аливаа зүйл <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-д харагдана. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио, видео зэрэг зүйлд болгоомжтой хандаарай."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Таныг апп хуваалцаж байхад тухайн аппад харуулж эсвэл тоглуулж буй аливаа зүйл <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-д харагдана. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио, видео зэрэг зүйлд болгоомжтой хандаарай."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Дэлгэцийг хуваалцах"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Хураах дүрс тэмдэг"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Дэлгэх дүрс тэмдэг"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"эсвэл"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Буцах зангаа"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Үндсэн нүүрний зангаа"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Тусгай товчлуур"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 5ec388d..76515d2 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> आणि उघडलेल्या इतर अ‍ॅप्सनी हा स्क्रीनशॉट डिटेक्ट केला."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"टीप जोडा"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"लिंकचा समावेश करा"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"स्क्रीन रेकॉर्डर"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रेकॉर्डिंग प्रोसेस सुरू"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रेकॉर्ड सत्रासाठी सुरू असलेली सूचना"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"स्क्रीन सेव्हर"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"इथरनेट"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"व्यत्यय आणू नका"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"प्राधान्य मोड"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ब्लूटूथ"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"कोणतेही जोडलेले डिव्हाइसेस उपलब्ध नाहीत"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"डिव्हाइस कनेक्ट किंवा डिस्कनेक्ट करण्यासाठी टॅप करा"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ब्‍लूटूथ वापरा"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"कनेक्ट केले"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ऑडिओ शेअरिंग"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"व्हिडिओवर स्विच करण्यासाठी टॅप करा किंवा शेअर करा"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेव्ह केले"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिस्कनेक्ट करा"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ॲक्टिव्हेट करा"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"सेटिंग्ज उघडा"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"इतर डिव्हाइस"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"अवलोकन टॉगल करा."</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"प्राधान्य मोड"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"पूर्ण झाले"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिंग्ज"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"सुरू आहे"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"रेकॉर्ड किंवा कास्ट करत असताना, हे कार्य पुरवणाऱ्या सेवेला तुमच्या स्क्रीनवर दाखवलेल्या किंवा डिव्हाइसवर प्ले केलेल्या सर्व माहितीचा अ‍ॅक्सेस असेल. यामध्ये पासवर्ड, पेमेंट तपशील, फोटो, मेसेज आणि तुम्ही प्ले करत असलेला ऑडिओ यासारख्या माहितीचा समावेश आहे."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"अ‍ॅप शेअर किंवा रेकॉर्ड करा"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"तुमची स्क्रीन <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> सह शेअर करायची आहे का?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"एक अ‍ॅप शेअर करा"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"संपूर्ण स्क्रीन शेअर करा"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"एक अ‍ॅप शेअर करा"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"संपूर्ण स्क्रीन शेअर करा"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"तुम्ही तुमची संपूर्ण स्क्रीन कास्ट करता, तेव्हा तुमच्या स्क्रीनवरील कोणत्याही गोष्टी <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> साठी दृश्यमान असतात. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"तुम्ही अ‍ॅप शेअर करता, तेव्हा त्या अ‍ॅपमध्ये दाखवल्या किंवा प्ले होणाऱ्या कोणत्याही गोष्टी <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> साठी दृश्यमान असतात. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"स्क्रीन शेअर करा"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"कोलॅप्स करा आयकन"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"विस्तार करा आयकन"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"किंवा"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"मागे जा जेश्चर"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"होम जेश्चर"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"अ‍ॅक्शन की"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 9a9455a..181b0c7 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> dan apl lain yang dibuka telah mengesan tangkapan skrin ini."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Tambahkan pada nota"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Sertakan pautan"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Perakam Skrin"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses rakaman skrin"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pemberitahuan breterusan untuk sesi rakaman skrin"</string>
@@ -291,7 +292,7 @@
     <string name="start_dreams" msgid="9131802557946276718">"Penyelamat skrin"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Jangan Ganggu"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Mod keutamaan"</string>
+    <string name="quick_settings_modes_label" msgid="879156359479504244">"Mod"</string>
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Tiada peranti berpasangan tersedia"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Ketik untuk menyambungkan atau memutuskan sambungan peranti"</string>
@@ -300,8 +301,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Gunakan Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Disambungkan"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Perkongsian Audio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Ketik untuk menukar atau berkongsi audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Disimpan"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"putuskan sambungan"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktifkan"</string>
@@ -433,7 +433,7 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Buka Tetapan"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Peranti lain"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Togol Ikhtisar"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Mod keutamaan"</string>
+    <string name="zen_modes_dialog_title" msgid="8854640808100096934">"Mod"</string>
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Selesai"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Tetapan"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Hidup"</string>
@@ -534,8 +534,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Perkhidmatan yang menyediakan fungsi ini boleh mengakses semua maklumat yang boleh dilihat pada skrin anda atau dimainkan daripada peranti anda semasa membuat rakaman atau penghantaran. Maklumat ini termasuk kata laluan, butiran pembayaran, foto, mesej dan audio yang anda mainkan."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Kongsi atau rakam apl"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Kongsi skrin anda dengan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Kongsi satu apl"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Kongsi seluruh skrin"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Kongsi satu apl"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Kongsi seluruh skrin"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Apabila anda berkongsi seluruh skrin anda, apa-apa sahaja kandungan pada skrin anda boleh dilihat oleh <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Apabila anda berkongsi apl, apa-apa sahaja kandungan yang dipaparkan atau dimainkan pada apl boleh dilihat oleh <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Kongsi skrin"</string>
@@ -1387,6 +1391,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Kuncupkan ikon"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Kembangkan ikon"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"atau"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gerak isyarat kembali"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gerak isyarat pergi ke laman utama"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Kekunci tindakan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 622b1d5..afc57ac 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> နှင့် အခြားဖွင့်ထားသော အက်ပ်များက ဤဖန်သားပြင်ဓာတ်ပုံကို တွေ့ရှိသည်။"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"မှတ်စုတွင် ထည့်ရန်"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"လင့်ခ်ထည့်သွင်းရန်"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"ဖန်သားပြင်ရိုက်ကူးစက်"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"စကရင်ရိုက်ကူးမှု အပြီးသတ်နေသည်"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"စခရင်နားချိန်ပုံ"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"အီသာနက်"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"မနှောင့်ယှက်ရ"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"ဦးစားပေးမုဒ်"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ဘလူးတုသ်"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ချိတ်တွဲထားသည့် ကိရိယာများ မရှိ"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"စက်ကို ချိတ်ဆက်ရန် (သို့) ချိတ်ဆက်မှုဖြုတ်ရန် တို့ပါ"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ဘလူးတုသ်သုံးရန်"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ချိတ်ဆက်ထားသည်"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"အော်ဒီယို မျှဝေခြင်း"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"အသံ ပြောင်းရန်/မျှဝေရန် တို့ပါ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"သိမ်းထားသည်"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ချိတ်ဆက်မှုဖြုတ်ရန်"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"စသုံးရန်"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ဆက်တင်များဖွင့်ရန်"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"အခြားစက်ပစ္စည်း"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ဖွင့်၊ ပိတ် အနှစ်ချုပ်"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ဦးစားပေးမုဒ်"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ပြီးပြီ"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ဆက်တင်များ"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"ဖွင့်"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ဤလုပ်ဆောင်ချက်ကို ပေးအပ်သည့် ဝန်ဆောင်မှုသည် ရုပ်သံဖမ်းနေစဉ် (သို့) ကာစ်လုပ်နေစဉ် သင့်မျက်နှာပြင်တွင် မြင်ရသော (သို့) သင့်စက်တွင် ဖွင့်ထားသော အချက်အလက်မှန်သမျှကို သုံးနိုင်ပါမည်။ ၎င်းတွင် စကားဝှက်များ၊ ငွေပေးချေမှုအသေးစိတ်များ၊ ဓာတ်ပုံများ၊ မက်ဆေ့ဂျ်များနှင့် သင်ဖွင့်သည့်အသံကဲ့သို့သော အချက်အလက်များ ပါဝင်သည်။"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"အက်ပ် မျှဝေခြင်း (သို့) ရိုက်ကူးခြင်း"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"သင့်စခရင်ကို <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> နှင့် မျှဝေမလား။"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"အက်ပ်တစ်ခု မျှဝေရန်"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"စခရင်တစ်ခုလုံး မျှဝေရန်"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"အက်ပ်တစ်ခု မျှဝေရန်"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"စခရင်တစ်ခုလုံး မျှဝေရန်"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"သင့်စခရင်တစ်ခုလုံးကို မျှဝေနေချိန်တွင် စခရင်ပေါ်ရှိ အရာအားလုံးကို <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> က မြင်နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"အက်ပ်ကို မျှဝေနေချိန်တွင် ယင်းအက်ပ်တွင် ပြထားသော (သို့) ဖွင့်ထားသော အရာအားလုံးကို <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> က မြင်နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"စခရင် မျှဝေရန်"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"လျှော့ပြရန် သင်္ကေတ"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ပိုပြရန် သင်္ကေတ"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"သို့မဟုတ်"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"နောက်သို့ လက်ဟန်"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ပင်မစာမျက်နှာ လက်ဟန်"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"လုပ်ဆောင်ချက်ကီး"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 1191844..d222f31 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> og andre åpne apper har registrert dette skjermbildet."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Legg til i notat"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Inkluder linken"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Skjermopptak"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skjermopptaket"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Vedvarende varsel for et skjermopptak"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Skjermsparer"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ikke forstyrr"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritetsmoduser"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Ingen sammenkoblede enheter er tilgjengelige"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Trykk for å koble en enhet til eller fra"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bruk Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Tilkoblet"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Lyddeling"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Trykk for å bytte eller dele lyd"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Lagret"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"koble fra"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiver"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Åpne Innstillinger"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Annen enhet"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå oversikten av eller på"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetsmoduser"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Ferdig"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Innstillinger"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"På"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Tjenesten som leverer denne funksjonen, får tilgang til all informasjon som vises på skjermen eller spilles av fra enheten mens du tar opp eller caster noe. Dette inkluderer informasjon som passord, betalingsopplysninger, bilder, meldinger og lyd du spiller av."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Del eller ta opp en app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vil du dele skjermen med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Del én app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Del hele skjermen"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Del én app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Del hele skjermen"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Når du deler hele skjermen, er alt på skjermen synlig for <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Når du deler en app, er alt som vises eller spilles av i appen, synlig for <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Del skjermen"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Skjul-ikon"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Vis-ikon"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"eller"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Tilbakebevegelse"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Startskjermbevegelse"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Handlingstast"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 610a449..8af52a1 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> र खुला रहेका अन्य एपहरूले यो स्क्रिनसट भेट्टाएका छन्।"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"नोटमा सेभ गर्नुहोस्"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"लिंक समावेश गर्नुहोस्"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"स्क्रिन रेकर्डर"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रिन रेकर्डिङको प्रक्रिया अघि बढाइँदै"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"कुनै स्क्रिन रेकर्ड गर्ने सत्रका लागि चलिरहेको सूचना"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"स्क्रिन सेभर"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"बाधा नपुऱ्याउनुहोस्"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"महत्त्वपूर्ण मोडहरू"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ब्लुटुथ"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"जोडी उपकरणहरू उपलब्ध छैन"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"कुनै डिभाइस कनेक्ट गर्न वा डिस्कनेक्ट गर्न ट्याप गर्नुहोस्"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ब्लुटुथ प्रयोग गर्नुहोस्"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"कनेक्ट गरिएको छ"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"अडियो सेयरिङ"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"अडियो बदल्न वा सेयर गर्न ट्याप गर्नुहोस्"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेभ गरिएको छ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिस्कनेक्ट गर्नुहोस्"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"एक्टिभेट गर्नुहोस्"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"सेटिङ खोल्नुहोस्"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"अर्को डिभाइड"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"परिदृश्य टगल गर्नुहोस्"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"महत्त्वपूर्ण मोडहरू"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"सम्पन्न भयो"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिङ"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"अन छ"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"यो फङ्सन प्रदान गर्ने सेवाले रेकर्ड वा कास्ट गर्दै गर्दा तपाईंको स्क्रिनमा देखिने सबै जानकारी अथवा तपाईंको डिभाइसबाट प्ले गरिने सबै सामग्री हेर्न तथा प्रयोग गर्न सक्छ। यसअन्तर्गत पासवर्ड, भुक्तानीसम्बन्धी विवरण, फोटो, म्यासेज र तपाईंले प्ले गर्ने अडियो जस्ता कुराहरू समावेश हुन्छन्।"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"कुनै एप सेयर वा रेकर्ड गर्नुहोस्"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"स्क्रिन <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> सँग सेयर गर्ने हो?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"एउटा एप सेयर गर्नुहोस्"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"पूरै स्क्रिन सेयर गर्नुहोस्"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"एउटा एप सेयर गर्नुहोस्"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"पूरै स्क्रिन सेयर गर्नुहोस्"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"तपाईंले पूरै स्क्रिन सेयर गरिरहेका बेला तपाईंको स्क्रिनमा देखिने सबै सामग्री <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> मा देखिन्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"तपाईंले यो एप सेयर गरिरहेका बेला यो एपमा देखाइने वा प्ले गरिने सबै सामग्री <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> मा देखिन्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"स्क्रिन सेयर गर्नुहोस्"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"\"कोल्याप्स गर्नुहोस्\" आइकन"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"\"एक्स्पान्ड गर्नुहोस्\" आइकन"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"वा"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ब्याक जेस्चर"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"होम जेस्चर"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"एक्सन की"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 404d768..24a4835 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> en andere geopende apps hebben dit screenshot waargenomen."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Toevoegen aan notitie"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Link opnemen"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Schermopname"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Schermopname verwerken"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Doorlopende melding voor een schermopname-sessie"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Screensaver"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Niet storen"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioriteitsmodi"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Geen gekoppelde apparaten beschikbaar"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tik om een apparaat te verbinden of de verbinding te verbreken"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth gebruiken"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Verbonden"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio delen"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tik om audio te schakelen of te delen"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Opgeslagen"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"loskoppelen"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activeren"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Instellingen openen"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Ander apparaat"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Overzicht aan- of uitzetten"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteitsmodi"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Klaar"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Instellingen"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Aan"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"De service die deze functie levert, krijgt tijdens het opnemen of casten toegang tot alle informatie die zichtbaar is op je scherm of wordt afgespeeld op je apparaat. Dit omvat informatie zoals wachtwoorden, betalingsgegevens, foto\'s, berichten en audio die je afspeelt."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"App delen of opnemen"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Je scherm delen met <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Eén app delen"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Hele scherm delen"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Eén app delen"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Hele scherm delen"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Als je het hele scherm deelt, is alles op je scherm zichtbaar voor <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Als je een app deelt, is alles dat wordt getoond of afgespeeld in die app zichtbaar voor <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Scherm delen"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icoon voor samenvouwen"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icoon voor uitvouwen"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"of"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gebaar voor terug"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gebaar voor startscherm"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Actietoets"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 5b9d747..67537c2 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ଏବଂ ଅନ୍ୟ ଓପନ ଆପ୍ସ ଏହି ସ୍କ୍ରିନସଟକୁ ଚିହ୍ନଟ କରିଛି।"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ନୋଟରେ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"ଲିଙ୍କକୁ ଅନ୍ତର୍ଭୁକ୍ତ କରନ୍ତୁ"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"ସ୍କ୍ରିନ ରେକର୍ଡର"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ସ୍କ୍ରିନ ରେକର୍ଡିଂର ପ୍ରକ୍ରିୟାକରଣ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ଏକ ସ୍କ୍ରି‍ନ୍‍ ରେକର୍ଡ୍‍ ସେସନ୍‍ ପାଇଁ ଚାଲୁଥିବା ବିଜ୍ଞପ୍ତି"</string>
@@ -228,7 +229,7 @@
     <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"ଫେସ ଅନଲକ ସେଟ ଅପ କରନ୍ତୁ"</string>
     <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"ଫେସ ଅନଲକ ପୁଣି ସେଟ ଅପ କରିବାକୁ ଆପଣଙ୍କ ବର୍ତ୍ତମାନର ଫେସ ମଡେଲ ଡିଲିଟ ହୋଇଯିବ।\n\nଆପଣଙ୍କ ଫୋନକୁ ଅନଲକ କରିବା ପାଇଁ ଆପଣଙ୍କ ଫେସ ବ୍ୟବହାର କରିବାକୁ ଆପଣଙ୍କୁ ଏହି ଫିଚର ପୁଣି ସେଟ ଅପ କରିବାକୁ ହେବ।"</string>
     <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"ଫେସ ଅନଲକ ସେଟ ଅପ କରାଯାଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରିବା ପାଇଁ ସେଟିଂସକୁ ଯାଆନ୍ତୁ।"</string>
-    <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ଟିପଚିହ୍ନ ସେନସର୍‌କୁ ଛୁଅଁନ୍ତୁ"</string>
+    <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ଟିପଚିହ୍ନ ସେନସରକୁ ସ୍ପର୍ଶ କରନ୍ତୁ"</string>
     <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"ଜାରି ରଖିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"ଫେସ ଚିହ୍ନଟ କରାଯାଇନାହିଁ। ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"ସ୍କ୍ରିନ୍‌ ସେଭର୍‌"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ଇଥରନେଟ୍‌"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"ପ୍ରାଥମିକତା ମୋଡ"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ବ୍ଲୁଟୁଥ"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ପେୟାର୍‍ ହୋଇଥିବା କୌଣସି ଡିଭାଇସ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ଏକ ଡିଭାଇସ କନେକ୍ଟ କିମ୍ବା ଡିସକନେକ୍ଟ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ବ୍ଲୁଟୁଥ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"କନେକ୍ଟ କରାଯାଇଛି"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ଅଡିଓ ସେୟାରିଂ"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ଅଡିଓ ସୁଇଚ କିମ୍ବା ସେୟାର କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ସେଭ କରାଯାଇଛି"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ଡିସକନେକ୍ଟ କରନ୍ତୁ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ଚାଲୁ କରନ୍ତୁ"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ସେଟିଂସ ଖୋଲନ୍ତୁ"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"ଅନ୍ୟ ଡିଭାଇସ୍"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ସଂକ୍ଷିପ୍ତ ବିବରଣୀକୁ ଟୋଗଲ୍ କରନ୍ତୁ"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ପ୍ରାଥମିକତା ମୋଡ"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ହୋଇଗଲା"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ସେଟିଂସ"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"ଚାଲୁ ଅଛି"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ରେକର୍ଡ ବା କାଷ୍ଟ କରିବା ସମୟରେ ଆପଣଙ୍କ ଡିଭାଇସରୁ ପ୍ଲେ ହେଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା ସମସ୍ତ ସୂଚନାକୁ ଏହି ଫଙ୍କସନ ପ୍ରଦାନ କରୁଥିବା ସେବାର ଆକ୍ସେସ ରହିବ। ଏଥିରେ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ଫଟୋ, ମେସେଜ ଏବଂ ଆପଣ ପ୍ଲେ କରୁଥିବା ଅଡିଓ ପରି ସୂଚନା ଅନ୍ତର୍ଭୁକ୍ତ ଅଛି।"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ଏକ ଆପକୁ ସେୟାର କିମ୍ବା ରେକର୍ଡ କରନ୍ତୁ"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ସହ ଆପଣଙ୍କ ସ୍କ୍ରିନକୁ ସେୟାର କରନ୍ତୁ?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ଗୋଟିଏ ଆପ ସେୟାର କରନ୍ତୁ"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ ସେୟାର କରନ୍ତୁ"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ଗୋଟିଏ ଆପ ସେୟାର କରନ୍ତୁ"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ ସେୟାର କରନ୍ତୁ"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ଆପଣ ଆପଣଙ୍କ ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ ସେୟାର କରିବା ସମୟରେ ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ସବୁକିଛି <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>କୁ ଦେଖାଯାଏ। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ଆପଣ ଏକ ଆପ ସେୟାର କରିବା ସମୟରେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛି <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>କୁ ଦେଖାଯାଏ। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ସ୍କ୍ରିନ ସେୟାର କରନ୍ତୁ"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ଆଇକନକୁ ସଙ୍କୁଚିତ କରନ୍ତୁ"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ଆଇକନକୁ ବିସ୍ତାର କରନ୍ତୁ"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"କିମ୍ବା"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ବେକ ଜେଶ୍ଚର"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ହୋମ ଜେଶ୍ଚର"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ଆକ୍ସନ କୀ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index c9a45ba..1927d45 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ਅਤੇ ਹੋਰ ਖੁੱਲ੍ਹੀਆਂ ਐਪਾਂ ਨੂੰ ਇਸ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦਾ ਪਤਾ ਲੱਗਿਆ ਹੈ।"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ਨੋਟ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"ਲਿੰਕ ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਰ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਜਾਰੀ ਹੈ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ਕਿਸੇ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਸੈਸ਼ਨ ਲਈ ਚੱਲ ਰਹੀ ਸੂਚਨਾ"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"ਸਕ੍ਰੀਨ ਸੇਵਰ"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ਈਥਰਨੈਟ"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"ਤਰਜੀਹ ਮੋਡ"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ਬਲੂਟੁੱਥ"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ਕੋਈ ਜੋੜਾਬੱਧ ਕੀਤੀਆਂ ਡੀਵਾਈਸਾਂ ਉਪਲਬਧ ਨਹੀਂ"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ਡੀਵਾਈਸ ਨੂੰ ਕਨੈਕਟ ਜਾਂ ਡਿਸਕਨੈਕਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ਬਲੂਟੁੱਥ ਵਰਤੋ"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ਕਨੈਕਟ ਹੈ"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ਆਡੀਓ ਸਾਂਝਾਕਰਨ"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ਆਡੀਓ ਨੂੰ ਸਵਿੱਚ ਜਾਂ ਸਾਂਝਾ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ਕਿਰਿਆਸ਼ੀਲ ਕਰੋ"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"ਹੋਰ ਡੀਵਾਈਸ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ਰੂਪ-ਰੇਖਾ ਨੂੰ ਟੌਗਲ ਕਰੋ"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ਤਰਜੀਹ ਮੋਡ"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ਹੋ ਗਿਆ"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"ਚਾਲੂ"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ਇਸ ਫੰਕਸ਼ਨ ਦੇ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਕੋਲ ਬਾਕੀ ਸਾਰੀ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ ਜੋ ਕਿ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਣਯੋਗ ਹੁੰਦੀ ਹੈ ਜਾਂ ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨ ਵੇਲੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਂਦੀ ਹੈ। ਇਸ ਵਿੱਚ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਫ਼ੋਟੋਆਂ, ਸੁਨੇਹਿਆਂ ਅਤੇ ਤੁਹਾਡੇ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਆਡੀਓ ਦੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੈ।"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ਐਪ ਨੂੰ ਸਾਂਝਾ ਕਰੋ ਜਾਂ ਰਿਕਾਰਡ ਕਰੋ"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"ਕੀ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਨਾਲ ਆਪਣੀ ਸਕ੍ਰੀਨ ਸਾਂਝੀ ਕਰਨੀ ਹੈ?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ਇੱਕ ਐਪ ਸਾਂਝੀ ਕਰੋ"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਸਾਂਝੀ ਕਰੋ"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ਇੱਕ ਐਪ ਸਾਂਝੀ ਕਰੋ"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਸਾਂਝੀ ਕਰੋ"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਦੌਰਾਨ, ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖ ਰਹੀ ਹਰੇਕ ਚੀਜ਼ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> \'ਤੇ ਵੀ ਦਿਖਣਯੋਗ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ਕਿਸੇ ਐਪ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਦੌਰਾਨ, ਉਸ ਐਪ \'ਤੇ ਦਿਖ ਰਹੀ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਨੂੰ ਦਿਖਣਯੋਗ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ਸਕ੍ਰੀਨ ਸਾਂਝੀ ਕਰੋ"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ਪ੍ਰਤੀਕ ਨੂੰ ਸਮੇਟੋ"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ਪ੍ਰਤੀਕ ਦਾ ਵਿਸਤਾਰ ਕਰੋ"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ਜਾਂ"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ਪਿੱਛੇ ਜਾਣ ਦਾ ਇਸ਼ਾਰਾ"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ਹੋਮ \'ਤੇ ਜਾਣ ਦਾ ਇਸ਼ਾਰਾ"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ਕਾਰਵਾਈ ਕੁੰਜੀ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index f467409..1b27dba 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Aplikacja <xliff:g id="APPNAME">%1$s</xliff:g> i inne aplikacje wykryły ten zrzut ekranu."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj do notatek"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Dołącz link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Nagrywanie ekranu"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Przetwarzam nagrywanie ekranu"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Stałe powiadomienie o sesji rejestrowania zawartości ekranu"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Wygaszacz ekranu"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Nie przeszkadzać"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Tryby priorytetowe"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Brak dostępnych sparowanych urządzeń"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Kliknij, aby podłączyć lub odłączyć urządzenie"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Używaj Bluetootha"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Połączone"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Udostępnianie dźwięku"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Kliknij, aby przełączyć lub udostępnić dźwięk"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Zapisane"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"rozłącz"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktywuj"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Otwórz Ustawienia"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Inne urządzenie"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Przełącz Przegląd"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Tryby priorytetowe"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotowe"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ustawienia"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Wł."</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Podczas nagrywania i przesyłania usługa udostępniająca tę funkcję będzie miała dostęp do wszystkich informacji widocznych na ekranie lub odtwarzanych na urządzeniu. Dotyczy to m.in. haseł, szczegółów płatności, zdjęć, wiadomości i odtwarzanych dźwięków."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Udostępnianie i nagrywanie za pomocą aplikacji"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Udostępnić ekran aplikacji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Udostępnij jedną aplikację"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Udostępnij cały ekran"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Udostępnij jedną aplikację"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Udostępnij cały ekran"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kiedy udostępniasz treści z całego ekranu, aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ma dostęp do całości obrazu z wyświetlacza. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kiedy udostępniasz obraz z aplikacji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, widoczne jest wszystko to, co jest w niej wyświetlane lub odtwarzane. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Udostępnij ekran"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona zwijania"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona rozwijania"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"lub"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gest przejścia wstecz"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gest przejścia na ekran główny"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Klawisz działania"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 154fc3d..d5856af 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e outros apps abertos detectaram essa captura de tela."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Incluir anotação"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Incluir link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Gravador de tela"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Protetor de tela"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Não perturbe"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modos prioritários"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Não há dispositivos pareados disponíveis"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toque para conectar ou desconectar um dispositivo"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartilhamento de áudio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Toque para mudar ou compartilhar o áudio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvo"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Abrir as Configurações"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Alternar Visão geral"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritários"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Concluído"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configurações"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"O serviço que oferece essa função terá acesso a todas as informações visíveis na tela ou reproduzidas durante uma gravação ou transmissão. Isso inclui senhas, detalhes de pagamento, fotos, mensagens e áudios."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Compartilhe ou grave um app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Compartilhar a tela com o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartilhar um app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartilhar a tela inteira"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Compartilhar um app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Compartilhar a tela inteira"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quando você compartilha a tela inteira, tudo nela fica visível para o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quando você compartilha um aplicativo, todas as informações mostradas ou abertas nele ficam visíveis para o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartilhar tela"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícone \"Fechar\""</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícone \"Abrir\""</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto de volta"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto de início"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de ação"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index d96c540..6589b0f 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"A app <xliff:g id="APPNAME">%1$s</xliff:g> e outras apps abertas detetaram esta captura de ecrã."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Adicionar a uma nota"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Incluir link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Gravador de ecrã"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"A processar a gravação de ecrã"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação persistente de uma sessão de gravação de ecrã"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Proteção ecrã"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Não incomodar"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modos de prioridade"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Sem dispositivos sincronizados disponíveis"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toque para associar ou desassociar um dispositivo"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ligado"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Partilha de áudio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Toque para mudar ou partilhar o áudio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desassociar"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Abrir definições"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Ativar/desativar Vista geral"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos de prioridade"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Concluir"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Definições"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"O serviço que fornece esta função vai ter acesso a todas as informações que estiverem visíveis no ecrã ou que forem reproduzidas a partir do dispositivo durante a gravação ou a transmissão. Isto inclui informações como palavras-passe, detalhes de pagamentos, fotos, mensagens e áudio reproduzido."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Partilhe ou grave uma app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Partilhar o seu ecrã com a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Partilhar uma app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Partilhar ecrã inteiro"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Partilhar uma app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Partilhar ecrã inteiro"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quando está a partilhar o ecrã inteiro, tudo o que estiver no ecrã é visível para a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quando está a partilhar uma app, tudo o que é mostrado ou reproduzido nessa app é visível para a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Partilhar ecrã"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícone de reduzir"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícone de expandir"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto para retroceder"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto para aceder ao ecrã principal"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de ação"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 154fc3d..d5856af 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e outros apps abertos detectaram essa captura de tela."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Incluir anotação"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Incluir link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Gravador de tela"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Protetor de tela"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Não perturbe"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modos prioritários"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Não há dispositivos pareados disponíveis"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toque para conectar ou desconectar um dispositivo"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartilhamento de áudio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Toque para mudar ou compartilhar o áudio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvo"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Abrir as Configurações"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Alternar Visão geral"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritários"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Concluído"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configurações"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"O serviço que oferece essa função terá acesso a todas as informações visíveis na tela ou reproduzidas durante uma gravação ou transmissão. Isso inclui senhas, detalhes de pagamento, fotos, mensagens e áudios."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Compartilhe ou grave um app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Compartilhar a tela com o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartilhar um app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartilhar a tela inteira"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Compartilhar um app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Compartilhar a tela inteira"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quando você compartilha a tela inteira, tudo nela fica visível para o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quando você compartilha um aplicativo, todas as informações mostradas ou abertas nele ficam visíveis para o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartilhar tela"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícone \"Fechar\""</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícone \"Abrir\""</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto de volta"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto de início"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de ação"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 5e1eee3..59136e0 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> și alte aplicații deschise au detectat această captură de ecran."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Adaugă în notă"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Include linkul"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Recorder pentru ecran"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Se procesează înregistrarea"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificare în curs pentru o sesiune de înregistrare a ecranului"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Screensaver"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Nu deranja"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Moduri cu prioritate"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Niciun dispozitiv conectat disponibil"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Atinge pentru a conecta sau deconecta un dispozitiv"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Folosește Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectat"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Permiterea accesului la audio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Atinge pentru a comuta sau a permite accesul la conținutul audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvat"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"deconectează"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activează"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Deschide Setări"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Alt dispozitiv"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Comută secțiunea Recente"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Moduri cu prioritate"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gata"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Setări"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Activat"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Serviciul care oferă această funcție va avea acces la toate informațiile vizibile pe ecran sau redate pe dispozitiv în timp ce înregistrezi sau proiectezi. Între aceste informații se numără parole, detalii de plată, fotografii, mesaje și conținutul audio pe care îl redai."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Permite accesul la o aplicație sau înregistreaz-o"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Permiți accesul <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> la ecran?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Permite accesul la o aplicație"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Permite accesul la tot ecranul"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Permite accesul la o aplicație"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Permite accesul la tot ecranul"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Când permiți accesul la tot ecranul, tot conținutul de pe ecran este vizibil pentru <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Când permiți accesul la o aplicație, orice conținut se afișează sau se redă în aplicație este vizibil pentru <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Permite accesul la ecran"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Pictograma de restrângere"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Pictograma de extindere"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"sau"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gestul Înapoi"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gestul Ecran de pornire"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tastă de acțiuni"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index e938ca0..de43676 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Приложение \"<xliff:g id="APPNAME">%1$s</xliff:g>\" и другие запущенные продукты обнаружили создание скриншота."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Добавить в заметку"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Добавить ссылку"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Запись видео с экрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обработка записи с экрана…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущее уведомление для записи видео с экрана"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Заставка"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не беспокоить"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Режимы приоритета"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Нет доступных сопряженных устройств"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Нажмите, чтобы подключить или отключить устройство."</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Использовать"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Подключено"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Отправка аудио"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Нажмите, чтобы переключить аудио или поделиться им"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сохранено"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"отключить"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активировать"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Открыть настройки"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Другое устройство"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Переключить режим обзора"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Режимы приоритета"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Настройки"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Включено"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Во время записи или трансляции у сервиса, предоставляющего эту функцию, будет доступ ко всему, что видно или воспроизводится на устройстве, включая пароли, сведения о способах оплаты, фотографии, сообщения и аудио."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Демонстрация или запись экрана приложения"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Показать экран приложению \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Показать приложение"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Показать весь экран"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Показать приложение"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Показать весь экран"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"При показе экрана целиком все, что на нем происходит, будет видно в приложении \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\". Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"При показе приложения все, что в нем происходит, будет видно в приложении \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\". Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Показать экран"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Значок \"Свернуть\""</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Значок \"Развернуть\""</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"или"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Жест \"назад\""</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жест \"на главный экран\""</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Клавиша действия"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 7b2b2be..8d6cd09 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> සහ අනෙකුත් විවෘත යෙදුම් මෙම තිර රුව අනාවරණය කර ගෙන ඇත."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"සටහනට එක් කරන්න"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"සබැඳිය ඇතුළත් කරන්න"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"තිර රෙකෝඩරය"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"තිර පටිගත කිරීම සකසමින්"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"තිර පටිගත කිරීමේ සැසියක් සඳහා කෙරෙන දැනුම් දීම"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"තිර සුරැකුම"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ඊතර නෙට්"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"බාධා නොකරන්න"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"ප්‍රමුඛතා ප්‍රකාර"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"බ්ලූටූත්"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"යුගල කළ උපාංග නොතිබේ"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"උපාංගයක් සම්බන්ධ කිරීමට හෝ විසන්ධි කිරීමට තට්ටු කරන්න"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"බ්ලූටූත් භාවිතා කරන්න"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"සම්බන්ධිතයි"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ශ්‍රව්‍ය බෙදා ගැනීම"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ශ්‍රව්‍ය මාරු කිරීමට හෝ බෙදා ගැනීමට තට්ටු කරන්න"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"සුරැකිණි"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"විසන්ධි කරන්න"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"සක්‍රිය කරන්න"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"සැකසීම් විවෘත කරන්න"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"වෙනත් උපාංගය"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"දළ විශ්ලේෂණය ටොගල කරන්න"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ප්‍රමුඛතා ප්‍රකාර"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"නිමයි"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"සැකසීම්"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"ක්‍රියාත්මකයි"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"මෙම කාර්යය සපයන සේවාවට තිරයේ පෙනෙන හෝ පටිගත කිරීමේ දී හෝ විකාශනය කිරීමේ දී ඔබේ උපාංගයේ වාදනය වන සියලු තොරතුරු වෙත ප්‍රවේශය ඇත. මෙයට මුරපද, ගෙවීම් විස්තර, ඡායාරූප, පණිවුඩ, සහ ඔබ වාදනය කරන ශ්‍රව්‍ය වැනි තොරතුරු ඇතුළත් වේ."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"යෙදුමක් බෙදා ගන්න හෝ පටිගත කරන්න"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> සමග ඔබේ තිරය බෙදා ගන්න ද?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"එක් යෙදුමක් බෙදා ගන්න"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"සම්පූර්ණ තිරය බෙදා ගන්න"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"එක් යෙදුමක් බෙදා ගන්න"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"සම්පූර්ණ තිරය බෙදා ගන්න"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ඔබ ඔබේ සම්පූර්ණ තිරය බෙදා ගන්නා විට, ඔබේ තිරයේ ඇති ඕනෑම දෙයක් <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> වෙත දෘශ්‍යමාන වේ. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවිඩ, ඡායාරූප, සහ ශ්‍රව්‍ය සහ දෘශ්‍ය වැනි දේවල් පිළිබඳ ප්‍රවේශම් වන්න."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ඔබ යෙදුමක් බෙදා ගන්නා විට, එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයක් <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> වෙත දෘශ්‍යමාන වේ. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවිඩ, ඡායාරූප, සහ ශ්‍රව්‍ය සහ දෘශ්‍ය වැනි දේවල් පිළිබඳ ප්‍රවේශම් වන්න."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"තිරය බෙදා ගන්න"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"හැකුළුම් නිරූපකය"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"දිගහැරීම් නිරූපකය"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"හෝ"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ආපසු අභිනය"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"නිවෙස් අභිනය"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ක්‍රියා යතුර"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 877e87b..7159285 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> a ďalšie otvorené aplikácie zaznamenali túto snímku obrazovky."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Pridať do poznámky"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Zahrnúť odkaz"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Rekordér obrazovky"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Spracúva sa záznam obrazovky"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Zobrazuje sa upozornenie týkajúce sa relácie záznamu obrazovky"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Šetrič obrazovky"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Režim bez vyrušení"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Režimy priority"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nie sú k dispozícii žiadne spárované zariadenia"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Klepnutím pripojíte alebo odpojíte zariadenie"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Používať Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Pripojené"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Zdieľanie zvuku"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Klepnutím prepnete alebo budete zdieľať zvuk"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Uložené"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"odpojiť"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivovať"</string>
@@ -391,7 +392,7 @@
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Rekordér obrazovky"</string>
     <string name="performance" msgid="6552785217174378320">"Výkon"</string>
     <string name="user_interface" msgid="3712869377953950887">"Používateľské rozhranie"</string>
-    <string name="thermal" msgid="6758074791325414831">"Termálne"</string>
+    <string name="thermal" msgid="6758074791325414831">"Teplota"</string>
     <string name="custom" msgid="3337456985275158299">"Vlastné"</string>
     <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Nastavenia vlastnej stopy"</string>
     <string name="restore_default" msgid="5259420807486239755">"Obnoviť predvolené"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Otvoriť Nastavenia"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Iné zariadenie"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Prepnúť prehľad"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Režimy priority"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hotovo"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavenia"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Zapnuté"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Služba poskytujúca túto funkciu bude mať prístup k všetkým informáciám zobrazovaným na obrazovke alebo prehrávaným v zariadení počas nahrávania či prenosu. Patria medzi ne informácie, ako sú heslá, platobné údaje, fotky, správy a prehrávaný zvuk."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Aplikácia na zdieľanie alebo nahrávanie"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Chcete zdieľať obrazovku s aplikáciou <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Zdieľať jednu aplikáciu"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Zdieľať celú obrazovku"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Zdieľať jednu aplikáciu"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Zdieľať celú obrazovku"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Pri zdieľaní celej obrazovky vidí aplikácia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> všetko, čo sa na nej zobrazuje. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Pri zdieľaní aplikácie vidí aplikácia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> všetko, čo sa v zdieľanej aplikácii zobrazuje alebo prehráva. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Zdieľať obrazovku"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona zbalenia"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona rozbalenia"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"alebo"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto prechodu späť"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto prechodu domov"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Akčný kláves"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 22c5293..f2c466e 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> in druge odprte aplikacije so zaznale ta posnetek zaslona."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj v zapisek"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Vključi povezavo"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Snemalnik zaslona"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obdelava videoposnetka zaslona"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Nenehno obveščanje o seji snemanja zaslona"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Ohranjeval. zaslona"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne moti"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prednostni načini"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Na voljo ni nobene seznanjene naprave"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Dotaknite se za vzpostavitev ali prekinitev povezave z napravo"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Uporabi Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Deljenje zvoka"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Dotaknite se za preklop ali deljenje zvoka"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Shranjeno"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekinitev povezave"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviranje"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Odpri nastavitve"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Druga naprava"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Vklop/izklop pregleda"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prednostni načini"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Končano"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavitve"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Vklopljeno"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Storitev, ki zagotavlja to funkcijo, bo imela dostop do vseh podatkov, ki so med snemanjem ali predvajanjem prikazani na vašem zaslonu ali se predvajajo iz vaše naprave. To vključuje podatke, kot so gesla, podrobnosti o plačilu, fotografije, sporočila in zvok, ki ga predvajate."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Deljenje ali snemanje aplikacije"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Želite deliti zaslon z aplikacijo <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Deli eno aplikacijo"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Deli celoten zaslon"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Deli eno aplikacijo"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Deli celoten zaslon"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Pri deljenju celotnega zaslona je aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vidno vse na zaslonu. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Pri deljenju aplikacije je aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vidno vse, kar je prikazano ali predvajano v tej aplikaciji. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Deli zaslon"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona za strnitev"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona za razširitev"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ali"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Poteza za pomik nazaj"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Poteza za začetni zaslon"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Gumb za dejanje"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index a864df9..70ea421 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> dhe aplikacionet e tjera të hapura zbuluan këtë pamje ekrani."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Shto te shënimi"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Përfshi lidhjen"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Regjistruesi i ekranit"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Regjistrimi i ekranit po përpunohet"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Njoftim i vazhdueshëm për një seancë regjistrimi të ekranit"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Mbrojtësi i ekranit"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Eternet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Mos shqetëso"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modalitetet e përparësisë"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth-i"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nuk ofrohet për përdorim asnjë pajisje e çiftuar"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Trokit për të lidhur ose shkëputur një pajisje"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Përdor Bluetooth-in"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Lidhur"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ndarja e audios"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Trokit për të ndërruar ose ndarë audion"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Ruajtur"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"shkëput"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivizo"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Hap \"Cilësimet\""</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Pajisje tjetër"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kalo te përmbledhja"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modalitetet e përparësisë"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"U krye"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Cilësimet"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Aktiv"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Shërbimi që e ofron këtë funksion do të ketë qasje te të gjitha informacionet që janë të dukshme në ekran ose që luhen nga pajisja jote gjatë regjistrimit ose transmetimit. Kjo përfshin informacione, si p.sh.: fjalëkalimet, detajet e pagesave, fotografitë, mesazhet, si dhe audion që luan ti."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Ndaj ose regjistro një aplikacion"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Të ndahet ekrani yt me <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Ndaj një aplikacion"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Ndaj të gjithë ekranin"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Ndaj një aplikacion"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Ndaj të gjithë ekranin"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kur ti ndan të gjithë ekranin, çdo gjë në ekranin tënd është e dukshme për <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kur ti ndan një aplikacion, çdo gjë që shfaqet ose luhet në atë aplikacion është e dukshme për <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ndaj ekranin"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona e palosjes"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona e zgjerimit"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ose"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gjesti i kthimit prapa"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gjesti për të shkuar tek ekrani bazë"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tasti i veprimit"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 91fdf2a..6db372d 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> и друге отворене апликације су откриле овај снимак екрана."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Додај у белешку"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Уврсти линк"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Снимач екрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обрађујемо видео снимка екрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Обавештење о сесији снимања екрана је активно"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Чувар екрана"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Етернет"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не узнемиравај"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Приоритетни режими"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Није доступан ниједан упарени уређај"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Додирните да бисте повезали уређај или прекинули везу"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Користи Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Повезано"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Дељење звука"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Додирните да бисте пребацили или делили звук"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сачувано"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекините везу"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активирајте"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Отвори Подешавања"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Други уређај"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Укључи/искључи преглед"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Приоритетни режими"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Подешавања"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Укључено"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Услуга која пружа ову функцију ће имати приступ свим информацијама које се приказују на екрану или репродукују са уређаја током снимања или пребацивања. То обухвата информације попут лозинки, информација о плаћању, слика, порука и звука који пуштате."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Делите или снимите апликацију"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Желите да делите екран са апликацијом <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Дели једну апликацију"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Дели цео екран"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Дели једну апликацију"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Дели цео екран"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Када делите цео екран, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> види све што је на њему. Зато пазите на лозинке, информације о плаћању, поруке, слике, аудио и видео садржај."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Када делите апликацију, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> види сав садржај који се приказује или пушта у њој. Зато пазите на лозинке, информације о плаћању, поруке, слике, аудио и видео садржај."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Дели екран"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Икона за скупљање"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Икона за проширивање"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"или"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Покрет за враћање"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Покрет за почетну страницу"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Тастер радњи"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index dfd65bb..225e3b3 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> och andra öppna appar identifierade skärmbilden."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Lägg till i anteckning"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Inkludera länk"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Skärminspelare"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandlar skärminspelning"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Avisering om att skärminspelning pågår"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Skärmsläckare"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Stör ej"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioriterade lägen"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Det finns inga kopplade enheter tillgängliga"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tryck för att ansluta eller koppla från en enhet"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Använd Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ansluten"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ljuddelning"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tryck för att byta eller dela ljud"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sparad"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"koppla från"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivera"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Öppna Inställningar"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Annan enhet"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aktivera och inaktivera översikten"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriterade lägen"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Klar"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Inställningar"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"På"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Den tjänst som tillhandahåller funktionen får åtkomst till all information som visas på skärmen eller spelas upp från enheten när du spelar in eller castar. Detta omfattar till exempel lösenord, betalningsuppgifter, foton, meddelanden och ljud som du spelar upp."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Dela eller spela in en app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vill du dela skärmen med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Dela en app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Dela hela skärmen"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Dela en app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Dela hela skärmen"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"När du delar hela skärmen är allt på skärmen synligt för <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton, ljud och video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"När du delar en app är allt som visas eller spelas upp i appen synligt för <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton, ljud och video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Dela skärmen"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikonen Komprimera"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikonen Utöka"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"eller"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Tillbaka-rörelse"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Rörelse för att öppna startskärmen"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Åtgärdstangent"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 809d2c4..9fa8e55 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> na zingine zinazotumika zimetambua picha hii ya skrini."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ongeza kwenye dokezo"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Jumuisha kiungo"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g> <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Kinasa Skrini"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Inachakata rekodi ya skrini"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Arifa inayoendelea ya kipindi cha kurekodi skrini"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Taswira ya skrini"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Usinisumbue"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Hali za kipaumbele"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Hakuna vifaa vilivyooanishwa vinavyopatikana"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Gusa ili uunganishe au utenganishe kifaa"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Tumia Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Imeunganishwa"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Kusikiliza Pamoja"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Gusa ili ubadilishe sauti au usikilize pamoja na wengine"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Imehifadhiwa"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ondoa"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"anza kutumia"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Fungua Mipangilio"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Kifaa kingine"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Washa Muhtasari"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Hali za kipaumbele"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Nimemaliza"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Mipangilio"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Imewashwa"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Huduma inayotoa utendaji huu itaweza kufikia maelezo yote yanayoonekana kwenye skrini yako au yanayochezwa kwenye kifaa chako wakati wa kurekodi au kutuma. Hii ni pamoja na maelezo kama vile manenosiri, maelezo ya malipo, picha, ujumbe na sauti unayocheza."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Kurekodi au kuruhusu programu ifikiwe"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ungependa kuruhusu <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ifikie skrini yako?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Ruhusu ufikiaji wa programu moja"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Ruhusu ufikiaji wa skrini nzima"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Ruhusu ufikiaji wa programu moja"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Ruhusu ufikiaji wa skrini nzima"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Unaporuhusu ufikiaji wa skrini nzima, chochote kilicho katika skrini yako kitaonekana kwa <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha, sauti na video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Unaporuhusu ufikiaji wa programu, chochote kinachoonyeshwa au kuchezwa katika programu hiyo kitaonekana kwa <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha, sauti na video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ruhusu ufikiaji wa skrini"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Kunja aikoni"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Panua aikoni"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"au"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Ishara ya kurudi nyuma"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Mguso wa kurudi kwenye skrini ya kwanza"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Kitufe cha vitendo"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index ee8e11f4..7acd1e8 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"இந்த ஸ்கிரீன்ஷாட்டை <xliff:g id="APPNAME">%1$s</xliff:g> மற்றும் திறந்திருக்கும் பிற ஆப்ஸ் கண்டறிந்துள்ளன."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"குறிப்பில் சேர்"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"இணைப்பைச் சேர்"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"ஸ்கிரீன் ரெக்கார்டர்"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ஸ்க்ரீன் ரெக்கார்டிங் செயலாக்கப்படுகிறது"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"திரை ரெக்கார்டிங் அமர்விற்கான தொடர் அறிவிப்பு"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"ஸ்கிரீன் சேவர்"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ஈதர்நெட்"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"தொந்தரவு செய்ய வேண்டாம்"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"முன்னுரிமைப் பயன்முறைகள்"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"புளூடூத்"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"இணைக்கப்பட்ட சாதனங்கள் இல்லை"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"சாதனத்தை இணைக்க/துண்டிக்க தட்டவும்"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"புளூடூத்தைப் பயன்படுத்துதல்"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"இணைக்கப்பட்டது"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ஆடியோ பகிர்வு"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ஆடியோவை மாற்ற அல்லது பகிர, தட்டவும்"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"சேமிக்கப்பட்டது"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"இணைப்பு நீக்கும்"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"செயல்படுத்தும்"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"அமைப்புகளைத் திற"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"பிற சாதனம்"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"மேலோட்டப் பார்வையை நிலைமாற்று"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"முன்னுரிமைப் பயன்முறைகள்"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"முடிந்தது"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"அமைப்புகள்"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"இயக்கப்பட்டுள்ளது"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ உங்கள் திரையில் காட்டப்படுகின்ற அல்லது சாதனத்திலிருந்து பிளே செய்யப்படுகின்ற அனைத்துத் தகவல்களையும் இந்தச் செயல்பாட்டை வழங்கும் சேவையால் அணுக முடியும். கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், படங்கள், மெசேஜ்கள், நீங்கள் பிளே செய்யும் ஆடியோ போன்றவை இதிலடங்கும்."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ஆப்ஸைப் பகிர்தல் அல்லது ரெக்கார்டு செய்தல்"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> உடன் திரையைப் பகிரவா?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ஓர் ஆப்ஸைப் பகிர்"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"முழுத் திரையையும் பகிர்"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ஓர் ஆப்ஸைப் பகிர்"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"முழுத் திரையையும் பகிர்"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"உங்கள் முழுத்திரையையும் பகிரும்போது, திரையில் உள்ள அனைத்தும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> இல் தெரியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ஓர் ஆப்ஸைப் பகிரும்போது, அதில் காட்டப்படும்/பிளே செய்யப்படும் அனைத்தும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> இல் தெரியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"திரையைப் பகிர்"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"சுருக்குவதற்கான ஐகான்"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"விரிவாக்குவதற்கான ஐகான்"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"அல்லது"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"பின்செல்வதற்கான சைகை"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"முகப்பிற்குச் செல்வதற்கான சைகை"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ஆக்ஷன் பட்டன்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index d09f3ec..5cba2ef 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g>, ఇతర ఓపెన్ యాప్‌లు ఈ స్క్రీన్‌షాట్‌ను గుర్తించాయి."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"గమనికకు జోడించండి"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"లింక్‌ను చేర్చండి"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"స్క్రీన్ రికార్డర్"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"స్క్రీన్ రికార్డింగ్ అవుతోంది"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"స్క్రీన్ రికార్డ్ సెషన్ కోసం ఆన్‌గోయింగ్ నోటిఫికేషన్"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"స్క్రీన్ సేవర్"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ఈథర్‌నెట్"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"అంతరాయం కలిగించవద్దు"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"ముఖ్యమైన ఫైల్స్ మోడ్స్"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"బ్లూటూత్"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"జత చేసిన పరికరాలు ఏవీ అందుబాటులో లేవు"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"పరికరాన్ని కనెక్ట్ చేయడానికి లేదా డిస్‌కనెక్ట్ చేయడానికి ట్యాప్ చేయండి"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"బ్లూటూత్ వాడండి"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"కనెక్ట్ అయింది"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ఆడియో షేరింగ్"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ఆడియోను మార్చడానికి లేదా షేర్ చేయడానికి ట్యాప్ చేయండి"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"సేవ్ అయ్యింది"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"డిస్‌కనెక్ట్ చేయండి"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"యాక్టివేట్ చేయండి"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"సెట్టింగ్‌లను తెరవండి"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"ఇతర పరికరం"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"స్థూలదృష్టిని టోగుల్ చేయి"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ముఖ్యమైన ఫైళ్ల మోడ్స్"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"పూర్తయింది"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"సెట్టింగ్‌లు"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"ఆన్‌లో ఉంది"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు మీ స్క్రీన్‌పై చూపబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన సమాచారం మొత్తాన్ని, ఈ ఫంక్షన్‌ను అందిస్తున్న సర్వీస్ యాక్సెస్ చేయగలదు. ఈ సమాచారంలో, పాస్‌వర్డ్‌లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్‌లు, మీరు ప్లే చేసే ఆడియో వంటివి ఉంటాయి."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"యాప్‌ను షేర్ చేయండి లేదా రికార్డ్ చేయండి"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"మీ స్క్రీన్‌ను <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‌తో షేర్ చేయండి?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ఒక యాప్‌ను షేర్ చేయండి"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"మొత్తం స్క్రీన్‌ను షేర్ చేయండి"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ఒక యాప్‌ను షేర్ చేయండి"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"మొత్తం స్క్రీన్‌ను షేర్ చేయండి"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"మీ మొత్తం స్క్రీన్‌ను మీరు షేర్ చేసేటప్పుడు, మీ స్క్రీన్‌పై ఉన్నవన్నీ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‌కు కనిపిస్తాయి. కాబట్టి పాస్‌వర్డ్‌లు, పేమెంట్ వివరాలు, మెసేజ్‌లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"మీరు యాప్‌ను షేర్ చేసేటప్పుడు, సంబంధిత యాప్‌లో కనిపించేవి లేదా ప్లే అయ్యేవన్నీ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‌కు కనిపిస్తాయి. కాబట్టి పాస్‌వర్డ్‌లు, పేమెంట్ వివరాలు, మెసేజ్‌లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"స్క్రీన్‌ను షేర్ చేయండి"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"కుదించండి చిహ్నం"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"విస్తరించండి చిహ్నం"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"లేదా"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"వెనుకకు పంపే సంజ్ఞ"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"హోమ్‌కు పంపే సంజ్ఞ"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"యాక్షన్ కీ"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index ddea72f..905ab98 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> และแอปอื่นๆ ที่เปิดอยู่ตรวจพบภาพหน้าจอนี้"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"เพิ่มลงในโน้ต"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"รวมลิงก์"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"โปรแกรมบันทึกหน้าจอ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"กำลังประมวลผลการอัดหน้าจอ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"การแจ้งเตือนต่อเนื่องสำหรับเซสชันการบันทึกหน้าจอ"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"ภาพพักหน้าจอ"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"อีเทอร์เน็ต"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"ห้ามรบกวน"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"โหมดสำคัญ"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"บลูทูธ"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ไม่มีอุปกรณ์ที่จับคู่ที่สามารถใช้ได้"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"แตะเพื่อเชื่อมต่อหรือยกเลิกการเชื่อมต่ออุปกรณ์"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ใช้บลูทูธ"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"เชื่อมต่อแล้ว"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"การแชร์เสียง"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"แตะเพื่อสลับหรือแชร์เสียง"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"บันทึกแล้ว"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ยกเลิกการเชื่อมต่อ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"เปิดใช้งาน"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"เปิดการตั้งค่า"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"อุปกรณ์อื่น"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"สลับภาพรวม"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"โหมดสำคัญ"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"เสร็จสิ้น"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"การตั้งค่า"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"เปิด"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"บริการที่มีฟังก์ชันนี้จะมีสิทธิ์เข้าถึงข้อมูลทั้งหมดที่ปรากฏบนหน้าจอหรือเปิดจากอุปกรณ์ของคุณขณะบันทึกหรือแคสต์ ซึ่งรวมถึงข้อมูลอย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน รูปภาพ ข้อความ และเสียงที่คุณเล่น"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"แชร์หรือบันทึกแอป"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"แชร์หน้าจอกับ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ไหม"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"แชร์แอปเดียว"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"แชร์ทั้งหน้าจอ"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"แชร์แอปเดียว"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"แชร์ทั้งหน้าจอ"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"เมื่อกำลังแชร์ทั้งหน้าจอ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะมองเห็นทุกสิ่งที่อยู่บนหน้าจอ ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"เมื่อกำลังแชร์แอป <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะมองเห็นทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าว ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"แชร์หน้าจอ"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ไอคอนยุบ"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ไอคอนขยาย"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"หรือ"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ท่าทางสัมผัสสำหรับย้อนกลับ"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ท่าทางสัมผัสสำหรับหน้าแรก"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ปุ่มดำเนินการ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 7247757..5e9d720 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Na-detect ng <xliff:g id="APPNAME">%1$s</xliff:g> at ng iba pang bukas na app ang screenshot na ito."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Idagdag sa tala"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Isama ang link"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Recorder ng Screen"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pinoproseso screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Kasalukuyang notification para sa session ng pag-record ng screen"</string>
@@ -291,7 +292,7 @@
     <string name="start_dreams" msgid="9131802557946276718">"Screen saver"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Huwag Istorbohin"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Mga mode ng priyoridad"</string>
+    <string name="quick_settings_modes_label" msgid="879156359479504244">"Mga Mode"</string>
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Walang available na mga magkapares na device"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Mag-tap para magkonekta o magdiskonekta ng device"</string>
@@ -300,8 +301,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Gumamit ng Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Nakakonekta"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Pag-share ng Audio"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"I-tap para lumipat o magbahagi ng audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Na-save"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"idiskonekta"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"i-activate"</string>
@@ -433,7 +433,7 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Buksan ang Mga Setting"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Iba pang device"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"I-toggle ang Overview"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Mga priyoridad na mode"</string>
+    <string name="zen_modes_dialog_title" msgid="8854640808100096934">"Mga Mode"</string>
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Tapos na"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Mga Setting"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Naka-on"</string>
@@ -534,8 +534,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Ang serbisyong nagbibigay ng function na ito ay magkakaroon ng access sa lahat ng impormasyong nakikita sa iyong screen o pine-play mula sa device mo habang nagre-record o nagka-cast. Kasama rito ang impormasyong tulad ng mga password, detalye ng pagbabayad, larawan, mensahe, at audio na pine-play mo."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Magbahagi o mag-record ng app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ibahagi ang iyong screen sa <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Magbahagi ng isang app"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Ibahagi ang buong screen"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Mag-share ng isang app"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"I-share ang buong screen"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kapag ibinahagi mo ang iyong buong screen, makikita ng <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ang kahit anong nasa screen mo. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kapag nagbabahagi ka ng app, makikita ng <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ang kahit anong ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ibahagi ang screen"</string>
@@ -1387,6 +1391,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"I-collapse ang icon"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"I-expand ang icon"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Galaw para bumalik"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Galaw para sa Home"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 067d207..db49402 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ve diğer açık uygulamalar bu ekran görüntüsünü algıladı."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Nota ekle"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Bağlantıyı dahil et"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Ekran Kaydedicisi"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran kaydı işleniyor"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekran kaydı oturumu için devam eden bildirim"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Ekran koruyucu"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Rahatsız Etmeyin"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Öncelik modları"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Kullanılabilir eşlenmiş cihaz yok"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Cihaz bağlamak veya cihazın bağlantısını kesmek için dokunun"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth\'u kullan"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Bağlandı"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ses Paylaşımı"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Geçiş yapmak veya ses paylaşmak için dokunun"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Kaydedildi"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"bağlantıyı kes"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"etkinleştir"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Ayarlar\'ı aç"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Diğer cihaz"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Genel bakışı aç/kapat"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Öncelik modları"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Bitti"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ayarlar"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Açık"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Bu işlevi sağlayan hizmet, ekranınızda görünen veya kayıt ya da yayın sırasında cihazınızdan oynatılan tüm bilgilere erişecektir. Bu bilgiler arasında şifreler, ödeme detayları, fotoğraflar, mesajlar ve çaldığınız sesler gibi bilgiler yer alır."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Uygulamayı paylaşın veya kaydedin"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ekranınız <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> uygulamasıyla paylaşılsın mı?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Tek bir uygulamayı paylaş"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Tüm ekranı paylaş"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Tek bir uygulamayı paylaş"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Tüm ekranı paylaş"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, tüm ekranınızı paylaştığınızda ekranınızdaki her şeyi görebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, bir uygulamayı paylaştığınızda o uygulamada gösterilen veya oynatılan her şeyi görebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ekranı paylaş"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Daralt simgesi"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Genişlet simgesi"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"veya"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Geri hareketi"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Ana sayfa hareketi"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Eylem tuşu"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 7ffb958..6d881df 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> та інші відкриті додатки виявили цей знімок екрана."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Додати до примітки"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Додати посилання"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Запис відео з екрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обробка записування екрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Сповіщення про сеанс запису екрана"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Заставка"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не турбувати"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Режими пріоритету"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Немає спарених пристроїв"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Натисніть, щоб під’єднати або від’єднати пристрій"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Увімкнути Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Підключено"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Надсилання аудіо"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Натисніть, щоб змінити режим або надіслати аудіо"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Збережено"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"від’єднати"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активувати"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Відкрити налаштування"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Інший пристрій"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Увімкнути або вимкнути огляд"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Режими пріоритету"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Налаштування"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Увімкнено"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Сервіс, що надає цю функцію, матиме доступ до всієї інформації, яка з’являється на екрані або відтворюється на пристрої під час запису чи трансляції, зокрема до паролів, платіжної інформації, фотографій, повідомлень і аудіофайлів."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Показувати або записувати додаток"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Показати екран для додатка <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Показати один додаток"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Показати весь екран"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Показати один додаток"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Показати весь екран"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Коли ви показуєте весь екран, для додатка <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> стає видимим увесь контент на ньому. Тому будьте обережні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Коли ви показуєте додаток, для додатка <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> стає видимим увесь контент, що відображається або відтворюється в ньому. Тому будьте обережні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Показати екран"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Значок згортання"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Значок розгортання"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"або"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Жест \"Назад\""</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жест переходу на головний екран"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Клавіша дії"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index b2d4a11..628d660 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"‫<xliff:g id="APPNAME">%1$s</xliff:g> اور دیگر کھلی ایپس نے اس اسکرین شاٹ کا پتا لگایا۔"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"نوٹ میں شامل کریں"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"لنک شامل کریں"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"اسکرین ریکارڈر"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"سکرین ریکارڈنگ پروسیس ہورہی ہے"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"اسکرین ریکارڈ سیشن کیلئے جاری اطلاع"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"اسکرین سیور"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"ایتھرنیٹ"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"ڈسٹرب نہ کریں"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"ترجیحی وضع"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"بلوٹوتھ"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"کوئی جوڑا بنائے ہوئے آلات دستیاب نہیں ہیں"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"کسی آلے کو منسلک یا غیر منسلک کرنے کے لیے تھپتھپائیں"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"بلوٹوتھ استعمال کریں"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"منسلک ہے"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"آڈیو کا اشتراک"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"آڈیو پر سوئچ کرنے یا اس کا اشتراک کرنے کے لیے تھپتھپائیں"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"محفوظ ہے"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"غیر منسلک کریں"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"فعال کریں"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ترتیبات کھولیں"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"دوسرا آلہ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"مجموعی جائزہ ٹوگل کریں"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ترجیحی وضع"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ہو گیا"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ترتیبات"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"آن ہے"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"اس فنکشن فراہم کرنے والی سروس کو اس تمام معلومات تک رسائی حاصل ہوگی جو آپ کی اسکرین پر نظر آتی ہے یا ریکارڈنگ یا کاسٹنگ کے دوران آپ کے آلے سے چلائی گئی ہے۔ اس میں پاس ورڈز، ادائیگی کی تفصیلات، تصاویر، پیغامات اور آپ کے ذریعے چلائی جانے والی آڈیو جیسی معلومات شامل ہے۔"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ایپ کا اشتراک یا ریکارڈ کریں"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کے ساتھ اپنی اسکرین کا اشتراک کریں؟"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ایک ایپ کا اشتراک کریں"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"پوری اسکرین کا اشتراک کریں"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ایک ایپ کا اشتراک کریں"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"پوری اسکرین کا اشتراک کریں"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"آپ کے اپنی پوری اسکرین کا اشتراک کرنے پر آپ کی اسکرین پر ہر چیز <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کیلئے مرئی ہوجاتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"آپ کے کسی ایپ کا اشتراک کرنے پر اس ایپ میں دکھائی گئی یا چلائی گئی ہر چیز <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کیلئے مرئی ہو جاتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"اسکرین کا اشتراک کریں"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"آئیکن سکیڑیں"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"آئیکن پھیلائیں"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"یا"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"پیچھے جانے کا اشارہ"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ہوم کا اشارہ"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ایکشن کلید"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 4b488a25..f0988ed 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> va boshqa ochiq ilovalar skrinshot olinganini aniqladi."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Qaydga qoʻshish"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Havolani kiritish"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g>, <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Ekranni yozib olish"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran yozib olinmoqda"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekrandan yozib olish seansi uchun joriy bildirishnoma"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Ekran lavhasi"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Bezovta qilinmasin"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Muhim rejimlar"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Ulangan qurilmalar topilmadi"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Qurilma ulash yoki uzish uchun tegining"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth ishlatish"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ulangan"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio ulashuvi"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Audioni almashtirish yoki ulashish uchun bosing"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saqlangan"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"uzish"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"faollashtirish"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Sozlamalarni ochish"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Boshqa qurilma"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Umumiy nazar rejimini almashtirish"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Muhim rejimlar"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Tayyor"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Sozlamalar"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Yoniq"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Bu funksiyani taʼminlovchi xizmat ekranda chiqqan yoki yozib olish va translatsiya vaqtida ijro etilgan barcha axborotlarga ruxsat oladi. Bu axborotlar parollar, toʻlov tafsilotlari, rasmlar, xabarlar va ijro etilgan audiolardan iborat boʻlishi mumkin."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Ilovani ulashish yoki yozib olish"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ekraningiz <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> bilan ulashilsinmi?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Bitta ilovani namoyish qilish"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Butun ekranni namoyish qilish"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Bitta ilovani namoyish qilish"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Butun ekranni namoyish qilish"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Butun ekranni namoyish qilayotganingizda, ekrandagi barcha narsalaringiz <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ga koʻrinadi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Ilovani namoyish qilayotganingizda oʻsha ilova ichida koʻrsatilayotgan yoki ijro qilinayotganlar <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ga koʻrinadi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ekranni namoyish qilish"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Yigʻish belgisi"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Yoyish belgisi"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"yoki"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Orqaga qaytish ishorasi"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Asosiy ekran ishorasi"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Amal tugmasi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 2e06f72..6ad5db4 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> và các ứng dụng đang mở khác đã phát hiện thấy ảnh chụp màn hình này."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Thêm vào ghi chú"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Thêm đường liên kết"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Trình ghi màn hình"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Đang xử lý video ghi màn hình"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Thông báo đang diễn ra về phiên ghi màn hình"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Trình bảo vệ m.hình"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Không làm phiền"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Chế độ ưu tiên"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Không có thiết bị nào được ghép nối"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Nhấn để kết nối/ngắt kết nối với một thiết bị"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bật Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Đã kết nối"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Chia sẻ âm thanh"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Nhấn để chuyển hoặc chia sẻ âm thanh"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Đã lưu"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ngắt kết nối"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"kích hoạt"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Mở phần Cài đặt"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Thiết bị khác"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Bật/tắt chế độ xem Tổng quan"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Chế độ ưu tiên"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Xong"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Cài đặt"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Đang bật"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Dịch vụ cung cấp chức năng này có quyền truy cập vào tất cả thông tin xuất hiện trên màn hình của bạn hoặc phát trên thiết bị của bạn trong khi ghi hoặc truyền, bao gồm cả thông tin như mật khẩu, thông tin thanh toán, ảnh, tin nhắn và âm thanh mà bạn phát."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Chia sẻ hoặc ghi một ứng dụng"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Chia sẻ màn hình của bạn với <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Chia sẻ một ứng dụng"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Chia sẻ toàn bộ màn hình"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Chia sẻ một ứng dụng"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Chia sẻ toàn bộ màn hình"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Khi bạn chia sẻ toàn bộ màn hình, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ thấy được mọi nội dung trên màn hình của bạn. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Khi bạn chia sẻ một ứng dụng, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ thấy được mọi nội dung hiển thị hoặc phát trong ứng dụng đó. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Chia sẻ màn hình"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Biểu tượng Thu gọn"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Biểu tượng Mở rộng"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"hoặc"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Cử chỉ quay lại"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Cử chỉ chuyển đến màn hình chính"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Phím hành động"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 0a96fc2..35f8851 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> 及其他打开的应用检测到此屏幕截图。"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"添加到备注中"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"包括链接"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>⁠"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"屏幕录制器"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在处理屏幕录制视频"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持续显示屏幕录制会话通知"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"屏保"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"有线网络"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"勿扰"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"优先模式"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"蓝牙"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"没有可用的配对设备"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"点按即可连接设备或断开设备连接"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"启用蓝牙"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已连接"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音频分享"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"点按即可切换或分享音频"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已保存"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"断开连接"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"启用"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"打开“设置”"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"其他设备"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切换概览"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"优先模式"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"完成"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"设置"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"已开启"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"在录制或投放内容时,提供此功能的服务将可访问屏幕上显示或设备中播放的所有信息,其中包括密码、付款信息、照片、消息及播放的音频等信息。"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"分享或录制应用"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"要与“<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>”共享屏幕吗?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"共享一个应用"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"共享整个屏幕"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"共享一个应用"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"共享整个屏幕"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"当您共享整个屏幕时,屏幕上的所有内容均对“<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>”可见。因此,请务必小心操作,谨防泄露密码、付款信息、消息、照片、音频、视频等。"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"当您共享一个应用时,该应用中显示或播放的所有内容均对“<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>”可见。因此,请务必小心操作,谨防泄露密码、付款信息、消息、照片、音频、视频等。"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"共享屏幕"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"收起图标"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"展开图标"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"或"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"返回手势"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"主屏幕手势"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"快捷操作按键"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 6b5edff..359b3cc 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> 和其他開啟的應用程式偵測到此螢幕截圖。"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"新增至筆記"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"加入連結"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"螢幕錄影機"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在處理螢幕錄影內容"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示錄影畫面工作階段通知"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"螢幕保護程式"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"以太網"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"請勿騷擾"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"優先模式"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"藍牙"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"找不到配對的裝置"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"輕按即可連結或解除連結裝置"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"使用藍牙"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已連接"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音訊分享功能"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"輕按即可切換或分享音訊"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已儲存"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"解除連結"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"啟動"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"開啟「設定」"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"其他裝置"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換概覽"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"優先模式"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"完成"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"開啟"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"在錄影或投放時,此功能的服務供應商可存取螢幕顯示或裝置播放的任何資料,當中包括密碼、付款資料、相片、訊息和播放的語音等資料。"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"分享或錄影應用程式"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"要與「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」分享螢幕畫面嗎?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"分享一個應用程式"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"分享整個螢幕畫面"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"分享一個應用程式"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"分享整個螢幕畫面"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"當你分享整個螢幕畫面時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可看到你畫面上的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"當你分享應用程式時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可看到該應用程式中顯示或播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"分享螢幕畫面"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"收合圖示"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"展開圖示"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"或"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"返去手勢"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"主畫面手勢"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"快捷操作鍵"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 78cd289..63b19d6b 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"「<xliff:g id="APPNAME">%1$s</xliff:g>」和其他開啟的應用程式偵測到這張螢幕截圖。"</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"新增至記事本"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"包含連結"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"螢幕錄影器"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"處理螢幕錄影內容"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示螢幕畫面錄製工作階段通知"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"螢幕保護程式"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"乙太網路"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"零打擾"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"優先模式"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"藍牙"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"找不到配對的裝置"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"輕觸即可連結/取消連結裝置"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"使用藍牙"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已連線"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音訊分享"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"輕觸即可切換或分享音訊"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已儲存"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"取消連結"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"啟用"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"開啟「設定」"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"其他裝置"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換總覽"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"優先模式"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"完成"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"開啟"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"當你錄製或投放內容時,提供這項功能的服務將可存取畫面上顯示的任何資訊或裝置播放的任何內容,包括密碼、付款資料、相片、訊息和你播放的音訊等資訊。"</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"分享或錄製應用程式"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"要使用「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」分享畫面嗎?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"分享單一應用程式的畫面"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"分享整個畫面"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"分享單一應用程式的畫面"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"分享整個畫面"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"當你分享整個畫面時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取畫面上的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"當你分享應用程式畫面時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取該應用程式顯示或播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"分享畫面"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"收合圖示"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"展開圖示"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"或"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"返回手勢"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"主畫面手勢"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"快捷操作鍵"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 8bcc3ed..048cb01 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -104,6 +104,7 @@
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"I-<xliff:g id="APPNAME">%1$s</xliff:g> namanye ama-app avuliwe athole lesi sithombe-skrini."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Engeza kunothi"</string>
     <string name="backlinks_include_link" msgid="4562093591148248158">"Faka ilinki"</string>
+    <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"Okokuqopha iskrini"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Icubungula okokuqopha iskrini"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Isaziso esiqhubekayo seseshini yokurekhoda isikrini"</string>
@@ -291,7 +292,8 @@
     <string name="start_dreams" msgid="9131802557946276718">"Isigciniskrini"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"I-Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ungaphazamisi"</string>
-    <string name="quick_settings_modes_label" msgid="5407025818652750501">"Amamodi okubalulekile"</string>
+    <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+    <skip />
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"I-Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Awekho amadivayisi abhanqiwe atholakalayo"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Thepha ukuze uxhumae noma ungaxhumi idivaysi"</string>
@@ -300,8 +302,7 @@
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Sebenzisa iBluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ixhunyiwe"</string>
     <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ukwabelana Ngokuqoshiwe"</string>
-    <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
-    <skip />
+    <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Thepha ukuze ushintshe noma wabelane ngokulalelwayo"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Ilondoloziwe"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"nqamula"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"yenza kusebenze"</string>
@@ -433,7 +434,8 @@
     <string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Vula Amasethingi"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Enye idivayisi"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Guqula ukubuka konke"</string>
-    <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Amamodi okubalulekile"</string>
+    <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+    <skip />
     <string name="zen_modes_dialog_done" msgid="6654130880256438950">"Kwenziwe"</string>
     <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Amasethingi"</string>
     <string name="zen_mode_on" msgid="9085304934016242591">"Vuliwe"</string>
@@ -534,8 +536,12 @@
     <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Isevisi enikezela ngalo msebenzi izothola ukufinyelela kulo lonke ulwazi olubonakalayo esikrinini sakho noma oludlalwa kusuka kudivayisi yakho ngenkathi urekhoda noma usakaza. Lokhu kubandakanya ulwazi olufana namaphasiwedi, imininingwane yenkokhelo, izithombe, imilayezo, nomsindo owudlalayo."</string>
     <string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Yabelana noma urekhode i-app"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Yabelana ngesikrini sakho ne-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Yabelana nge-app eyodwa"</string>
-    <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Yabelana ngesikrini sonke"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Yabelana nge-app eyodwa"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+    <skip />
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Yabelana ngesikrini sonke"</string>
+    <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+    <skip />
     <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Uma wabelana ngesikrini sakho sonke, noma yini esesikrinini sakho ibonakala ku-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yenkokhelo, imilayezo, izithombe, nomsindo nevidiyo."</string>
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Uma wabelana nge-app, noma yini eboniswayo noma edlalwayo kuleyo app ibonakala ku-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yenkokhelo, imilayezo, izithombe, nomsindo nevidiyo."</string>
     <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Yabelana ngesikrini"</string>
@@ -1387,6 +1393,18 @@
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Goqa isithonjana"</string>
     <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Nweba isithonjana"</string>
     <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"noma"</string>
+    <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+    <skip />
+    <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+    <skip />
+    <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+    <skip />
     <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Ukunyakazisa umzimba kwangemuva"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Ukunyakazisa umzimba kwasekhaya"</string>
     <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Inkinobho yokufinyelela"</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 141d035..e1808fa 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -2002,10 +2002,10 @@
     <!-- Shadow for dream overlay status bar complications -->
     <dimen name="dream_overlay_status_bar_key_text_shadow_dx">0.5dp</dimen>
     <dimen name="dream_overlay_status_bar_key_text_shadow_dy">0.5dp</dimen>
-    <dimen name="dream_overlay_status_bar_key_text_shadow_radius">1dp</dimen>
+    <dimen name="dream_overlay_status_bar_key_text_shadow_radius">3dp</dimen>
     <dimen name="dream_overlay_status_bar_ambient_text_shadow_dx">0.5dp</dimen>
     <dimen name="dream_overlay_status_bar_ambient_text_shadow_dy">0.5dp</dimen>
-    <dimen name="dream_overlay_status_bar_ambient_text_shadow_radius">2dp</dimen>
+    <dimen name="dream_overlay_status_bar_ambient_text_shadow_radius">3dp</dimen>
     <dimen name="dream_overlay_icon_inset_dimen">0dp</dimen>
 
     <!-- Default device corner radius, used for assist UI -->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index dd84bc6..92e5432 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -271,7 +271,8 @@
                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
                         keyguardSecurityCallback, mLatencyTracker, mFalsingCollector,
                         emergencyButtonController, mMessageAreaControllerFactory,
-                        mDevicePostureController, mFeatureFlags, mSelectedUserInteractor);
+                        mDevicePostureController, mFeatureFlags, mSelectedUserInteractor,
+                        mMSDLPlayer);
             } else if (keyguardInputView instanceof KeyguardPasswordView) {
                 return new KeyguardPasswordViewController((KeyguardPasswordView) keyguardInputView,
                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index caa74780..f74d93e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -36,6 +36,7 @@
 import com.android.internal.widget.LockscreenCredential;
 import com.android.keyguard.EmergencyButtonController.EmergencyButtonCallback;
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticHelper;
 import com.android.systemui.classifier.FalsingClassifier;
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.flags.FeatureFlags;
@@ -43,6 +44,8 @@
 import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
 
+import com.google.android.msdl.domain.MSDLPlayer;
+
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -67,6 +70,7 @@
     private LockPatternView mLockPatternView;
     private CountDownTimer mCountdownTimer;
     private AsyncTask<?, ?, ?> mPendingLockCheck;
+    private MSDLPlayer mMSDLPlayer;
 
     private EmergencyButtonCallback mEmergencyButtonCallback = new EmergencyButtonCallback() {
         @Override
@@ -75,6 +79,10 @@
         }
     };
 
+    private final LockPatternView.ExternalHapticsPlayer mExternalHapticsPlayer = () -> {
+        BouncerHapticHelper.INSTANCE.playPatternDotFeedback(mMSDLPlayer, mView);
+    };
+
     /**
      * Useful for clearing out the wrong pattern after a delay
      */
@@ -166,6 +174,10 @@
                 boolean isValidPattern) {
             boolean dismissKeyguard = mSelectedUserInteractor.getSelectedUserId() == userId;
             if (matched) {
+                BouncerHapticHelper.INSTANCE.playMSDLAuthenticationFeedback(
+                        /* authenticationSucceeded= */true,
+                        /* player =*/mMSDLPlayer
+                );
                 getKeyguardSecurityCallback().reportUnlockAttempt(userId, true, 0);
                 if (dismissKeyguard) {
                     mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
@@ -173,6 +185,10 @@
                     getKeyguardSecurityCallback().dismiss(true, userId, SecurityMode.Pattern);
                 }
             } else {
+                BouncerHapticHelper.INSTANCE.playMSDLAuthenticationFeedback(
+                        /* authenticationSucceeded= */false,
+                        /* player =*/mMSDLPlayer
+                );
                 mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
                 if (isValidPattern) {
                     getKeyguardSecurityCallback().reportUnlockAttempt(userId, false, timeoutMs);
@@ -200,7 +216,7 @@
             EmergencyButtonController emergencyButtonController,
             KeyguardMessageAreaController.Factory messageAreaControllerFactory,
             DevicePostureController postureController, FeatureFlags featureFlags,
-            SelectedUserInteractor selectedUserInteractor) {
+            SelectedUserInteractor selectedUserInteractor, MSDLPlayer msdlPlayer) {
         super(view, securityMode, keyguardSecurityCallback, emergencyButtonController,
                 messageAreaControllerFactory, featureFlags, selectedUserInteractor);
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -212,6 +228,7 @@
                 featureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE));
         mLockPatternView = mView.findViewById(R.id.lockPatternView);
         mPostureController = postureController;
+        mMSDLPlayer = msdlPlayer;
     }
 
     @Override
@@ -249,6 +266,7 @@
         if (deadline != 0) {
             handleAttemptLockout(deadline);
         }
+        mLockPatternView.setExternalHapticsPlayer(mExternalHapticsPlayer);
     }
 
     @Override
@@ -262,6 +280,7 @@
             cancelBtn.setOnClickListener(null);
         }
         mPostureController.removeCallback(mPostureCallback);
+        mLockPatternView.setExternalHapticsPlayer(null);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonModeObserver.java b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonModeObserver.java
index 2c97d62..4d5e717 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonModeObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonModeObserver.java
@@ -28,6 +28,7 @@
 
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.SecureSettings;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -68,8 +69,9 @@
     }
 
     @Inject
-    public AccessibilityButtonModeObserver(Context context, UserTracker userTracker) {
-        super(context, userTracker, Settings.Secure.ACCESSIBILITY_BUTTON_MODE);
+    public AccessibilityButtonModeObserver(
+            Context context, UserTracker userTracker, SecureSettings secureSettings) {
+        super(context, userTracker, secureSettings, Settings.Secure.ACCESSIBILITY_BUTTON_MODE);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserver.java b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserver.java
index 53a21b3..1363b1c 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserver.java
@@ -24,6 +24,7 @@
 
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.SecureSettings;
 
 import javax.inject.Inject;
 
@@ -49,8 +50,9 @@
     }
 
     @Inject
-    public AccessibilityButtonTargetsObserver(Context context, UserTracker userTracker) {
-        super(context, userTracker, Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
+    public AccessibilityButtonTargetsObserver(
+            Context context, UserTracker userTracker, SecureSettings secureSettings) {
+        super(context, userTracker, secureSettings, Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserver.java b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserver.java
index c944878..736217a 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserver.java
@@ -24,6 +24,7 @@
 
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.SecureSettings;
 
 import javax.inject.Inject;
 
@@ -49,8 +50,9 @@
     }
 
     @Inject
-    public AccessibilityGestureTargetsObserver(Context context, UserTracker userTracker) {
-        super(context, userTracker, Settings.Secure.ACCESSIBILITY_GESTURE_TARGETS);
+    public AccessibilityGestureTargetsObserver(
+            Context context, UserTracker userTracker, SecureSettings secureSettings) {
+        super(context, userTracker, secureSettings, Settings.Secure.ACCESSIBILITY_GESTURE_TARGETS);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MirrorWindowControl.java b/packages/SystemUI/src/com/android/systemui/accessibility/MirrorWindowControl.java
index 443441f..eb4de68 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MirrorWindowControl.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MirrorWindowControl.java
@@ -18,6 +18,9 @@
 
 import static android.view.WindowManager.LayoutParams;
 
+import static com.android.app.viewcapture.ViewCaptureFactory.getViewCaptureAwareWindowManagerInstance;
+import static com.android.systemui.Flags.enableViewCaptureTracing;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -29,8 +32,8 @@
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.WindowManager;
 
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
 import com.android.systemui.res.R;
 
 /**
@@ -70,11 +73,12 @@
      * @see #setDefaultPosition(LayoutParams)
      */
     private final Point mControlPosition = new Point();
-    private final WindowManager mWindowManager;
+    private final ViewCaptureAwareWindowManager mWindowManager;
 
     MirrorWindowControl(Context context) {
         mContext = context;
-        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        mWindowManager = getViewCaptureAwareWindowManagerInstance(mContext,
+                enableViewCaptureTracing());
     }
 
     public void setWindowDelegate(@Nullable MirrorWindowDelegate windowDelegate) {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java b/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java
index 326773f..c50cf85 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java
@@ -28,6 +28,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.SecureSettings;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -48,6 +49,7 @@
     private final UserTracker mUserTracker;
     @VisibleForTesting
     final ContentObserver mContentObserver;
+    private final SecureSettings mSecureSettings;
 
     private final String mKey;
 
@@ -55,7 +57,7 @@
     final List<T> mListeners = new ArrayList<>();
 
     protected SecureSettingsContentObserver(Context context, UserTracker userTracker,
-            String secureSettingsKey) {
+            SecureSettings secureSettings, String secureSettingsKey) {
         mKey = secureSettingsKey;
         mContentResolver = context.getContentResolver();
         mUserTracker = userTracker;
@@ -65,6 +67,7 @@
                 updateValueChanged();
             }
         };
+        mSecureSettings = secureSettings;
     }
 
     /**
@@ -80,9 +83,8 @@
         }
 
         if (mListeners.size() == 1) {
-            mContentResolver.registerContentObserver(
-                    Settings.Secure.getUriFor(mKey), /* notifyForDescendants= */
-                    false, mContentObserver, UserHandle.USER_ALL);
+            mSecureSettings.registerContentObserverForUserAsync(Settings.Secure.getUriFor(mKey),
+                    /* notifyForDescendants= */ false, mContentObserver, UserHandle.USER_ALL);
         }
     }
 
@@ -97,7 +99,7 @@
         mListeners.remove(listener);
 
         if (mListeners.isEmpty()) {
-            mContentResolver.unregisterContentObserver(mContentObserver);
+            mSecureSettings.unregisterContentObserverAsync(mContentObserver);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/data/model/CaptioningModel.kt b/packages/SystemUI/src/com/android/systemui/accessibility/data/model/CaptioningModel.kt
new file mode 100644
index 0000000..4eb2274
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/data/model/CaptioningModel.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 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.accessibility.data.model
+
+data class CaptioningModel(
+    val isSystemAudioCaptioningUiEnabled: Boolean,
+    val isSystemAudioCaptioningEnabled: Boolean,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/CaptioningRepository.kt b/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/CaptioningRepository.kt
index bf749d4..5414b62 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/CaptioningRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/CaptioningRepository.kt
@@ -16,98 +16,90 @@
 
 package com.android.systemui.accessibility.data.repository
 
+import android.annotation.SuppressLint
 import android.view.accessibility.CaptioningManager
+import com.android.systemui.accessibility.data.model.CaptioningModel
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.user.data.repository.UserRepository
+import com.android.systemui.user.utils.UserScopedService
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import javax.inject.Inject
 import kotlin.coroutines.CoroutineContext
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.channels.ProducerScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.callbackFlow
-import kotlinx.coroutines.flow.filterIsInstance
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.flow.shareIn
 import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 
 interface CaptioningRepository {
 
-    /** The system audio caption enabled state. */
-    val isSystemAudioCaptioningEnabled: StateFlow<Boolean>
+    /** Current state of Live Captions. */
+    val captioningModel: StateFlow<CaptioningModel?>
 
-    /** The system audio caption UI enabled state. */
-    val isSystemAudioCaptioningUiEnabled: StateFlow<Boolean>
-
-    /** Sets [isSystemAudioCaptioningEnabled]. */
+    /** Sets [CaptioningModel.isSystemAudioCaptioningEnabled]. */
     suspend fun setIsSystemAudioCaptioningEnabled(isEnabled: Boolean)
 }
 
-class CaptioningRepositoryImpl(
-    private val captioningManager: CaptioningManager,
-    private val backgroundCoroutineContext: CoroutineContext,
-    coroutineScope: CoroutineScope,
+@OptIn(ExperimentalCoroutinesApi::class)
+class CaptioningRepositoryImpl
+@Inject
+constructor(
+    private val userScopedCaptioningManagerProvider: UserScopedService<CaptioningManager>,
+    userRepository: UserRepository,
+    @Background private val backgroundCoroutineContext: CoroutineContext,
+    @Application coroutineScope: CoroutineScope,
 ) : CaptioningRepository {
 
-    private val captioningChanges: SharedFlow<CaptioningChange> =
-        callbackFlow {
-                val listener = CaptioningChangeProducingListener(this)
-                captioningManager.addCaptioningChangeListener(listener)
-                awaitClose { captioningManager.removeCaptioningChangeListener(listener) }
-            }
-            .shareIn(coroutineScope, SharingStarted.WhileSubscribed(), replay = 0)
+    @SuppressLint("NonInjectedService") // this uses user-aware context
+    private val captioningManager: StateFlow<CaptioningManager?> =
+        userRepository.selectedUser
+            .map { userScopedCaptioningManagerProvider.forUser(it.userInfo.userHandle) }
+            .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), null)
 
-    override val isSystemAudioCaptioningEnabled: StateFlow<Boolean> =
-        captioningChanges
-            .filterIsInstance(CaptioningChange.IsSystemAudioCaptioningEnabled::class)
-            .map { it.isEnabled }
-            .onStart { emit(captioningManager.isSystemAudioCaptioningEnabled) }
-            .stateIn(
-                coroutineScope,
-                SharingStarted.WhileSubscribed(),
-                captioningManager.isSystemAudioCaptioningEnabled,
-            )
-
-    override val isSystemAudioCaptioningUiEnabled: StateFlow<Boolean> =
-        captioningChanges
-            .filterIsInstance(CaptioningChange.IsSystemUICaptioningEnabled::class)
-            .map { it.isEnabled }
-            .onStart { emit(captioningManager.isSystemAudioCaptioningUiEnabled) }
-            .stateIn(
-                coroutineScope,
-                SharingStarted.WhileSubscribed(),
-                captioningManager.isSystemAudioCaptioningUiEnabled,
-            )
+    override val captioningModel: StateFlow<CaptioningModel?> =
+        captioningManager
+            .filterNotNull()
+            .flatMapLatest { it.captioningModel() }
+            .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), null)
 
     override suspend fun setIsSystemAudioCaptioningEnabled(isEnabled: Boolean) {
         withContext(backgroundCoroutineContext) {
-            captioningManager.isSystemAudioCaptioningEnabled = isEnabled
+            captioningManager.value?.isSystemAudioCaptioningEnabled = isEnabled
         }
     }
 
-    private sealed interface CaptioningChange {
+    private fun CaptioningManager.captioningModel(): Flow<CaptioningModel> {
+        return conflatedCallbackFlow {
+                val listener =
+                    object : CaptioningManager.CaptioningChangeListener() {
 
-        data class IsSystemAudioCaptioningEnabled(val isEnabled: Boolean) : CaptioningChange
+                        override fun onSystemAudioCaptioningChanged(enabled: Boolean) {
+                            trySend(Unit)
+                        }
 
-        data class IsSystemUICaptioningEnabled(val isEnabled: Boolean) : CaptioningChange
-    }
-
-    private class CaptioningChangeProducingListener(
-        private val scope: ProducerScope<CaptioningChange>
-    ) : CaptioningManager.CaptioningChangeListener() {
-
-        override fun onSystemAudioCaptioningChanged(enabled: Boolean) {
-            emitChange(CaptioningChange.IsSystemAudioCaptioningEnabled(enabled))
-        }
-
-        override fun onSystemAudioCaptioningUiChanged(enabled: Boolean) {
-            emitChange(CaptioningChange.IsSystemUICaptioningEnabled(enabled))
-        }
-
-        private fun emitChange(change: CaptioningChange) {
-            scope.launch { scope.send(change) }
-        }
+                        override fun onSystemAudioCaptioningUiChanged(enabled: Boolean) {
+                            trySend(Unit)
+                        }
+                    }
+                addCaptioningChangeListener(listener)
+                awaitClose { removeCaptioningChangeListener(listener) }
+            }
+            .onStart { emit(Unit) }
+            .map {
+                CaptioningModel(
+                    isSystemAudioCaptioningEnabled = isSystemAudioCaptioningEnabled,
+                    isSystemAudioCaptioningUiEnabled = isSystemAudioCaptioningUiEnabled,
+                )
+            }
+            .flowOn(backgroundCoroutineContext)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/domain/interactor/CaptioningInteractor.kt b/packages/SystemUI/src/com/android/systemui/accessibility/domain/interactor/CaptioningInteractor.kt
index 1d493c6..840edf4 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/domain/interactor/CaptioningInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/domain/interactor/CaptioningInteractor.kt
@@ -17,16 +17,22 @@
 package com.android.systemui.accessibility.domain.interactor
 
 import com.android.systemui.accessibility.data.repository.CaptioningRepository
-import kotlinx.coroutines.flow.StateFlow
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.map
 
-class CaptioningInteractor(private val repository: CaptioningRepository) {
+@SysUISingleton
+class CaptioningInteractor @Inject constructor(private val repository: CaptioningRepository) {
 
-    val isSystemAudioCaptioningEnabled: StateFlow<Boolean>
-        get() = repository.isSystemAudioCaptioningEnabled
+    val isSystemAudioCaptioningEnabled: Flow<Boolean> =
+        repository.captioningModel.filterNotNull().map { it.isSystemAudioCaptioningEnabled }
 
-    val isSystemAudioCaptioningUiEnabled: StateFlow<Boolean>
-        get() = repository.isSystemAudioCaptioningUiEnabled
+    val isSystemAudioCaptioningUiEnabled: Flow<Boolean> =
+        repository.captioningModel.filterNotNull().map { it.isSystemAudioCaptioningUiEnabled }
 
-    suspend fun setIsSystemAudioCaptioningEnabled(enabled: Boolean) =
+    suspend fun setIsSystemAudioCaptioningEnabled(enabled: Boolean) {
         repository.setIsSystemAudioCaptioningEnabled(enabled)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
index d08653c3..60edaae 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
@@ -52,7 +52,6 @@
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.internal.logging.UiEventLogger;
 import com.android.settingslib.bluetooth.BluetoothCallback;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.HapClientProfile;
@@ -105,7 +104,8 @@
     private final AudioManager mAudioManager;
     private final LocalBluetoothProfileManager mProfileManager;
     private final HapClientProfile mHapClientProfile;
-    private final UiEventLogger mUiEventLogger;
+    private final HearingDevicesUiEventLogger mUiEventLogger;
+    private final int mLaunchSourceId;
     private HearingDevicesListAdapter mDeviceListAdapter;
     private HearingDevicesPresetsController mPresetsController;
     private Context mApplicationContext;
@@ -153,20 +153,22 @@
     public interface Factory {
         /** Create a {@link HearingDevicesDialogDelegate} instance */
         HearingDevicesDialogDelegate create(
-                boolean showPairNewDevice);
+                boolean showPairNewDevice,
+                @HearingDevicesUiEventLogger.LaunchSourceId int launchSource);
     }
 
     @AssistedInject
     public HearingDevicesDialogDelegate(
             @Application Context applicationContext,
             @Assisted boolean showPairNewDevice,
+            @Assisted @HearingDevicesUiEventLogger.LaunchSourceId int launchSourceId,
             SystemUIDialog.Factory systemUIDialogFactory,
             ActivityStarter activityStarter,
             DialogTransitionAnimator dialogTransitionAnimator,
             @Nullable LocalBluetoothManager localBluetoothManager,
             @Main Handler handler,
             AudioManager audioManager,
-            UiEventLogger uiEventLogger) {
+            HearingDevicesUiEventLogger uiEventLogger) {
         mApplicationContext = applicationContext;
         mShowPairNewDevice = showPairNewDevice;
         mSystemUIDialogFactory = systemUIDialogFactory;
@@ -178,6 +180,7 @@
         mProfileManager = localBluetoothManager.getProfileManager();
         mHapClientProfile = mProfileManager.getHapClientProfile();
         mUiEventLogger = uiEventLogger;
+        mLaunchSourceId = launchSourceId;
     }
 
     @Override
@@ -191,7 +194,7 @@
 
     @Override
     public void onDeviceItemGearClicked(@NonNull DeviceItem deviceItem, @NonNull View view) {
-        mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_GEAR_CLICK);
+        mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_GEAR_CLICK, mLaunchSourceId);
         dismissDialogIfExists();
         Intent intent = new Intent(ACTION_BLUETOOTH_DEVICE_DETAILS);
         Bundle bundle = new Bundle();
@@ -207,15 +210,17 @@
         CachedBluetoothDevice cachedBluetoothDevice = deviceItem.getCachedBluetoothDevice();
         switch (deviceItem.getType()) {
             case ACTIVE_MEDIA_BLUETOOTH_DEVICE, CONNECTED_BLUETOOTH_DEVICE -> {
-                mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DISCONNECT);
+                mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DISCONNECT,
+                        mLaunchSourceId);
                 cachedBluetoothDevice.disconnect();
             }
             case AVAILABLE_MEDIA_BLUETOOTH_DEVICE -> {
-                mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_SET_ACTIVE);
+                mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_SET_ACTIVE,
+                        mLaunchSourceId);
                 cachedBluetoothDevice.setActive();
             }
             case SAVED_BLUETOOTH_DEVICE -> {
-                mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_CONNECT);
+                mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_CONNECT, mLaunchSourceId);
                 cachedBluetoothDevice.connect();
             }
         }
@@ -275,7 +280,7 @@
         if (mLocalBluetoothManager == null) {
             return;
         }
-        mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DIALOG_SHOW);
+        mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DIALOG_SHOW, mLaunchSourceId);
         mPairButton = dialog.requireViewById(R.id.pair_new_device_button);
         mDeviceList = dialog.requireViewById(R.id.device_list);
         mPresetSpinner = dialog.requireViewById(R.id.preset_spinner);
@@ -363,7 +368,8 @@
         mPresetSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
             @Override
             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-                mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_PRESET_SELECT);
+                mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_PRESET_SELECT,
+                        mLaunchSourceId);
                 mPresetsController.selectPreset(
                         mPresetsController.getAllPresetInfo().get(position).getIndex());
             }
@@ -381,7 +387,7 @@
     private void setupPairNewDeviceButton(SystemUIDialog dialog, @Visibility int visibility) {
         if (visibility == VISIBLE) {
             mPairButton.setOnClickListener(v -> {
-                mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_PAIR);
+                mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_PAIR, mLaunchSourceId);
                 dismissDialogIfExists();
                 final Intent intent = new Intent(Settings.ACTION_HEARING_DEVICE_PAIRING_SETTINGS);
                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
@@ -485,7 +491,8 @@
             final String name = intent.getComponent() != null
                     ? intent.getComponent().flattenToString()
                     : intent.getPackage() + "/" + intent.getAction();
-            mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_RELATED_TOOL_CLICK, 0, name);
+            mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_RELATED_TOOL_CLICK,
+                    mLaunchSourceId, name);
             dismissDialogIfExists();
             mActivityStarter.postStartActivityDismissingKeyguard(intent, /* delay= */ 0,
                     mDialogTransitionAnimator.createActivityTransitionController(view));
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java
index bc4cb45..3d24177 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java
@@ -70,8 +70,10 @@
      * Shows the dialog.
      *
      * @param expandable {@link Expandable} from which the dialog is shown.
+     * @param launchSourceId the id indicates where the dialog is launched from.
      */
-    public void showDialog(Expandable expandable) {
+    public void showDialog(Expandable expandable,
+            @HearingDevicesUiEventLogger.LaunchSourceId int launchSourceId) {
         if (mDialog != null) {
             if (DEBUG) {
                 Log.d(TAG, "HearingDevicesDialog already showing. Destroy it first.");
@@ -91,7 +93,8 @@
                 });
         pairedHearingDeviceCheckTask.addListener(() -> {
             try {
-                mDialog = mDialogFactory.create(!pairedHearingDeviceCheckTask.get()).createDialog();
+                mDialog = mDialogFactory.create(!pairedHearingDeviceCheckTask.get(),
+                        launchSourceId).createDialog();
 
                 if (expandable != null) {
                     DialogTransitionAnimator.Controller controller =
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogReceiver.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogReceiver.java
index 6a34d19..02e65fd 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogReceiver.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.accessibility.hearingaid;
 
+import static com.android.systemui.accessibility.hearingaid.HearingDevicesUiEventLogger.LAUNCH_SOURCE_A11Y;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -46,7 +48,7 @@
         }
 
         if (ACTION.equals(intent.getAction())) {
-            mDialogManager.showDialog(/* view= */ null);
+            mDialogManager.showDialog(/* expandable= */ null, LAUNCH_SOURCE_A11Y);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.java
deleted file mode 100644
index 3fbe56e..0000000
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2024 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.accessibility.hearingaid;
-
-import com.android.internal.logging.UiEvent;
-import com.android.internal.logging.UiEventLogger;
-
-public enum HearingDevicesUiEvent implements UiEventLogger.UiEventEnum {
-
-    @UiEvent(doc = "Hearing devices dialog is shown")
-    HEARING_DEVICES_DIALOG_SHOW(1848),
-    @UiEvent(doc = "Pair new device")
-    HEARING_DEVICES_PAIR(1849),
-    @UiEvent(doc = "Connect to the device")
-    HEARING_DEVICES_CONNECT(1850),
-    @UiEvent(doc = "Disconnect from the device")
-    HEARING_DEVICES_DISCONNECT(1851),
-    @UiEvent(doc = "Set the device as active device")
-    HEARING_DEVICES_SET_ACTIVE(1852),
-    @UiEvent(doc = "Click on the device gear to enter device detail page")
-    HEARING_DEVICES_GEAR_CLICK(1853),
-    @UiEvent(doc = "Select a preset from preset spinner")
-    HEARING_DEVICES_PRESET_SELECT(1854),
-    @UiEvent(doc = "Click on related tool")
-    HEARING_DEVICES_RELATED_TOOL_CLICK(1856);
-
-    private final int mId;
-
-    HearingDevicesUiEvent(int id) {
-        mId = id;
-    }
-
-    @Override
-    public int getId() {
-        return mId;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.kt b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.kt
new file mode 100644
index 0000000..9e77b02
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 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.accessibility.hearingaid
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+
+enum class HearingDevicesUiEvent(private val id: Int) : UiEventLogger.UiEventEnum {
+
+    @UiEvent(doc = "Hearing devices dialog is shown") HEARING_DEVICES_DIALOG_SHOW(1848),
+    @UiEvent(doc = "Pair new device") HEARING_DEVICES_PAIR(1849),
+    @UiEvent(doc = "Connect to the device") HEARING_DEVICES_CONNECT(1850),
+    @UiEvent(doc = "Disconnect from the device") HEARING_DEVICES_DISCONNECT(1851),
+    @UiEvent(doc = "Set the device as active device") HEARING_DEVICES_SET_ACTIVE(1852),
+    @UiEvent(doc = "Click on the device gear to enter device detail page")
+    HEARING_DEVICES_GEAR_CLICK(1853),
+    @UiEvent(doc = "Select a preset from preset spinner") HEARING_DEVICES_PRESET_SELECT(1854),
+    @UiEvent(doc = "Click on related tool") HEARING_DEVICES_RELATED_TOOL_CLICK(1856);
+
+    override fun getId(): Int = this.id
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEventLogger.kt b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEventLogger.kt
new file mode 100644
index 0000000..0b32cfc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEventLogger.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 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.accessibility.hearingaid
+
+import android.annotation.IntDef
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+
+@SysUISingleton
+class HearingDevicesUiEventLogger @Inject constructor(private val uiEventLogger: UiEventLogger) {
+
+    /** Logs the given event */
+    fun log(event: UiEventLogger.UiEventEnum, launchSourceId: Int) {
+        log(event, launchSourceId, null)
+    }
+
+    fun log(event: UiEventLogger.UiEventEnum, launchSourceId: Int, pkgName: String?) {
+        uiEventLogger.log(event, launchSourceId, pkgName)
+    }
+
+    /**
+     * The possible launch source of hearing devices dialog
+     *
+     * @hide
+     */
+    @IntDef(LAUNCH_SOURCE_UNKNOWN, LAUNCH_SOURCE_A11Y, LAUNCH_SOURCE_QS_TILE)
+    annotation class LaunchSourceId
+
+    companion object {
+        const val LAUNCH_SOURCE_UNKNOWN = 0
+        const val LAUNCH_SOURCE_A11Y = 1 // launch from AccessibilityManagerService
+        const val LAUNCH_SOURCE_QS_TILE = 2
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 970fdea..69ab976 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -78,6 +78,8 @@
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 
+import com.google.android.msdl.domain.MSDLPlayer;
+
 import kotlin.Lazy;
 
 import kotlinx.coroutines.CoroutineScope;
@@ -157,6 +159,8 @@
 
     private final @Background DelayableExecutor mBackgroundExecutor;
 
+    private final MSDLPlayer mMSDLPlayer;
+
     // 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;
     // HAT received from LockSettingsService when credential is verified.
@@ -292,7 +296,8 @@
             @NonNull Provider<CredentialViewModel> credentialViewModelProvider,
             @NonNull @Background DelayableExecutor bgExecutor,
             @NonNull VibratorHelper vibratorHelper,
-            Lazy<ViewCapture> lazyViewCapture) {
+            Lazy<ViewCapture> lazyViewCapture,
+            @NonNull MSDLPlayer msdlPlayer) {
         super(config.mContext);
 
         mConfig = config;
@@ -309,6 +314,7 @@
                 .getDimension(R.dimen.biometric_dialog_animation_translation_offset);
         mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
         mBiometricCallback = new BiometricCallback();
+        mMSDLPlayer = msdlPlayer;
 
         final BiometricModalities biometricModalities = new BiometricModalities(
                 Utils.findFirstSensorProperties(fpProps, mConfig.mSensorIds),
@@ -379,7 +385,7 @@
                 getJankListener(mLayout, TRANSIT,
                         BiometricViewSizeBinder.ANIMATE_MEDIUM_TO_LARGE_DURATION_MS),
                 mBackgroundView, mBiometricCallback, mApplicationCoroutineScope,
-                vibratorHelper);
+                vibratorHelper, mMSDLPlayer);
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 097ab72..b39aae9 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -89,6 +89,8 @@
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.concurrency.Execution;
 
+import com.google.android.msdl.domain.MSDLPlayer;
+
 import dagger.Lazy;
 
 import kotlin.Unit;
@@ -183,6 +185,7 @@
     private final @Background DelayableExecutor mBackgroundExecutor;
     private final DisplayInfo mCachedDisplayInfo = new DisplayInfo();
     @NonNull private final VibratorHelper mVibratorHelper;
+    @NonNull private final MSDLPlayer mMSDLPlayer;
 
     private final kotlin.Lazy<ViewCapture> mLazyViewCapture;
 
@@ -742,7 +745,8 @@
             @Background DelayableExecutor bgExecutor,
             @NonNull UdfpsUtils udfpsUtils,
             @NonNull VibratorHelper vibratorHelper,
-            Lazy<ViewCapture> daggerLazyViewCapture) {
+            Lazy<ViewCapture> daggerLazyViewCapture,
+            @NonNull MSDLPlayer msdlPlayer) {
         mContext = context;
         mExecution = execution;
         mUserManager = userManager;
@@ -764,6 +768,7 @@
         mUdfpsUtils = udfpsUtils;
         mApplicationCoroutineScope = applicationCoroutineScope;
         mVibratorHelper = vibratorHelper;
+        mMSDLPlayer = msdlPlayer;
 
         mLogContextInteractor = logContextInteractor;
         mPromptSelectorInteractor = promptSelectorInteractorProvider;
@@ -1327,7 +1332,7 @@
                 wakefulnessLifecycle, userManager, lockPatternUtils,
                 mInteractionJankMonitor, mPromptSelectorInteractor, viewModel,
                 mCredentialViewModelProvider, bgExecutor, mVibratorHelper,
-                mLazyViewCapture);
+                mLazyViewCapture, mMSDLPlayer);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
index 0b440ad..e7e8d8f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
@@ -25,7 +25,6 @@
 import android.hardware.biometrics.Flags
 import android.hardware.face.FaceManager
 import android.util.Log
-import android.view.HapticFeedbackConstants
 import android.view.MotionEvent
 import android.view.View
 import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO
@@ -59,6 +58,7 @@
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.VibratorHelper
+import com.google.android.msdl.domain.MSDLPlayer
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.combine
@@ -83,6 +83,7 @@
         legacyCallback: Spaghetti.Callback,
         applicationScope: CoroutineScope,
         vibratorHelper: VibratorHelper,
+        msdlPlayer: MSDLPlayer,
     ): Spaghetti {
         val accessibilityManager = view.context.getSystemService(AccessibilityManager::class.java)!!
 
@@ -434,21 +435,27 @@
                 // Play haptics
                 launch {
                     viewModel.hapticsToPlay.collect { haptics ->
-                        if (haptics.hapticFeedbackConstant != HapticFeedbackConstants.NO_HAPTICS) {
-                            if (haptics.flag != null) {
-                                vibratorHelper.performHapticFeedback(
-                                    view,
-                                    haptics.hapticFeedbackConstant,
-                                    haptics.flag,
-                                )
-                            } else {
-                                vibratorHelper.performHapticFeedback(
-                                    view,
-                                    haptics.hapticFeedbackConstant,
-                                )
+                        when (haptics) {
+                            is PromptViewModel.HapticsToPlay.HapticConstant -> {
+                                if (haptics.flag != null) {
+                                    vibratorHelper.performHapticFeedback(
+                                        view,
+                                        haptics.constant,
+                                        haptics.flag,
+                                    )
+                                } else {
+                                    vibratorHelper.performHapticFeedback(
+                                        view,
+                                        haptics.constant,
+                                    )
+                                }
                             }
-                            viewModel.clearHaptics()
+                            is PromptViewModel.HapticsToPlay.MSDL -> {
+                                msdlPlayer.playToken(haptics.token, haptics.properties)
+                            }
+                            is PromptViewModel.HapticsToPlay.None -> {}
                         }
+                        viewModel.clearHaptics()
                     }
                 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
index 85c3ae3..d69e875 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
@@ -18,13 +18,11 @@
 
 import android.animation.Animator
 import android.animation.AnimatorSet
-import android.animation.ValueAnimator
 import android.graphics.Outline
 import android.graphics.Rect
 import android.transition.AutoTransition
 import android.transition.TransitionManager
 import android.util.TypedValue
-import android.view.Surface
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewOutlineProvider
@@ -413,13 +411,12 @@
                                     ANIMATE_SMALL_TO_MEDIUM_DURATION_MS.toLong()
                                 )
 
-                                TransitionManager.beginDelayedTransition(view, autoTransition)
-
                                 if (position.isLeft) {
                                     flipConstraintSet.applyTo(view)
                                 } else {
                                     mediumConstraintSet.applyTo(view)
                                 }
+                                TransitionManager.beginDelayedTransition(view, autoTransition)
                             }
                             size.isMedium -> {
                                 if (position.isLeft) {
@@ -428,14 +425,18 @@
                                     mediumConstraintSet.applyTo(view)
                                 }
                             }
-                            size.isLarge && currentSize.isMedium -> {
+                            size.isLarge -> {
                                 val autoTransition = AutoTransition()
                                 autoTransition.setDuration(
-                                    ANIMATE_MEDIUM_TO_LARGE_DURATION_MS.toLong()
+                                    if (currentSize.isSmall) {
+                                        ANIMATE_SMALL_TO_MEDIUM_DURATION_MS.toLong()
+                                    } else {
+                                        ANIMATE_MEDIUM_TO_LARGE_DURATION_MS.toLong()
+                                    }
                                 )
 
-                                TransitionManager.beginDelayedTransition(view, autoTransition)
                                 largeConstraintSet.applyTo(view)
+                                TransitionManager.beginDelayedTransition(view, autoTransition)
                             }
                         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index 4c2fe07..168ba11 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -35,7 +35,9 @@
 import android.util.RotationUtils
 import android.view.HapticFeedbackConstants
 import android.view.MotionEvent
+import com.android.keyguard.AuthInteractionProperties
 import com.android.launcher3.icons.IconProvider
+import com.android.systemui.Flags.msdlFeedback
 import com.android.systemui.biometrics.UdfpsUtils
 import com.android.systemui.biometrics.Utils
 import com.android.systemui.biometrics.Utils.isSystem
@@ -53,6 +55,8 @@
 import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus
 import com.android.systemui.res.R
 import com.android.systemui.util.kotlin.combine
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.android.msdl.domain.InteractionProperties
 import javax.inject.Inject
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.coroutineScope
@@ -245,8 +249,9 @@
     private val _forceLargeSize = MutableStateFlow(false)
     private val _forceMediumSize = MutableStateFlow(false)
 
-    private val _hapticsToPlay =
-        MutableStateFlow(HapticsToPlay(HapticFeedbackConstants.NO_HAPTICS, /* flag= */ null))
+    private val authInteractionProperties = AuthInteractionProperties()
+    private val _hapticsToPlay: MutableStateFlow<HapticsToPlay> =
+        MutableStateFlow(HapticsToPlay.None)
 
     /** Event fired to the view indicating a [HapticsToPlay] */
     val hapticsToPlay = _hapticsToPlay.asStateFlow()
@@ -939,26 +944,52 @@
     }
 
     private fun vibrateOnSuccess() {
-        _hapticsToPlay.value =
-            HapticsToPlay(
-                HapticFeedbackConstants.BIOMETRIC_CONFIRM,
-                null,
-            )
+        val haptics =
+            if (msdlFeedback()) {
+                HapticsToPlay.MSDL(MSDLToken.UNLOCK, authInteractionProperties)
+            } else {
+                HapticsToPlay.HapticConstant(
+                    HapticFeedbackConstants.BIOMETRIC_CONFIRM,
+                    flag = null,
+                )
+            }
+        _hapticsToPlay.value = haptics
     }
 
     private fun vibrateOnError() {
-        _hapticsToPlay.value =
-            HapticsToPlay(
-                HapticFeedbackConstants.BIOMETRIC_REJECT,
-                null,
-            )
+        val haptics =
+            if (msdlFeedback()) {
+                HapticsToPlay.MSDL(MSDLToken.FAILURE, authInteractionProperties)
+            } else {
+                HapticsToPlay.HapticConstant(
+                    HapticFeedbackConstants.BIOMETRIC_REJECT,
+                    flag = null,
+                )
+            }
+        _hapticsToPlay.value = haptics
     }
 
     /** Clears the [hapticsToPlay] variable by setting its constant to the NO_HAPTICS default. */
     fun clearHaptics() {
-        _hapticsToPlay.update { previous ->
-            HapticsToPlay(HapticFeedbackConstants.NO_HAPTICS, previous.flag)
-        }
+        _hapticsToPlay.update { HapticsToPlay.None }
+    }
+
+    /** The state of haptic feedback to play. */
+    sealed interface HapticsToPlay {
+        /**
+         * Haptics using [HapticFeedbackConstants]. It is composed by a [HapticFeedbackConstants]
+         * and a [HapticFeedbackConstants] flag.
+         */
+        data class HapticConstant(val constant: Int, val flag: Int?) : HapticsToPlay
+
+        /**
+         * Haptics using MSDL feedback. It is composed by a [MSDLToken] and optional
+         * [InteractionProperties]
+         */
+        data class MSDL(val token: MSDLToken, val properties: InteractionProperties?) :
+            HapticsToPlay
+
+        data object None : HapticsToPlay
     }
 
     companion object {
@@ -1095,9 +1126,3 @@
     val isStarted: Boolean
         get() = this == Normal || this == Delayed
 }
-
-/**
- * The state of haptic feedback to play. It is composed by a [HapticFeedbackConstants] and a
- * [HapticFeedbackConstants] flag.
- */
-data class HapticsToPlay(val hapticFeedbackConstant: Int, val flag: Int?)
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt
index f36ef66..8b5a09b 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt
@@ -34,10 +34,14 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.doze.DozeLogger
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
 import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.EmergencyDialerConstants
+import dagger.Lazy
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.Flow
@@ -69,6 +73,7 @@
     private val emergencyDialerIntentFactory: EmergencyDialerIntentFactory,
     private val metricsLogger: MetricsLogger,
     private val dozeLogger: DozeLogger,
+    private val sceneInteractor: Lazy<SceneInteractor>,
 ) {
     /** The bouncer action button. If `null`, the button should not be shown. */
     val actionButton: Flow<BouncerActionButtonModel?> =
@@ -158,14 +163,17 @@
     }
 
     private fun prepareToPerformAction() {
-        // TODO(b/308001302): Trigger occlusion and resetting bouncer state.
+        if (SceneContainerFlag.isEnabled) {
+            sceneInteractor.get().changeScene(Scenes.Lockscreen, "Bouncer action button clicked")
+        }
+
         metricsLogger.action(MetricsEvent.ACTION_EMERGENCY_CALL)
         activityTaskManager.stopSystemLockTaskMode()
     }
 
     @SuppressLint("MissingPermission")
     private fun returnToCall() {
-        telecomManager?.showInCallScreen(/* showDialpad = */ false)
+        telecomManager?.showInCallScreen(/* showDialpad= */ false)
     }
 
     private val <T> Flow<T>.asUnitFlow: Flow<Unit>
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticHelper.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticHelper.kt
new file mode 100644
index 0000000..1faacff
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticHelper.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 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.bouncer.ui.helper
+
+import android.view.HapticFeedbackConstants
+import android.view.View
+import com.android.keyguard.AuthInteractionProperties
+import com.android.systemui.Flags
+//noinspection CleanArchitectureDependencyViolation: Data layer only referenced for this enum class
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.android.msdl.domain.MSDLPlayer
+
+/** A helper object to deliver haptic feedback in bouncer interactions. */
+object BouncerHapticHelper {
+
+    private val authInteractionProperties = AuthInteractionProperties()
+
+    /**
+     * Deliver MSDL feedback as a result of authenticating through a bouncer.
+     *
+     * @param[authenticationSucceeded] Whether the authentication was successful or not.
+     * @param[player] The [MSDLPlayer] that delivers the correct feedback.
+     */
+    fun playMSDLAuthenticationFeedback(
+        authenticationSucceeded: Boolean,
+        player: MSDLPlayer?,
+    ) {
+        if (player == null || !Flags.msdlFeedback()) {
+            return
+        }
+
+        val token =
+            if (authenticationSucceeded) {
+                MSDLToken.UNLOCK
+            } else {
+                MSDLToken.FAILURE
+            }
+        player.playToken(token, authInteractionProperties)
+    }
+
+    /**
+     * Deliver feedback when dragging through cells in the pattern bouncer. This function can play
+     * MSDL feedback using a [MSDLPlayer], or fallback to a default haptic feedback using the
+     * [View.performHapticFeedback] API and a [View].
+     *
+     * @param[player] [MSDLPlayer] for MSDL feedback.
+     * @param[view] A [View] for default haptic feedback using [View.performHapticFeedback]
+     */
+    fun playPatternDotFeedback(player: MSDLPlayer?, view: View?) {
+        if (player == null || !Flags.msdlFeedback()) {
+            view?.performHapticFeedback(
+                HapticFeedbackConstants.VIRTUAL_KEY,
+                HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING,
+            )
+        } else {
+            player.playToken(MSDLToken.DRAG_INDICATOR)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index e1ba93c..83d4091 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -34,8 +34,6 @@
 import com.android.systemui.classifier.FalsingDataProvider.SessionListener;
 import com.android.systemui.classifier.HistoryTracker.BeliefListener;
 import com.android.systemui.dagger.qualifiers.TestHarness;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
@@ -396,6 +394,7 @@
                 || mDataProvider.isA11yAction()
                 || mDataProvider.isFromTrackpad()
                 || mDataProvider.isFromKeyboard()
+                || !mDataProvider.isTouchScreenSource()
                 || mDataProvider.isUnfolded();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
index 2eca02c..962ab99 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
@@ -21,6 +21,7 @@
 import android.hardware.SensorManager;
 import android.hardware.biometrics.BiometricSourceType;
 import android.util.Log;
+import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 
@@ -28,6 +29,7 @@
 
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.Flags;
 import com.android.systemui.communal.domain.interactor.CommunalInteractor;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -343,7 +345,9 @@
         // will be ignored by the collector until another MotionEvent.ACTION_DOWN is passed in.
         // avoidGesture must be called immediately following the MotionEvent.ACTION_DOWN, before
         // any other events are processed, otherwise the whole gesture will be recorded.
-        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+        //
+        // We should only delay processing of these events for touchscreen sources
+        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN && isTouchscreenSource(ev)) {
             // Make a copy of ev, since it will be recycled after we exit this method.
             mPendingDownEvent = MotionEvent.obtain(ev);
             mAvoidGesture = false;
@@ -410,6 +414,22 @@
         mFalsingDataProvider.onA11yAction();
     }
 
+    /**
+     * returns {@code true} if the device supports Touchscreen, {@code false} otherwise. Defaults to
+     * {@code true} if the device is {@code null}
+     */
+    private boolean isTouchscreenSource(MotionEvent ev) {
+        if (!Flags.nonTouchscreenDevicesBypassFalsing()) {
+            return true;
+        }
+        InputDevice device = ev.getDevice();
+        if (device != null) {
+            return device.supportsSource(InputDevice.SOURCE_TOUCHSCREEN);
+        } else {
+            return true;
+        }
+    }
+
     private boolean shouldSessionBeActive() {
         return mScreenOn
                 && (mState == StatusBarState.KEYGUARD)
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
index 1501701..769976e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
@@ -20,11 +20,13 @@
 
 import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
 import android.util.DisplayMetrics;
+import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.MotionEvent.PointerCoords;
 import android.view.MotionEvent.PointerProperties;
 
+import com.android.systemui.Flags;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -281,6 +283,9 @@
     }
 
     public boolean isFromTrackpad() {
+        if (Flags.nonTouchscreenDevicesBypassFalsing()) {
+            return false;
+        }
         if (mRecentMotionEvents.isEmpty()) {
             return false;
         }
@@ -290,6 +295,25 @@
                 || classification == MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE;
     }
 
+    /**
+     * returns {@code true} if the device supports Touchscreen, {@code false} otherwise. Defaults to
+     * {@code true} if the device is {@code null}
+     */
+    public boolean isTouchScreenSource() {
+        if (!Flags.nonTouchscreenDevicesBypassFalsing()) {
+            return true;
+        }
+        if (mRecentMotionEvents.isEmpty()) {
+            return true;
+        }
+        InputDevice device = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1).getDevice();
+        if (device != null) {
+            return device.supportsSource(InputDevice.SOURCE_TOUCHSCREEN);
+        } else {
+            return true;
+        }
+    }
+
     private void recalculateData() {
         if (!mDirty) {
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt
index b6ace81..9c4736a 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt
@@ -27,6 +27,7 @@
 import android.view.accessibility.AccessibilityNodeInfo
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
+import com.android.systemui.log.LongPressHandlingViewLogger
 import com.android.systemui.shade.TouchLogger
 import kotlin.math.pow
 import kotlin.math.sqrt
@@ -42,6 +43,8 @@
     context: Context,
     attrs: AttributeSet?,
     longPressDuration: () -> Long,
+    allowedTouchSlop: Int = ViewConfiguration.getTouchSlop(),
+    logger: LongPressHandlingViewLogger? = null,
 ) :
     View(
         context,
@@ -97,6 +100,8 @@
             },
             onSingleTapDetected = { listener?.onSingleTapDetected(this@LongPressHandlingView) },
             longPressDuration = longPressDuration,
+            allowedTouchSlop = allowedTouchSlop,
+            logger = logger,
         )
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt
index d3fc610..4e38a49 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt
@@ -17,7 +17,7 @@
 
 package com.android.systemui.common.ui.view
 
-import android.view.ViewConfiguration
+import com.android.systemui.log.LongPressHandlingViewLogger
 import kotlinx.coroutines.DisposableHandle
 
 /** Encapsulates logic to handle complex touch interactions with a [LongPressHandlingView]. */
@@ -35,6 +35,14 @@
     private val onSingleTapDetected: () -> Unit,
     /** Time for the touch to be considered a long-press in ms */
     var longPressDuration: () -> Long,
+    /**
+     * Default touch slop that is allowed, if the movement between [MotionEventModel.Down] and
+     * [MotionEventModel.Up] is more than [allowedTouchSlop] then the touch is not processed as
+     * single tap or a long press.
+     */
+    val allowedTouchSlop: Int,
+    /** Optional logger that can be passed in to log touch events */
+    val logger: LongPressHandlingViewLogger? = null,
 ) {
     sealed class MotionEventModel {
         object Other : MotionEventModel()
@@ -70,22 +78,26 @@
                 true
             }
             is MotionEventModel.Move -> {
-                if (event.distanceMoved > ViewConfiguration.getTouchSlop()) {
+                if (event.distanceMoved > allowedTouchSlop) {
+                    logger?.cancelingLongPressDueToTouchSlop(event.distanceMoved, allowedTouchSlop)
                     cancelScheduledLongPress()
                 }
                 false
             }
             is MotionEventModel.Up -> {
+                logger?.onUpEvent(event.distanceMoved, allowedTouchSlop, event.gestureDuration)
                 cancelScheduledLongPress()
                 if (
-                    event.distanceMoved <= ViewConfiguration.getTouchSlop() &&
+                    event.distanceMoved <= allowedTouchSlop &&
                         event.gestureDuration < longPressDuration()
                 ) {
+                    logger?.dispatchingSingleTap()
                     dispatchSingleTap()
                 }
                 false
             }
             is MotionEventModel.Cancel -> {
+                logger?.motionEventCancelled()
                 cancelScheduledLongPress()
                 false
             }
@@ -97,15 +109,18 @@
         x: Int,
         y: Int,
     ) {
+        val duration = longPressDuration()
+        logger?.schedulingLongPress(duration)
         scheduledLongPressHandle =
             postDelayed(
                 {
+                    logger?.longPressTriggered()
                     dispatchLongPress(
                         x = x,
                         y = y,
                     )
                 },
-                longPressDuration(),
+                duration,
             )
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt
index c69cea4..04393fe 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.CoreStartable
 import com.android.systemui.Flags.glanceableHubAllowKeyguardWhenDreaming
 import com.android.systemui.Flags.restartDreamOnUnocclude
+import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
 import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
@@ -55,6 +56,7 @@
     private val keyguardInteractor: KeyguardInteractor,
     private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
     private val dreamManager: DreamManager,
+    private val communalSceneInteractor: CommunalSceneInteractor,
     @Background private val bgScope: CoroutineScope,
 ) : CoreStartable {
     /** Flow that emits when the dream should be started underneath the glanceable hub. */
@@ -66,6 +68,8 @@
                 not(keyguardInteractor.isDreaming),
                 // TODO(b/362830856): Remove this workaround.
                 keyguardInteractor.isKeyguardShowing,
+                not(communalSceneInteractor.isLaunchingWidget),
+                not(keyguardInteractor.isKeyguardOccluded),
             )
             .filter { it }
 
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
index 21a704d..8818c3a 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
@@ -202,6 +202,13 @@
         return context.getSystemService(CaptioningManager.class);
     }
 
+    @Provides
+    @Singleton
+    static UserScopedService<CaptioningManager> provideUserScopedCaptioningManager(
+            Context context) {
+        return new UserScopedServiceImpl<>(context, CaptioningManager.class);
+    }
+
     /** */
     @Provides
     @Singleton
diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
index 3105527..43855d9 100644
--- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
@@ -19,6 +19,7 @@
 import android.hardware.input.InputManager
 import android.hardware.input.InputManager.KeyGestureEventListener
 import android.hardware.input.KeyGestureEvent
+import android.os.SystemProperties
 import com.android.systemui.CoreStartable
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.contextualeducation.GestureType
@@ -35,7 +36,10 @@
 import java.time.Clock
 import java.util.concurrent.Executor
 import javax.inject.Inject
-import kotlin.time.Duration.Companion.hours
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.days
+import kotlin.time.DurationUnit
+import kotlin.time.toDuration
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
@@ -58,7 +62,21 @@
     companion object {
         const val TAG = "KeyboardTouchpadEduInteractor"
         const val MAX_SIGNAL_COUNT: Int = 2
-        val usageSessionDuration = 72.hours
+        const val MAX_EDUCATION_SHOW_COUNT: Int = 2
+        val usageSessionDuration =
+            getDurationForConfig("persist.contextual_edu.usage_session_sec", 3.days)
+        val minIntervalBetweenEdu =
+            getDurationForConfig("persist.contextual_edu.edu_interval_sec", 7.days)
+
+        private fun getDurationForConfig(
+            systemPropertyKey: String,
+            defaultDuration: Duration
+        ): Duration =
+            SystemProperties.getLong(
+                    systemPropertyKey,
+                    /* defaultValue= */ defaultDuration.inWholeSeconds
+                )
+                .toDuration(DurationUnit.SECONDS)
     }
 
     private val _educationTriggered = MutableStateFlow<EducationInfo?>(null)
@@ -128,10 +146,20 @@
     }
 
     private fun isEducationNeeded(model: GestureEduModel): Boolean {
-        // Todo: b/354884305 - add complete education logic to show education in correct scenarios
+        val lessThanMaxEduCount = model.educationShownCount < MAX_EDUCATION_SHOW_COUNT
         val noShortcutTriggered = model.lastShortcutTriggeredTime == null
         val signalCountReached = model.signalCount >= MAX_SIGNAL_COUNT
-        return noShortcutTriggered && signalCountReached
+        val isPreviousEduOlderThanMinInterval =
+            if (model.educationShownCount == 1) {
+                model.lastEducationTime
+                    ?.plusSeconds(minIntervalBetweenEdu.inWholeSeconds)
+                    ?.isBefore(clock.instant()) ?: true
+            } else true
+
+        return lessThanMaxEduCount &&
+            noShortcutTriggered &&
+            signalCountReached &&
+            isPreviousEduOlderThanMinInterval
     }
 
     private fun isUsageSessionExpired(model: GestureEduModel): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 1bc91ca..67625d0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -81,6 +81,7 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardEnabledInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardStateCallbackInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardWakeDirectlyToGoneInteractor;
 import com.android.systemui.keyguard.ui.binder.KeyguardSurfaceBehindParamsApplier;
 import com.android.systemui.keyguard.ui.binder.KeyguardSurfaceBehindViewBinder;
@@ -126,6 +127,7 @@
     private final Lazy<DeviceEntryInteractor> mDeviceEntryInteractorLazy;
     private final Executor mMainExecutor;
     private final Lazy<KeyguardStateCallbackStartable> mKeyguardStateCallbackStartableLazy;
+    private final KeyguardStateCallbackInteractor mKeyguardStateCallbackInteractor;
 
     private static RemoteAnimationTarget[] wrap(TransitionInfo info, boolean wallpapers,
             SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap,
@@ -350,7 +352,8 @@
             Lazy<KeyguardStateCallbackStartable> keyguardStateCallbackStartableLazy,
             KeyguardWakeDirectlyToGoneInteractor keyguardWakeDirectlyToGoneInteractor,
             KeyguardDismissInteractor keyguardDismissInteractor,
-            Lazy<DeviceEntryInteractor> deviceEntryInteractorLazy) {
+            Lazy<DeviceEntryInteractor> deviceEntryInteractorLazy,
+            KeyguardStateCallbackInteractor keyguardStateCallbackInteractor) {
         super();
         mKeyguardViewMediator = keyguardViewMediator;
         mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher;
@@ -363,6 +366,7 @@
         mSceneInteractorLazy = sceneInteractorLazy;
         mMainExecutor = mainExecutor;
         mKeyguardStateCallbackStartableLazy = keyguardStateCallbackStartableLazy;
+        mKeyguardStateCallbackInteractor = keyguardStateCallbackInteractor;
         mDeviceEntryInteractorLazy = deviceEntryInteractorLazy;
 
         if (KeyguardWmStateRefactor.isEnabled()) {
@@ -455,6 +459,8 @@
             checkPermission();
             if (SceneContainerFlag.isEnabled()) {
                 mKeyguardStateCallbackStartableLazy.get().addCallback(callback);
+            } else if (KeyguardWmStateRefactor.isEnabled()) {
+                mKeyguardStateCallbackInteractor.addCallback(callback);
             } else {
                 mKeyguardViewMediator.addStateMonitorCallback(callback);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index d38c952..3b1569d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2288,6 +2288,10 @@
     }
 
     private void updateInputRestrictedLocked() {
+        if (KeyguardWmStateRefactor.isEnabled()) {
+            return;
+        }
+
         boolean inputRestricted = isInputRestricted();
         if (mInputRestricted != inputRestricted) {
             mInputRestricted = inputRestricted;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
index db5a63b..58c8a04 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
@@ -73,7 +73,7 @@
         if (SceneContainerFlag.isEnabled) return
         listenForGoneToAodOrDozing()
         listenForGoneToDreaming()
-        listenForGoneToLockscreenOrHub()
+        listenForGoneToLockscreenOrHubOrOccluded()
         listenForGoneToOccluded()
         listenForGoneToDreamingLockscreenHosted()
     }
@@ -89,22 +89,19 @@
      */
     private fun listenForGoneToOccluded() {
         scope.launch("$TAG#listenForGoneToOccluded") {
-            keyguardInteractor.showDismissibleKeyguard
-                .filterRelevantKeyguardState()
-                .sample(keyguardInteractor.isKeyguardOccluded, ::Pair)
-                .collect { (_, isKeyguardOccluded) ->
-                    if (isKeyguardOccluded) {
-                        startTransitionTo(
-                            KeyguardState.OCCLUDED,
-                            ownerReason = "Dismissible keyguard with occlusion"
-                        )
-                    }
+            keyguardInteractor.showDismissibleKeyguard.filterRelevantKeyguardState().collect {
+                if (keyguardInteractor.isKeyguardOccluded.value) {
+                    startTransitionTo(
+                        KeyguardState.OCCLUDED,
+                        ownerReason = "Dismissible keyguard with occlusion"
+                    )
                 }
+            }
         }
     }
 
     // Primarily for when the user chooses to lock down the device
-    private fun listenForGoneToLockscreenOrHub() {
+    private fun listenForGoneToLockscreenOrHubOrOccluded() {
         if (KeyguardWmStateRefactor.isEnabled) {
             scope.launch("$TAG#listenForGoneToLockscreenOrHub") {
                 biometricSettingsRepository.isCurrentUserInLockdown
@@ -137,7 +134,7 @@
                     }
             }
         } else {
-            scope.launch("$TAG#listenForGoneToLockscreenOrHub") {
+            scope.launch("$TAG#listenForGoneToLockscreenOrHubOrOccluded") {
                 keyguardInteractor.isKeyguardShowing
                     .filterRelevantKeyguardStateAnd { isKeyguardShowing -> isKeyguardShowing }
                     .sample(communalSceneInteractor.isIdleOnCommunalNotEditMode, ::Pair)
@@ -145,6 +142,8 @@
                         val to =
                             if (isIdleOnCommunal) {
                                 KeyguardState.GLANCEABLE_HUB
+                            } else if (keyguardInteractor.isKeyguardOccluded.value) {
+                                KeyguardState.OCCLUDED
                             } else {
                                 KeyguardState.LOCKSCREEN
                             }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractor.kt
new file mode 100644
index 0000000..420fbd4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractor.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import android.os.DeadObjectException
+import android.os.RemoteException
+import com.android.internal.policy.IKeyguardStateCallback
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyguard.KeyguardWmStateRefactor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import javax.inject.Inject
+
+/**
+ * Updates KeyguardStateCallbacks provided to KeyguardService with KeyguardTransitionInteractor
+ * state.
+ *
+ * This borrows heavily from [KeyguardStateCallbackStartable], which requires Flexiglass. This class
+ * can be removed after Flexiglass launches.
+ */
+@SysUISingleton
+class KeyguardStateCallbackInteractor
+@Inject
+constructor(
+    @Application private val applicationScope: CoroutineScope,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+    private val selectedUserInteractor: SelectedUserInteractor,
+    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+) : CoreStartable {
+    private val callbacks = mutableListOf<IKeyguardStateCallback>()
+
+    override fun start() {
+        if (!KeyguardWmStateRefactor.isEnabled || SceneContainerFlag.isEnabled) {
+            return
+        }
+
+        applicationScope.launch {
+            combine(
+                selectedUserInteractor.selectedUser,
+                keyguardTransitionInteractor.currentKeyguardState,
+                ::Pair
+            ).collectLatest { (selectedUser, currentState) ->
+                val iterator = callbacks.iterator()
+                    withContext(backgroundDispatcher) {
+                        while (iterator.hasNext()) {
+                            val callback = iterator.next()
+                            try {
+                                 callback.onShowingStateChanged(
+                                    currentState != KeyguardState.GONE,
+                                    selectedUser
+                                )
+                                callback.onInputRestrictedStateChanged(
+                                    currentState != KeyguardState.GONE)
+                            } catch (e: RemoteException) {
+                                if (e is DeadObjectException) {
+                                    iterator.remove()
+                                }
+                            }
+                        }
+                    }
+                }
+        }
+    }
+
+    fun addCallback(callback: IKeyguardStateCallback) {
+        KeyguardWmStateRefactor.isUnexpectedlyInLegacyMode()
+        callbacks.add(callback)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
index d9c48fa..25b8fd3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
@@ -29,6 +29,7 @@
     private val auditLogger: KeyguardTransitionAuditLogger,
     private val bootInteractor: KeyguardTransitionBootInteractor,
     private val statusBarDisableFlagsInteractor: StatusBarDisableFlagsInteractor,
+    private val keyguardStateCallbackInteractor: KeyguardStateCallbackInteractor,
 ) : CoreStartable {
 
     override fun start() {
@@ -55,6 +56,7 @@
         auditLogger.start()
         bootInteractor.start()
         statusBarDisableFlagsInteractor.start()
+        keyguardStateCallbackInteractor.start()
     }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt
index e00e33d..43aab35 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt
@@ -39,12 +39,14 @@
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.power.shared.model.WakeSleepReason
 import com.android.systemui.power.shared.model.WakefulnessModel
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
@@ -75,62 +77,66 @@
     private val disableToken: IBinder = Binder()
 
     private val disableFlagsForUserId =
-        combine(
-                selectedUserInteractor.selectedUser,
-                keyguardTransitionInteractor.startedKeyguardTransitionStep.map { it.to },
-                deviceConfigInteractor.property(
-                    namespace = DeviceConfig.NAMESPACE_SYSTEMUI,
-                    name = SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN,
-                    default = true,
-                ),
-                navigationInteractor.isGesturalMode,
-                authenticationInteractor.authenticationMethod,
-                powerInteractor.detailedWakefulness,
-            ) { values ->
-                val selectedUserId = values[0] as Int
-                val startedState = values[1] as KeyguardState
-                val isShowHomeOverLockscreen = values[2] as Boolean
-                val isGesturalMode = values[3] as Boolean
-                val authenticationMethod = values[4] as AuthenticationMethodModel
-                val wakefulnessModel = values[5] as WakefulnessModel
-                val isOccluded = startedState == KeyguardState.OCCLUDED
+        if (!KeyguardWmStateRefactor.isEnabled || SceneContainerFlag.isEnabled) {
+            flowOf(Pair(0, StatusBarManager.DISABLE_NONE))
+        } else {
+            combine(
+                    selectedUserInteractor.selectedUser,
+                    keyguardTransitionInteractor.startedKeyguardTransitionStep.map { it.to },
+                    deviceConfigInteractor.property(
+                        namespace = DeviceConfig.NAMESPACE_SYSTEMUI,
+                        name = SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN,
+                        default = true,
+                    ),
+                    navigationInteractor.isGesturalMode,
+                    authenticationInteractor.authenticationMethod,
+                    powerInteractor.detailedWakefulness,
+                ) { values ->
+                    val selectedUserId = values[0] as Int
+                    val startedState = values[1] as KeyguardState
+                    val isShowHomeOverLockscreen = values[2] as Boolean
+                    val isGesturalMode = values[3] as Boolean
+                    val authenticationMethod = values[4] as AuthenticationMethodModel
+                    val wakefulnessModel = values[5] as WakefulnessModel
+                    val isOccluded = startedState == KeyguardState.OCCLUDED
 
-                val hideHomeAndRecentsForBouncer =
-                    startedState == KeyguardState.PRIMARY_BOUNCER ||
-                        startedState == KeyguardState.ALTERNATE_BOUNCER
-                val isKeyguardShowing = startedState != KeyguardState.GONE
-                val isPowerGestureIntercepted =
-                    with(wakefulnessModel) {
-                        isAwake() &&
-                            powerButtonLaunchGestureTriggered &&
-                            lastSleepReason == WakeSleepReason.POWER_BUTTON
+                    val hideHomeAndRecentsForBouncer =
+                        startedState == KeyguardState.PRIMARY_BOUNCER ||
+                            startedState == KeyguardState.ALTERNATE_BOUNCER
+                    val isKeyguardShowing = startedState != KeyguardState.GONE
+                    val isPowerGestureIntercepted =
+                        with(wakefulnessModel) {
+                            isAwake() &&
+                                powerButtonLaunchGestureTriggered &&
+                                lastSleepReason == WakeSleepReason.POWER_BUTTON
+                        }
+
+                    var flags = StatusBarManager.DISABLE_NONE
+
+                    if (hideHomeAndRecentsForBouncer || (isKeyguardShowing && !isOccluded)) {
+                        if (!isShowHomeOverLockscreen || !isGesturalMode) {
+                            flags = flags or StatusBarManager.DISABLE_HOME
+                        }
+                        flags = flags or StatusBarManager.DISABLE_RECENT
                     }
 
-                var flags = StatusBarManager.DISABLE_NONE
-
-                if (hideHomeAndRecentsForBouncer || (isKeyguardShowing && !isOccluded)) {
-                    if (!isShowHomeOverLockscreen || !isGesturalMode) {
-                        flags = flags or StatusBarManager.DISABLE_HOME
+                    if (
+                        isPowerGestureIntercepted &&
+                            isOccluded &&
+                            authenticationMethod.isSecure &&
+                            deviceEntryFaceAuthInteractor.isFaceAuthEnabledAndEnrolled()
+                    ) {
+                        flags = flags or StatusBarManager.DISABLE_RECENT
                     }
-                    flags = flags or StatusBarManager.DISABLE_RECENT
-                }
 
-                if (
-                    isPowerGestureIntercepted &&
-                        isOccluded &&
-                        authenticationMethod.isSecure &&
-                        deviceEntryFaceAuthInteractor.isFaceAuthEnabledAndEnrolled()
-                ) {
-                    flags = flags or StatusBarManager.DISABLE_RECENT
+                    selectedUserId to flags
                 }
-
-                selectedUserId to flags
-            }
-            .distinctUntilChanged()
+                .distinctUntilChanged()
+        }
 
     @SuppressLint("WrongConstant", "NonInjectedService")
     override fun start() {
-        if (!KeyguardWmStateRefactor.isEnabled) {
+        if (!KeyguardWmStateRefactor.isEnabled || SceneContainerFlag.isEnabled) {
             return
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
index 91a7f7f..7696273 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
@@ -42,6 +42,7 @@
 import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel
 import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerWindowViewModel
 import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.log.LongPressHandlingViewLogger
 import com.android.systemui.res.R
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scrim.ScrimView
@@ -191,6 +192,7 @@
 
         optionallyAddUdfpsViews(
             view = view,
+            logger = alternateBouncerDependencies.logger,
             udfpsIconViewModel = alternateBouncerDependencies.udfpsIconViewModel,
             udfpsA11yOverlayViewModel =
                 alternateBouncerDependencies.udfpsAccessibilityOverlayViewModel,
@@ -248,6 +250,7 @@
 
     private fun optionallyAddUdfpsViews(
         view: ConstraintLayout,
+        logger: LongPressHandlingViewLogger,
         udfpsIconViewModel: AlternateBouncerUdfpsIconViewModel,
         udfpsA11yOverlayViewModel: Lazy<AlternateBouncerUdfpsAccessibilityOverlayViewModel>,
     ) {
@@ -276,7 +279,7 @@
                         var udfpsView = view.getViewById(udfpsViewId)
                         if (udfpsView == null) {
                             udfpsView =
-                                DeviceEntryIconView(view.context, null).apply {
+                                DeviceEntryIconView(view.context, null, logger = logger).apply {
                                     id = udfpsViewId
                                     contentDescription =
                                         context.resources.getString(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
index 4d6577c..b951b73 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
@@ -19,6 +19,7 @@
 
 import android.annotation.SuppressLint
 import android.content.res.ColorStateList
+import android.util.Log
 import android.util.StateSet
 import android.view.HapticFeedbackConstants
 import android.view.View
@@ -83,6 +84,11 @@
                     if (
                         !isA11yAction && falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)
                     ) {
+                        Log.d(
+                            TAG,
+                            "Long press rejected because it is not a11yAction " +
+                                "and it is a falseLongTap"
+                        )
                         return
                     }
                     vibratorHelper.performHapticFeedback(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
index 3e6d5da..8d2e939 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
@@ -23,6 +23,7 @@
 import android.util.StateSet
 import android.view.Gravity
 import android.view.View
+import android.view.ViewConfiguration
 import android.view.ViewGroup
 import android.view.accessibility.AccessibilityNodeInfo
 import android.widget.FrameLayout
@@ -31,6 +32,7 @@
 import com.airbnb.lottie.LottieCompositionFactory
 import com.airbnb.lottie.LottieDrawable
 import com.android.systemui.common.ui.view.LongPressHandlingView
+import com.android.systemui.log.LongPressHandlingViewLogger
 import com.android.systemui.res.R
 
 class DeviceEntryIconView
@@ -39,8 +41,17 @@
     context: Context,
     attrs: AttributeSet?,
     defStyleAttrs: Int = 0,
+    logger: LongPressHandlingViewLogger? = null,
 ) : FrameLayout(context, attrs, defStyleAttrs) {
-    val longPressHandlingView: LongPressHandlingView = LongPressHandlingView(context, attrs)
+
+    val longPressHandlingView: LongPressHandlingView =
+        LongPressHandlingView(
+            context = context,
+            attrs = attrs,
+            longPressDuration = { ViewConfiguration.getLongPressTimeout().toLong() },
+            allowedTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(),
+            logger = logger,
+        )
     val iconView: ImageView = ImageView(context, attrs).apply { id = R.id.device_entry_icon_fg }
     val bgView: ImageView = ImageView(context, attrs).apply { id = R.id.device_entry_icon_bg }
     val aodFpDrawable: LottieDrawable = LottieDrawable()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
index 51230dd..782d37b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
@@ -42,6 +42,9 @@
 import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryBackgroundViewModel
 import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryForegroundViewModel
 import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LongPressHandlingViewLogger
+import com.android.systemui.log.dagger.LongPressTouchLog
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.res.R
 import com.android.systemui.shade.NotificationPanelView
@@ -69,6 +72,7 @@
     private val deviceEntryBackgroundViewModel: Lazy<DeviceEntryBackgroundViewModel>,
     private val falsingManager: Lazy<FalsingManager>,
     private val vibratorHelper: Lazy<VibratorHelper>,
+    @LongPressTouchLog private val logBuffer: LogBuffer,
 ) : KeyguardSection() {
     private val deviceEntryIconViewId = R.id.device_entry_icon_view
     private var disposableHandle: DisposableHandle? = null
@@ -88,7 +92,16 @@
 
         val view =
             if (DeviceEntryUdfpsRefactor.isEnabled) {
-                DeviceEntryIconView(context, null).apply { id = deviceEntryIconViewId }
+                DeviceEntryIconView(
+                        context,
+                        null,
+                        logger =
+                            LongPressHandlingViewLogger(
+                                logBuffer = logBuffer,
+                                TAG
+                            )
+                    )
+                    .apply { id = deviceEntryIconViewId }
             } else {
                 // KeyguardBottomAreaRefactor.isEnabled or MigrateClocksToBlueprint.isEnabled
                 LockIconView(context, null).apply { id = R.id.lock_icon_view }
@@ -258,4 +271,8 @@
             }
         }
     }
+
+    companion object {
+        private const val TAG = "DefaultDeviceEntrySection"
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt
index b432417..9f8e9c5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt
@@ -18,6 +18,9 @@
 
 import com.android.systemui.deviceentry.ui.viewmodel.AlternateBouncerUdfpsAccessibilityOverlayViewModel
 import com.android.systemui.keyguard.ui.SwipeUpAnywhereGestureHandler
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LongPressHandlingViewLogger
+import com.android.systemui.log.dagger.LongPressTouchLog
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.statusbar.gesture.TapGestureDetector
 import dagger.Lazy
@@ -37,4 +40,11 @@
         Lazy<AlternateBouncerUdfpsAccessibilityOverlayViewModel>,
     val messageAreaViewModel: AlternateBouncerMessageAreaViewModel,
     val powerInteractor: PowerInteractor,
-)
+    @LongPressTouchLog private val touchLogBuffer: LogBuffer,
+) {
+    val logger: LongPressHandlingViewLogger =
+        LongPressHandlingViewLogger(logBuffer = touchLogBuffer, TAG)
+    companion object {
+        private const val TAG = "AlternateBouncer"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToOccludedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToOccludedTransitionViewModel.kt
index f33752f..12bcc7e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToOccludedTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToOccludedTransitionViewModel.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import android.util.MathUtils
+import com.android.systemui.Flags.lightRevealMigration
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.domain.interactor.FromAodTransitionInteractor
 import com.android.systemui.keyguard.shared.model.Edge
@@ -55,8 +56,18 @@
         var currentAlpha = 0f
         return transitionAnimation.sharedFlow(
             duration = 250.milliseconds,
-            startTime = 100.milliseconds, // Wait for the light reveal to "hit" the LS elements.
-            onStart = { currentAlpha = viewState.alpha() },
+            startTime = if (lightRevealMigration()) {
+                100.milliseconds // Wait for the light reveal to "hit" the LS elements.
+            } else {
+                0.milliseconds
+            },
+            onStart = {
+                if (lightRevealMigration()) {
+                    currentAlpha = viewState.alpha()
+                } else {
+                    currentAlpha = 0f
+                }
+            },
             onStep = { MathUtils.lerp(currentAlpha, 0f, it) },
             onCancel = { 0f },
         )
diff --git a/packages/SystemUI/src/com/android/systemui/log/LongPressHandlingViewLogger.kt b/packages/SystemUI/src/com/android/systemui/log/LongPressHandlingViewLogger.kt
new file mode 100644
index 0000000..4ff8118
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LongPressHandlingViewLogger.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2024 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.log
+
+import com.android.systemui.log.core.LogLevel.DEBUG
+import com.google.errorprone.annotations.CompileTimeConstant
+
+data class LongPressHandlingViewLogger
+constructor(
+    private val logBuffer: LogBuffer,
+    @CompileTimeConstant private val tag: String = "LongPressHandlingViewLogger"
+) {
+    fun schedulingLongPress(delay: Long) {
+        logBuffer.log(
+            tag,
+            DEBUG,
+            { long1 = delay },
+            { "on MotionEvent.Down: scheduling long press activation after $long1 ms" }
+        )
+    }
+
+    fun longPressTriggered() {
+        logBuffer.log(tag, DEBUG, "long press event detected and dispatched")
+    }
+
+    fun motionEventCancelled() {
+        logBuffer.log(tag, DEBUG, "Long press may be cancelled due to MotionEventModel.Cancel")
+    }
+
+    fun dispatchingSingleTap() {
+        logBuffer.log(tag, DEBUG, "Dispatching single tap instead of long press")
+    }
+
+    fun onUpEvent(distanceMoved: Float, touchSlop: Int, gestureDuration: Long) {
+        logBuffer.log(
+            tag,
+            DEBUG,
+            {
+                double1 = distanceMoved.toDouble()
+                int1 = touchSlop
+                long1 = gestureDuration
+            },
+            {
+                "on MotionEvent.Up: distanceMoved: $double1, " +
+                    "allowedTouchSlop: $int1, " +
+                    "eventDuration: $long1"
+            }
+        )
+    }
+
+    fun cancelingLongPressDueToTouchSlop(distanceMoved: Float, allowedTouchSlop: Int) {
+        logBuffer.log(
+            tag,
+            DEBUG,
+            {
+                double1 = distanceMoved.toDouble()
+                int1 = allowedTouchSlop
+            },
+            {
+                "on MotionEvent.Motion: May cancel long press due to movement: " +
+                    "distanceMoved: $double1, " +
+                    "allowedTouchSlop: $int1 "
+            }
+        )
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 19906fd..498c34c 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -717,4 +717,12 @@
     public static LogBuffer provideVolumeLogBuffer(LogBufferFactory factory) {
         return factory.create("VolumeLog", 50);
     }
+
+    /** Provides a {@link LogBuffer} for use by long touch event handlers. */
+    @Provides
+    @SysUISingleton
+    @LongPressTouchLog
+    public static LogBuffer providesLongPressTouchLog(LogBufferFactory factory) {
+        return factory.create("LongPressViewLog", 200);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LongPressTouchLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/LongPressTouchLog.kt
new file mode 100644
index 0000000..1163d74
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LongPressTouchLog.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 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.log.dagger
+
+import javax.inject.Qualifier
+
+/** Log buffer for logging touch/long press events */
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class LongPressTouchLog
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt
index 24c57be..4ad437c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt
@@ -76,6 +76,7 @@
 import com.android.systemui.media.controls.shared.model.MediaButton
 import com.android.systemui.media.controls.shared.model.MediaData
 import com.android.systemui.media.controls.shared.model.MediaDeviceData
+import com.android.systemui.media.controls.shared.model.MediaNotificationAction
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvider
 import com.android.systemui.media.controls.ui.view.MediaViewHolder
@@ -943,7 +944,7 @@
                     desc.subtitle,
                     desc.title,
                     artworkIcon,
-                    listOf(mediaAction),
+                    listOf(),
                     listOf(0),
                     MediaButton(playOrPause = mediaAction),
                     packageName,
@@ -1074,13 +1075,13 @@
         }
 
         // Control buttons
-        // If flag is enabled and controller has a PlaybackState, create actions from session info
+        // If controller has a PlaybackState, create actions from session info
         // Otherwise, use the notification actions
-        var actionIcons: List<MediaAction> = emptyList()
+        var actionIcons: List<MediaNotificationAction> = emptyList()
         var actionsToShowCollapsed: List<Int> = emptyList()
         val semanticActions = createActionsFromState(sbn.packageName, mediaController, sbn.user)
         if (semanticActions == null) {
-            val actions = createActionsFromNotification(context, activityStarter, sbn)
+            val actions = createActionsFromNotification(context, sbn)
             actionIcons = actions.first
             actionsToShowCollapsed = actions.second
         }
@@ -1464,7 +1465,7 @@
         val updated =
             data.copy(
                 token = null,
-                actions = actions,
+                actions = listOf(),
                 semanticActions = MediaButton(playOrPause = resumeAction),
                 actionsToShowInCompact = listOf(0),
                 active = false,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaActions.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaActions.kt
index bcf748e..f2825d0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaActions.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaActions.kt
@@ -33,6 +33,7 @@
 import com.android.systemui.media.controls.shared.MediaControlDrawables
 import com.android.systemui.media.controls.shared.model.MediaAction
 import com.android.systemui.media.controls.shared.model.MediaButton
+import com.android.systemui.media.controls.shared.model.MediaNotificationAction
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.NotificationMediaManager.isConnectingState
@@ -217,11 +218,10 @@
 /** Generate action buttons based on notification actions */
 fun createActionsFromNotification(
     context: Context,
-    activityStarter: ActivityStarter,
     sbn: StatusBarNotification
-): Pair<List<MediaAction>, List<Int>> {
+): Pair<List<MediaNotificationAction>, List<Int>> {
     val notif = sbn.notification
-    val actionIcons: MutableList<MediaAction> = ArrayList()
+    val actionIcons: MutableList<MediaNotificationAction> = ArrayList()
     val actions = notif.actions
     var actionsToShowCollapsed =
         notif.extras.getIntArray(Notification.EXTRA_COMPACT_ACTIONS)?.toMutableList()
@@ -250,25 +250,6 @@
                 continue
             }
 
-            val runnable =
-                action.actionIntent?.let { actionIntent ->
-                    Runnable {
-                        when {
-                            actionIntent.isActivity ->
-                                activityStarter.startPendingIntentDismissingKeyguard(
-                                    action.actionIntent
-                                )
-                            action.isAuthenticationRequired ->
-                                activityStarter.dismissKeyguardThenExecute(
-                                    { sendPendingIntent(action.actionIntent) },
-                                    {},
-                                    true
-                                )
-                            else -> sendPendingIntent(actionIntent)
-                        }
-                    }
-                }
-
             val themeText =
                 com.android.settingslib.Utils.getColorAttr(
                         context,
@@ -285,13 +266,53 @@
                     .setTint(themeText)
                     .loadDrawable(context)
 
-            val mediaAction = MediaAction(mediaActionIcon, runnable, action.title, null)
+            val mediaAction =
+                MediaNotificationAction(
+                    action.isAuthenticationRequired,
+                    action.actionIntent,
+                    mediaActionIcon,
+                    action.title
+                )
             actionIcons.add(mediaAction)
         }
     }
     return Pair(actionIcons, actionsToShowCollapsed)
 }
 
+/**
+ * Converts [MediaNotificationAction] list into [MediaAction] list
+ *
+ * @param actions list of [MediaNotificationAction]
+ * @param activityStarter starter for activities
+ * @return list of [MediaAction]
+ */
+fun getNotificationActions(
+    actions: List<MediaNotificationAction>,
+    activityStarter: ActivityStarter
+): List<MediaAction> {
+    return actions.map { action ->
+        val runnable =
+            action.actionIntent?.let { actionIntent ->
+                Runnable {
+                    when {
+                        actionIntent.isActivity ->
+                            activityStarter.startPendingIntentDismissingKeyguard(
+                                action.actionIntent
+                            )
+                        action.isAuthenticationRequired ->
+                            activityStarter.dismissKeyguardThenExecute(
+                                { sendPendingIntent(action.actionIntent) },
+                                {},
+                                true
+                            )
+                        else -> sendPendingIntent(actionIntent)
+                    }
+                }
+            }
+        MediaAction(action.icon, runnable, action.contentDescription, background = null)
+    }
+}
+
 private fun sendPendingIntent(intent: PendingIntent): Boolean {
     return try {
         intent.send(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt
index f9fef8e..53cc15b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt
@@ -54,10 +54,10 @@
 import com.android.systemui.media.controls.shared.model.MediaButton
 import com.android.systemui.media.controls.shared.model.MediaData
 import com.android.systemui.media.controls.shared.model.MediaDeviceData
+import com.android.systemui.media.controls.shared.model.MediaNotificationAction
 import com.android.systemui.media.controls.util.MediaControllerFactory
 import com.android.systemui.media.controls.util.MediaDataUtils
 import com.android.systemui.media.controls.util.MediaFlags
-import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
 import com.android.systemui.statusbar.notification.row.HybridGroupManager
@@ -80,7 +80,6 @@
     @Application val context: Context,
     @Main val mainDispatcher: CoroutineDispatcher,
     @Background val backgroundScope: CoroutineScope,
-    private val activityStarter: ActivityStarter,
     private val mediaControllerFactory: MediaControllerFactory,
     private val mediaFlags: MediaFlags,
     private val imageLoader: ImageLoader,
@@ -209,15 +208,14 @@
             val device: MediaDeviceData? = getDeviceInfoForRemoteCast(key, sbn)
 
             // Control buttons
-            // If flag is enabled and controller has a PlaybackState, create actions from session
-            // info
+            // If controller has a PlaybackState, create actions from session info
             // Otherwise, use the notification actions
-            var actionIcons: List<MediaAction> = emptyList()
+            var actionIcons: List<MediaNotificationAction> = emptyList()
             var actionsToShowCollapsed: List<Int> = emptyList()
             val semanticActions = createActionsFromState(sbn.packageName, mediaController, sbn.user)
             logD(TAG) { "Semantic actions: $semanticActions" }
             if (semanticActions == null) {
-                val actions = createActionsFromNotification(context, activityStarter, sbn)
+                val actions = createActionsFromNotification(context, sbn)
                 actionIcons = actions.first
                 actionsToShowCollapsed = actions.second
                 logD(TAG) { "[!!] Semantic actions: $semanticActions" }
@@ -329,7 +327,7 @@
                 artist = desc.subtitle,
                 song = desc.title,
                 artworkIcon = artworkIcon,
-                actionIcons = listOf(mediaAction),
+                actionIcons = listOf(),
                 actionsToShowInCompact = listOf(0),
                 semanticActions = MediaButton(playOrPause = mediaAction),
                 token = token,
@@ -514,7 +512,7 @@
         val artist: CharSequence?,
         val song: CharSequence?,
         val artworkIcon: Icon?,
-        val actionIcons: List<MediaAction>,
+        val actionIcons: List<MediaNotificationAction>,
         val actionsToShowInCompact: List<Int>,
         val semanticActions: MediaButton?,
         val token: MediaSession.Token?,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
index 4555810..5f0a9f8 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
@@ -71,12 +71,14 @@
 import com.android.systemui.media.controls.domain.pipeline.MediaDataManager.Companion.isMediaNotification
 import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
 import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser
+import com.android.systemui.media.controls.shared.MediaLogger
 import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_SOURCE
 import com.android.systemui.media.controls.shared.model.EXTRA_VALUE_TRIGGER_PERIODIC
 import com.android.systemui.media.controls.shared.model.MediaAction
 import com.android.systemui.media.controls.shared.model.MediaButton
 import com.android.systemui.media.controls.shared.model.MediaData
 import com.android.systemui.media.controls.shared.model.MediaDeviceData
+import com.android.systemui.media.controls.shared.model.MediaNotificationAction
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvider
 import com.android.systemui.media.controls.ui.view.MediaViewHolder
@@ -149,6 +151,7 @@
     private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
     private val mediaDataRepository: MediaDataRepository,
     private val mediaDataLoader: dagger.Lazy<MediaDataLoader>,
+    private val mediaLogger: MediaLogger,
 ) : CoreStartable, BcSmartspaceDataPlugin.SmartspaceTargetListener {
 
     companion object {
@@ -228,6 +231,7 @@
         keyguardUpdateMonitor: KeyguardUpdateMonitor,
         mediaDataRepository: MediaDataRepository,
         mediaDataLoader: dagger.Lazy<MediaDataLoader>,
+        mediaLogger: MediaLogger,
     ) : this(
         context,
         applicationScope,
@@ -253,6 +257,7 @@
         keyguardUpdateMonitor,
         mediaDataRepository,
         mediaDataLoader,
+        mediaLogger,
     )
 
     private val appChangeReceiver =
@@ -794,7 +799,7 @@
                     desc.subtitle,
                     desc.title,
                     artworkIcon,
-                    listOf(mediaAction),
+                    listOf(),
                     listOf(0),
                     MediaButton(playOrPause = mediaAction),
                     packageName,
@@ -832,12 +837,48 @@
                 return@withContext
             }
 
-            val currentEntry = mediaDataRepository.mediaEntries.value[key]
-            val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId()
-            val createdTimestampMillis = currentEntry?.createdTimestampMillis ?: 0L
-            val resumeAction: Runnable? = currentEntry?.resumeAction
-            val hasCheckedForResume = currentEntry?.hasCheckedForResume == true
-            val active = currentEntry?.active ?: true
+            val mediaController = mediaControllerFactory.create(result.token!!)
+            val oldEntry = mediaDataRepository.mediaEntries.value[key]
+            val instanceId = oldEntry?.instanceId ?: logger.getNewInstanceId()
+            val createdTimestampMillis = oldEntry?.createdTimestampMillis ?: 0L
+            val resumeAction: Runnable? = oldEntry?.resumeAction
+            val hasCheckedForResume = oldEntry?.hasCheckedForResume == true
+            val active = oldEntry?.active ?: true
+
+            val mediaData =
+                MediaData(
+                    userId = sbn.normalizedUserId,
+                    initialized = true,
+                    app = result.appName,
+                    appIcon = result.appIcon,
+                    artist = result.artist,
+                    song = result.song,
+                    artwork = result.artworkIcon,
+                    actions = result.actionIcons,
+                    actionsToShowInCompact = result.actionsToShowInCompact,
+                    semanticActions = result.semanticActions,
+                    packageName = sbn.packageName,
+                    token = result.token,
+                    clickIntent = result.clickIntent,
+                    device = result.device,
+                    active = active,
+                    resumeAction = resumeAction,
+                    playbackLocation = result.playbackLocation,
+                    notificationKey = key,
+                    hasCheckedForResume = hasCheckedForResume,
+                    isPlaying = result.isPlaying,
+                    isClearable = !sbn.isOngoing,
+                    lastActive = lastActive,
+                    createdTimestampMillis = createdTimestampMillis,
+                    instanceId = instanceId,
+                    appUid = result.appUid,
+                    isExplicit = result.isExplicit,
+                )
+
+            if (isSameMediaData(context, mediaController, mediaData, oldEntry)) {
+                mediaLogger.logDuplicateMediaNotification(key)
+                return@withContext
+            }
 
             // We need to log the correct media added.
             if (isNewlyActiveEntry) {
@@ -848,7 +889,7 @@
                     instanceId,
                     result.playbackLocation
                 )
-            } else if (result.playbackLocation != currentEntry?.playbackLocation) {
+            } else if (result.playbackLocation != oldEntry?.playbackLocation) {
                 logger.logPlaybackLocationChange(
                     result.appUid,
                     sbn.packageName,
@@ -857,40 +898,7 @@
                 )
             }
 
-            withContext(mainDispatcher) {
-                onMediaDataLoaded(
-                    key,
-                    oldKey,
-                    MediaData(
-                        userId = sbn.normalizedUserId,
-                        initialized = true,
-                        app = result.appName,
-                        appIcon = result.appIcon,
-                        artist = result.artist,
-                        song = result.song,
-                        artwork = result.artworkIcon,
-                        actions = result.actionIcons,
-                        actionsToShowInCompact = result.actionsToShowInCompact,
-                        semanticActions = result.semanticActions,
-                        packageName = sbn.packageName,
-                        token = result.token,
-                        clickIntent = result.clickIntent,
-                        device = result.device,
-                        active = active,
-                        resumeAction = resumeAction,
-                        playbackLocation = result.playbackLocation,
-                        notificationKey = key,
-                        hasCheckedForResume = hasCheckedForResume,
-                        isPlaying = result.isPlaying,
-                        isClearable = !sbn.isOngoing,
-                        lastActive = lastActive,
-                        createdTimestampMillis = createdTimestampMillis,
-                        instanceId = instanceId,
-                        appUid = result.appUid,
-                        isExplicit = result.isExplicit,
-                    )
-                )
-            }
+            withContext(mainDispatcher) { onMediaDataLoaded(key, oldKey, mediaData) }
         }
 
     @Deprecated("Cleanup when media_load_metadata_via_media_data_loader is cleaned up")
@@ -1001,13 +1009,13 @@
         }
 
         // Control buttons
-        // If flag is enabled and controller has a PlaybackState, create actions from session info
+        // If controller has a PlaybackState, create actions from session info
         // Otherwise, use the notification actions
-        var actionIcons: List<MediaAction> = emptyList()
+        var actionIcons: List<MediaNotificationAction> = emptyList()
         var actionsToShowCollapsed: List<Int> = emptyList()
         val semanticActions = createActionsFromState(sbn.packageName, mediaController, sbn.user)
         if (semanticActions == null) {
-            val actions = createActionsFromNotification(context, activityStarter, sbn)
+            val actions = createActionsFromNotification(context, sbn)
             actionIcons = actions.first
             actionsToShowCollapsed = actions.second
         }
@@ -1022,57 +1030,72 @@
             else MediaData.PLAYBACK_CAST_LOCAL
         val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) }
 
-        val currentEntry = mediaDataRepository.mediaEntries.value.get(key)
-        val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId()
+        val oldEntry = mediaDataRepository.mediaEntries.value.get(key)
+        val instanceId = oldEntry?.instanceId ?: logger.getNewInstanceId()
         val appUid = appInfo?.uid ?: Process.INVALID_UID
 
+        val lastActive = systemClock.elapsedRealtime()
+        val createdTimestampMillis = oldEntry?.createdTimestampMillis ?: 0L
+        val resumeAction: Runnable? = mediaDataRepository.mediaEntries.value[key]?.resumeAction
+        val hasCheckedForResume =
+            mediaDataRepository.mediaEntries.value[key]?.hasCheckedForResume == true
+        val active = mediaDataRepository.mediaEntries.value[key]?.active ?: true
+        var mediaData =
+            MediaData(
+                sbn.normalizedUserId,
+                true,
+                appName,
+                smallIcon,
+                artist,
+                song,
+                artWorkIcon,
+                actionIcons,
+                actionsToShowCollapsed,
+                semanticActions,
+                sbn.packageName,
+                token,
+                notif.contentIntent,
+                device,
+                active,
+                resumeAction = resumeAction,
+                playbackLocation = playbackLocation,
+                notificationKey = key,
+                hasCheckedForResume = hasCheckedForResume,
+                isPlaying = isPlaying,
+                isClearable = !sbn.isOngoing,
+                lastActive = lastActive,
+                createdTimestampMillis = createdTimestampMillis,
+                instanceId = instanceId,
+                appUid = appUid,
+                isExplicit = isExplicit,
+                smartspaceId = SmallHash.hash(appUid + systemClock.currentTimeMillis().toInt()),
+            )
+
+        if (isSameMediaData(context, mediaController, mediaData, oldEntry)) {
+            mediaLogger.logDuplicateMediaNotification(key)
+            return
+        }
+
         if (isNewlyActiveEntry) {
             logSingleVsMultipleMediaAdded(appUid, sbn.packageName, instanceId)
             logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation)
-        } else if (playbackLocation != currentEntry?.playbackLocation) {
+        } else if (playbackLocation != oldEntry?.playbackLocation) {
             logger.logPlaybackLocationChange(appUid, sbn.packageName, instanceId, playbackLocation)
         }
 
-        val lastActive = systemClock.elapsedRealtime()
-        val createdTimestampMillis = currentEntry?.createdTimestampMillis ?: 0L
         foregroundExecutor.execute {
-            val resumeAction: Runnable? = mediaDataRepository.mediaEntries.value[key]?.resumeAction
-            val hasCheckedForResume =
+            val oldResumeAction: Runnable? =
+                mediaDataRepository.mediaEntries.value[key]?.resumeAction
+            val oldHasCheckedForResume =
                 mediaDataRepository.mediaEntries.value[key]?.hasCheckedForResume == true
-            val active = mediaDataRepository.mediaEntries.value[key]?.active ?: true
-            onMediaDataLoaded(
-                key,
-                oldKey,
-                MediaData(
-                    sbn.normalizedUserId,
-                    true,
-                    appName,
-                    smallIcon,
-                    artist,
-                    song,
-                    artWorkIcon,
-                    actionIcons,
-                    actionsToShowCollapsed,
-                    semanticActions,
-                    sbn.packageName,
-                    token,
-                    notif.contentIntent,
-                    device,
-                    active,
-                    resumeAction = resumeAction,
-                    playbackLocation = playbackLocation,
-                    notificationKey = key,
-                    hasCheckedForResume = hasCheckedForResume,
-                    isPlaying = isPlaying,
-                    isClearable = !sbn.isOngoing,
-                    lastActive = lastActive,
-                    createdTimestampMillis = createdTimestampMillis,
-                    instanceId = instanceId,
-                    appUid = appUid,
-                    isExplicit = isExplicit,
-                    smartspaceId = SmallHash.hash(appUid + systemClock.currentTimeMillis().toInt()),
+            val oldActive = mediaDataRepository.mediaEntries.value[key]?.active ?: true
+            mediaData =
+                mediaData.copy(
+                    resumeAction = oldResumeAction,
+                    hasCheckedForResume = oldHasCheckedForResume,
+                    active = oldActive
                 )
-            )
+            onMediaDataLoaded(key, oldKey, mediaData)
         }
     }
 
@@ -1402,7 +1425,7 @@
         val updated =
             data.copy(
                 token = null,
-                actions = actions,
+                actions = listOf(),
                 semanticActions = MediaButton(playOrPause = resumeAction),
                 actionsToShowInCompact = listOf(0),
                 active = false,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaProcessingHelper.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaProcessingHelper.kt
new file mode 100644
index 0000000..55d7b1d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaProcessingHelper.kt
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.domain.pipeline
+
+import android.annotation.WorkerThread
+import android.app.PendingIntent
+import android.content.Context
+import android.graphics.drawable.Icon
+import android.media.session.MediaController
+import android.media.session.PlaybackState
+import android.util.Log
+import com.android.systemui.Flags.mediaControlsPostsOptimization
+import com.android.systemui.biometrics.Utils.toBitmap
+import com.android.systemui.media.controls.shared.model.MediaData
+
+private const val TAG = "MediaProcessingHelper"
+
+/**
+ * Compares [new] media data to [old] media data.
+ *
+ * @param context Context
+ * @param newController media controller of the new media data.
+ * @param new new media data.
+ * @param old old media data.
+ * @return whether new and old contain same data
+ */
+fun isSameMediaData(
+    context: Context,
+    newController: MediaController,
+    new: MediaData,
+    old: MediaData?
+): Boolean {
+    if (old == null || !mediaControlsPostsOptimization()) return false
+
+    return new.userId == old.userId &&
+        new.app == old.app &&
+        new.artist == old.artist &&
+        new.song == old.song &&
+        new.packageName == old.packageName &&
+        new.isExplicit == old.isExplicit &&
+        new.appUid == old.appUid &&
+        new.notificationKey == old.notificationKey &&
+        new.isPlaying == old.isPlaying &&
+        new.isClearable == old.isClearable &&
+        new.playbackLocation == old.playbackLocation &&
+        new.device == old.device &&
+        new.initialized == old.initialized &&
+        new.resumption == old.resumption &&
+        new.token == old.token &&
+        new.resumeProgress == old.resumeProgress &&
+        areClickIntentsEqual(new.clickIntent, old.clickIntent) &&
+        areActionsEqual(context, newController, new, old) &&
+        areIconsEqual(context, new.artwork, old.artwork) &&
+        areIconsEqual(context, new.appIcon, old.appIcon)
+}
+
+/** Returns whether actions lists are equal. */
+fun areCustomActionListsEqual(
+    first: List<PlaybackState.CustomAction>?,
+    second: List<PlaybackState.CustomAction>?
+): Boolean {
+    // Same object, or both null
+    if (first === second) {
+        return true
+    }
+
+    // Only one null, or different number of actions
+    if ((first == null || second == null) || (first.size != second.size)) {
+        return false
+    }
+
+    // Compare individual actions
+    first.asSequence().zip(second.asSequence()).forEach { (firstAction, secondAction) ->
+        if (!areCustomActionsEqual(firstAction, secondAction)) {
+            return false
+        }
+    }
+    return true
+}
+
+private fun areCustomActionsEqual(
+    firstAction: PlaybackState.CustomAction,
+    secondAction: PlaybackState.CustomAction
+): Boolean {
+    if (
+        firstAction.action != secondAction.action ||
+            firstAction.name != secondAction.name ||
+            firstAction.icon != secondAction.icon
+    ) {
+        return false
+    }
+
+    if ((firstAction.extras == null) != (secondAction.extras == null)) {
+        return false
+    }
+    if (firstAction.extras != null) {
+        firstAction.extras.keySet().forEach { key ->
+            if (firstAction.extras[key] != secondAction.extras[key]) {
+                return false
+            }
+        }
+    }
+    return true
+}
+
+@WorkerThread
+private fun areIconsEqual(context: Context, new: Icon?, old: Icon?): Boolean {
+    if (new == old) return true
+    if (new == null || old == null || new.type != old.type) return false
+    return if (new.type == Icon.TYPE_BITMAP || new.type == Icon.TYPE_ADAPTIVE_BITMAP) {
+        if (new.bitmap.isRecycled || old.bitmap.isRecycled) {
+            Log.e(TAG, "Cannot compare recycled bitmap")
+            return false
+        }
+        new.bitmap.sameAs(old.bitmap)
+    } else {
+        val newDrawable = new.loadDrawable(context)
+        val oldDrawable = old.loadDrawable(context)
+
+        return newDrawable?.toBitmap()?.sameAs(oldDrawable?.toBitmap()) ?: false
+    }
+}
+
+private fun areActionsEqual(
+    context: Context,
+    newController: MediaController,
+    new: MediaData,
+    old: MediaData
+): Boolean {
+    val oldState = MediaController(context, old.token!!).playbackState
+    return if (
+        new.semanticActions == null &&
+            old.semanticActions == null &&
+            new.actions.size == old.actions.size
+    ) {
+        var same = true
+        new.actions.asSequence().zip(old.actions.asSequence()).forEach {
+            if (
+                it.first.actionIntent?.intent?.filterEquals(it.second.actionIntent?.intent) !=
+                    true ||
+                    it.first.icon != it.second.icon ||
+                    it.first.contentDescription != it.second.contentDescription
+            ) {
+                same = false
+                return@forEach
+            }
+        }
+        same
+    } else if (new.semanticActions != null && old.semanticActions != null) {
+        oldState?.actions == newController.playbackState?.actions &&
+            areCustomActionListsEqual(
+                oldState?.customActions,
+                newController.playbackState?.customActions
+            )
+    } else {
+        false
+    }
+}
+
+private fun areClickIntentsEqual(newIntent: PendingIntent?, oldIntent: PendingIntent?): Boolean {
+    if ((newIntent == null && oldIntent == null) || newIntent === oldIntent) return true
+    if (newIntent == null || oldIntent == null) return false
+
+    return newIntent.intent?.filterEquals(oldIntent.intent) == true
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt
index fc31903..275f1ee 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt
@@ -16,12 +16,14 @@
 
 package com.android.systemui.media.controls.domain.pipeline
 
+import android.annotation.WorkerThread
 import android.media.session.MediaController
 import android.media.session.MediaSession
 import android.media.session.PlaybackState
 import android.os.SystemProperties
 import com.android.internal.annotations.VisibleForTesting
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.media.controls.shared.model.MediaData
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
@@ -32,6 +34,7 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController
 import com.android.systemui.util.concurrency.DelayableExecutor
 import com.android.systemui.util.time.SystemClock
+import java.util.concurrent.Executor
 import java.util.concurrent.TimeUnit
 import javax.inject.Inject
 
@@ -49,6 +52,8 @@
 @Inject
 constructor(
     private val mediaControllerFactory: MediaControllerFactory,
+    @Background private val bgExecutor: Executor,
+    @Main private val uiExecutor: Executor,
     @Main private val mainExecutor: DelayableExecutor,
     private val logger: MediaTimeoutLogger,
     statusBarStateController: SysuiStatusBarStateController,
@@ -147,19 +152,21 @@
         }
 
         reusedListener?.let {
-            val wasPlaying = it.isPlaying()
-            logger.logUpdateListener(key, wasPlaying)
-            it.setMediaData(data)
-            it.key = key
-            mediaListeners[key] = it
-            if (wasPlaying != it.isPlaying()) {
-                // If a player becomes active because of a migration, we'll need to broadcast
-                // its state. Doing it now would lead to reentrant callbacks, so let's wait
-                // until we're done.
-                mainExecutor.execute {
-                    if (mediaListeners[key]?.isPlaying() == true) {
-                        logger.logDelayedUpdate(key)
-                        timeoutCallback.invoke(key, false /* timedOut */)
+            bgExecutor.execute {
+                val wasPlaying = it.isPlaying()
+                logger.logUpdateListener(key, wasPlaying)
+                it.setMediaData(data)
+                it.key = key
+                mediaListeners[key] = it
+                if (wasPlaying != it.isPlaying()) {
+                    // If a player becomes active because of a migration, we'll need to broadcast
+                    // its state. Doing it now would lead to reentrant callbacks, so let's wait
+                    // until we're done.
+                    mainExecutor.execute {
+                        if (mediaListeners[key]?.isPlaying() == true) {
+                            logger.logDelayedUpdate(key)
+                            timeoutCallback.invoke(key, false /* timedOut */)
+                        }
                     }
                 }
             }
@@ -217,18 +224,20 @@
             private set
 
         fun Int.isPlaying() = isPlayingState(this)
+
         fun isPlaying() = lastState?.state?.isPlaying() ?: false
 
         init {
-            setMediaData(data)
+            bgExecutor.execute { setMediaData(data) }
         }
 
         fun destroy() {
-            mediaController?.unregisterCallback(this)
+            bgExecutor.execute { mediaController?.unregisterCallback(this) }
             cancellation?.run()
             destroyed = true
         }
 
+        @WorkerThread
         fun setMediaData(data: MediaData) {
             sessionToken = data.token
             destroyed = false
@@ -258,7 +267,7 @@
             if (resumption == true) {
                 // Some apps create a session when MBS is queried. We should unregister the
                 // controller since it will no longer be valid, but don't cancel the timeout
-                mediaController?.unregisterCallback(this)
+                bgExecutor.execute { mediaController?.unregisterCallback(this) }
             } else {
                 // For active controls, if the session is destroyed, clean up everything since we
                 // will need to recreate it if this key is updated later
@@ -284,7 +293,7 @@
 
             if ((!actionsSame || !playingStateSame) && state != null && dispatchEvents) {
                 logger.logStateCallback(key)
-                stateCallback.invoke(key, state)
+                uiExecutor.execute { stateCallback.invoke(key, state) }
             }
 
             if (playingStateSame && !resumptionChanged) {
@@ -313,7 +322,7 @@
                 expireMediaTimeout(key, "playback started - $state, $key")
                 timedOut = false
                 if (dispatchEvents) {
-                    timeoutCallback(key, timedOut)
+                    uiExecutor.execute { timeoutCallback(key, timedOut) }
                 }
             }
         }
@@ -337,60 +346,13 @@
         }
     }
 
-    private fun areCustomActionListsEqual(
-        first: List<PlaybackState.CustomAction>?,
-        second: List<PlaybackState.CustomAction>?
-    ): Boolean {
-        // Same object, or both null
-        if (first === second) {
-            return true
-        }
-
-        // Only one null, or different number of actions
-        if ((first == null || second == null) || (first.size != second.size)) {
-            return false
-        }
-
-        // Compare individual actions
-        first.asSequence().zip(second.asSequence()).forEach { (firstAction, secondAction) ->
-            if (!areCustomActionsEqual(firstAction, secondAction)) {
-                return false
-            }
-        }
-        return true
-    }
-
-    private fun areCustomActionsEqual(
-        firstAction: PlaybackState.CustomAction,
-        secondAction: PlaybackState.CustomAction
-    ): Boolean {
-        if (
-            firstAction.action != secondAction.action ||
-                firstAction.name != secondAction.name ||
-                firstAction.icon != secondAction.icon
-        ) {
-            return false
-        }
-
-        if ((firstAction.extras == null) != (secondAction.extras == null)) {
-            return false
-        }
-        if (firstAction.extras != null) {
-            firstAction.extras.keySet().forEach { key ->
-                if (firstAction.extras.get(key) != secondAction.extras.get(key)) {
-                    return false
-                }
-            }
-        }
-        return true
-    }
-
     /** Listens to changes in recommendation card data and schedules a timeout for its expiration */
     private inner class RecommendationListener(var key: String, data: SmartspaceMediaData) {
         private var timedOut = false
         var destroyed = false
         var expiration = Long.MAX_VALUE
             private set
+
         var cancellation: Runnable? = null
             private set
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
index 245f6f8..130868d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
@@ -32,6 +32,7 @@
 import com.android.systemui.bluetooth.BroadcastDialogController
 import com.android.systemui.media.controls.data.repository.MediaFilterRepository
 import com.android.systemui.media.controls.domain.pipeline.MediaDataProcessor
+import com.android.systemui.media.controls.domain.pipeline.getNotificationActions
 import com.android.systemui.media.controls.shared.model.MediaControlModel
 import com.android.systemui.media.controls.shared.model.MediaData
 import com.android.systemui.media.controls.util.MediaSmartspaceLogger
@@ -102,7 +103,7 @@
                 artwork = artwork,
                 deviceData = device,
                 semanticActionButtons = semanticActions,
-                notificationActionButtons = actions,
+                notificationActionButtons = getNotificationActions(data.actions, activityStarter),
                 actionsToShowInCollapsed = actionsToShowInCompact,
                 isDismissible = isClearable,
                 isResume = resumption,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaLogger.kt
index 2b710b5..7d20e17 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaLogger.kt
@@ -114,6 +114,15 @@
         )
     }
 
+    fun logDuplicateMediaNotification(key: String) {
+        buffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            { str1 = key },
+            { "duplicate media notification $str1 posted" }
+        )
+    }
+
     companion object {
         private const val TAG = "MediaLog"
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt
index 40b3477..aed8609 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt
@@ -39,7 +39,7 @@
     /** Album artwork. */
     val artwork: Icon? = null,
     /** List of generic action buttons for the media player, based on notification actions */
-    val actions: List<MediaAction> = emptyList(),
+    val actions: List<MediaNotificationAction> = emptyList(),
     /** Same as above, but shown on smaller versions of the player, like in QQS or keyguard. */
     val actionsToShowInCompact: List<Int> = emptyList(),
     /**
@@ -162,6 +162,14 @@
     val rebindId: Int? = null
 )
 
+/** State of a media action from notification. */
+data class MediaNotificationAction(
+    val isAuthenticationRequired: Boolean,
+    val actionIntent: PendingIntent?,
+    val icon: Drawable?,
+    val contentDescription: CharSequence?
+)
+
 /** State of the media device. */
 data class MediaDeviceData
 @JvmOverloads
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
index 87610cf..8bec46a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
@@ -21,6 +21,7 @@
 import static com.android.settingslib.flags.Flags.legacyLeAudioSharing;
 import static com.android.systemui.Flags.communalHub;
 import static com.android.systemui.Flags.mediaLockscreenLaunchAnimation;
+import static com.android.systemui.media.controls.domain.pipeline.MediaActionsKt.getNotificationActions;
 import static com.android.systemui.media.controls.shared.model.SmartspaceMediaDataKt.NUM_REQUIRED_RECOMMENDATIONS;
 
 import android.animation.Animator;
@@ -1170,7 +1171,7 @@
 
             // Set all the generic buttons
             List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact();
-            List<MediaAction> actions = data.getActions();
+            List<MediaAction> actions = getNotificationActions(data.getActions(), mActivityStarter);
             int i = 0;
             for (; i < actions.size() && i < genericButtons.size(); i++) {
                 boolean showInCompact = actionsWhenCollapsed.contains(i);
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 6bd880d..89d76f0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -29,6 +29,7 @@
 import static java.util.stream.Collectors.joining;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -1331,21 +1332,20 @@
         }
     }
 
-    public void setBackAnimation(BackAnimation backAnimation) {
+    public void setBackAnimation(@Nullable BackAnimation backAnimation) {
         mBackAnimation = backAnimation;
-        mBackAnimation.setPilferPointerCallback(() -> {
-            pilferPointers();
-        });
-        mBackAnimation.setTopUiRequestCallback(
-                (requestTopUi, tag) -> mUiThreadContext.getExecutor().execute(() ->
-                        mNotificationShadeWindowController.setRequestTopUi(requestTopUi, tag)));
-        updateBackAnimationThresholds();
-        if (mLightBarControllerProvider.get() != null) {
-            mBackAnimation.setStatusBarCustomizer((appearance) -> {
-                mUiThreadContext.getExecutor().execute(() ->
-                        mLightBarControllerProvider.get()
-                                .customizeStatusBarAppearance(appearance));
-            });
+        if (backAnimation != null) {
+            backAnimation.setPilferPointerCallback(this::pilferPointers);
+            backAnimation.setTopUiRequestCallback(
+                    (requestTopUi, tag) -> mUiThreadContext.getExecutor().execute(() ->
+                            mNotificationShadeWindowController.setRequestTopUi(requestTopUi, tag)));
+            updateBackAnimationThresholds();
+            if (mLightBarControllerProvider.get() != null) {
+                mBackAnimation.setStatusBarCustomizer((appearance) ->
+                        mUiThreadContext.getExecutor().execute(() ->
+                            mLightBarControllerProvider.get()
+                                    .customizeStatusBarAppearance(appearance)));
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
index a5c07bc..11854d9 100644
--- a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
@@ -18,9 +18,13 @@
 
 import com.android.compose.animation.scene.Back
 import com.android.compose.animation.scene.Swipe
+import com.android.compose.animation.scene.SwipeDirection
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
+import com.android.compose.animation.scene.UserActionResult.ReplaceByOverlay
+import com.android.systemui.scene.shared.model.Overlays
 import com.android.systemui.scene.shared.model.SceneFamilies
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge
 import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
@@ -34,8 +38,10 @@
     override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
         setActions(
             mapOf(
-                Swipe.Up to SceneFamilies.Home,
                 Back to SceneFamilies.Home,
+                Swipe.Up to SceneFamilies.Home,
+                Swipe(direction = SwipeDirection.Down, fromSource = SceneContainerEdge.TopRight) to
+                    ReplaceByOverlay(Overlays.QuickSettingsShade),
             )
         )
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index cbcf68c..2f843ac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -50,10 +50,12 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.WorkerThread;
 
+import com.android.systemui.Flags;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.time.SystemClock;
 
 import dagger.assisted.Assisted;
 import dagger.assisted.AssistedFactory;
@@ -95,6 +97,7 @@
     // Bind retry control.
     private static final int MAX_BIND_RETRIES = 5;
     private static final long DEFAULT_BIND_RETRY_DELAY = 5 * DateUtils.SECOND_IN_MILLIS;
+    private static final long ACTIVE_TILE_BIND_RETRY_DELAY = 1 * DateUtils.SECOND_IN_MILLIS;
     private static final long LOW_MEMORY_BIND_RETRY_DELAY = 20 * DateUtils.SECOND_IN_MILLIS;
     private static final long TILE_SERVICE_ONCLICK_ALLOW_LIST_DEFAULT_DURATION_MS = 15_000;
     private static final String PROPERTY_TILE_SERVICE_ONCLICK_ALLOW_LIST_DURATION =
@@ -107,6 +110,7 @@
     private final Intent mIntent;
     private final UserHandle mUser;
     private final DelayableExecutor mExecutor;
+    private final SystemClock mSystemClock;
     private final IBinder mToken = new Binder();
     private final PackageManagerAdapter mPackageManagerAdapter;
     private final BroadcastDispatcher mBroadcastDispatcher;
@@ -120,7 +124,6 @@
     private IBinder mClickBinder;
 
     private int mBindTryCount;
-    private long mBindRetryDelay = DEFAULT_BIND_RETRY_DELAY;
     private AtomicBoolean isDeathRebindScheduled = new AtomicBoolean(false);
     private AtomicBoolean mBound = new AtomicBoolean(false);
     private AtomicBoolean mPackageReceiverRegistered = new AtomicBoolean(false);
@@ -138,7 +141,8 @@
     TileLifecycleManager(@Main Handler handler, Context context, IQSService service,
             PackageManagerAdapter packageManagerAdapter, BroadcastDispatcher broadcastDispatcher,
             @Assisted Intent intent, @Assisted UserHandle user, ActivityManager activityManager,
-            IDeviceIdleController deviceIdleController, @Background DelayableExecutor executor) {
+            IDeviceIdleController deviceIdleController, @Background DelayableExecutor executor,
+            SystemClock systemClock) {
         mContext = context;
         mHandler = handler;
         mIntent = intent;
@@ -146,6 +150,7 @@
         mIntent.putExtra(TileService.EXTRA_TOKEN, mToken);
         mUser = user;
         mExecutor = executor;
+        mSystemClock = systemClock;
         mPackageManagerAdapter = packageManagerAdapter;
         mBroadcastDispatcher = broadcastDispatcher;
         mActivityManager = activityManager;
@@ -436,25 +441,31 @@
             // If mBound is true (meaning that we should be bound), then reschedule binding for
             // later.
             if (mBound.get() && checkComponentState()) {
-                if (isDeathRebindScheduled.compareAndSet(false, true)) {
+                if (isDeathRebindScheduled.compareAndSet(false, true)) { // if already not scheduled
+
+
                     mExecutor.executeDelayed(() -> {
                         // Only rebind if we are supposed to, but remove the scheduling anyway.
                         if (mBound.get()) {
                             setBindService(true);
                         }
-                        isDeathRebindScheduled.set(false);
+                        isDeathRebindScheduled.set(false); // allow scheduling again
                     }, getRebindDelay());
                 }
             }
         });
     }
 
+    private long mLastRebind = 0;
     /**
      * @return the delay to automatically rebind after a service died. It provides a longer delay if
      * the device is a low memory state because the service is likely to get killed again by the
      * system. In this case we want to rebind later and not to cause a loop of a frequent rebinds.
+     * It also provides a longer delay if called quickly (a few seconds) after a first call.
      */
     private long getRebindDelay() {
+        final long now = mSystemClock.currentTimeMillis();
+
         final ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
         mActivityManager.getMemoryInfo(info);
 
@@ -462,7 +473,20 @@
         if (info.lowMemory) {
             delay = LOW_MEMORY_BIND_RETRY_DELAY;
         } else {
-            delay = mBindRetryDelay;
+            if (Flags.qsQuickRebindActiveTiles()) {
+                final long elapsedTimeSinceLastRebind = now - mLastRebind;
+                final boolean justAttemptedRebind =
+                        elapsedTimeSinceLastRebind < DEFAULT_BIND_RETRY_DELAY;
+                if (isActiveTile() && !justAttemptedRebind) {
+                    delay = ACTIVE_TILE_BIND_RETRY_DELAY;
+                } else {
+                    delay = DEFAULT_BIND_RETRY_DELAY;
+                }
+            } else {
+                delay = DEFAULT_BIND_RETRY_DELAY;
+            }
+
+            mLastRebind = now;
         }
         if (mDebug) Log.i(TAG, "Rebinding with a delay=" + delay + " - " + getComponent());
         return delay;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index d10471d..c5fa8cf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -44,7 +44,7 @@
 /**
  * Manages the priority which lets {@link TileServices} make decisions about which tiles
  * to bind.  Also holds on to and manages the {@link TileLifecycleManager}, informing it
- * of when it is allowed to bind based on decisions frome the {@link TileServices}.
+ * of when it is allowed to bind based on decisions from the {@link TileServices}.
  */
 public class TileServiceManager {
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java
index b96e83d..f723ff2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.qs.tiles;
 
+import static com.android.systemui.accessibility.hearingaid.HearingDevicesUiEventLogger.LAUNCH_SOURCE_QS_TILE;
+
 import android.content.Intent;
 import android.os.Handler;
 import android.os.Looper;
@@ -96,7 +98,7 @@
 
     @Override
     protected void handleClick(@Nullable Expandable expandable) {
-        mUiHandler.post(() -> mDialogManager.showDialog(expandable));
+        mUiHandler.post(() -> mDialogManager.showDialog(expandable, LAUNCH_SOURCE_QS_TILE));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
index a3feb2b..d89e73d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
@@ -43,12 +43,14 @@
 import com.android.systemui.qs.logging.QSLogger
 import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
 import com.android.systemui.qs.tileimpl.QSTileImpl
-import com.android.systemui.recordissue.IssueRecordingService
+import com.android.systemui.recordissue.IssueRecordingService.Companion.getStartIntent
+import com.android.systemui.recordissue.IssueRecordingService.Companion.getStopIntent
 import com.android.systemui.recordissue.IssueRecordingState
 import com.android.systemui.recordissue.RecordIssueDialogDelegate
 import com.android.systemui.recordissue.RecordIssueModule.Companion.TILE_SPEC
 import com.android.systemui.recordissue.TraceurMessageSender
 import com.android.systemui.res.R
+import com.android.systemui.screenrecord.RecordingController
 import com.android.systemui.screenrecord.RecordingService
 import com.android.systemui.settings.UserContextProvider
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil
@@ -56,6 +58,9 @@
 import java.util.concurrent.Executor
 import javax.inject.Inject
 
+const val DELAY_MS: Long = 0
+const val INTERVAL_MS: Long = 1000
+
 class RecordIssueTile
 @Inject
 constructor(
@@ -77,6 +82,7 @@
     @Background private val bgExecutor: Executor,
     private val issueRecordingState: IssueRecordingState,
     private val delegateFactory: RecordIssueDialogDelegate.Factory,
+    private val recordingController: RecordingController,
 ) :
     QSTileImpl<QSTile.BooleanState>(
         host,
@@ -132,23 +138,25 @@
     }
 
     private fun startIssueRecordingService() =
-        PendingIntent.getForegroundService(
-                userContextProvider.userContext,
-                RecordingService.REQUEST_CODE,
-                IssueRecordingService.getStartIntent(userContextProvider.userContext),
-                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
-            )
-            .send(BroadcastOptions.makeBasic().apply { isInteractive = true }.toBundle())
+        recordingController.startCountdown(
+            DELAY_MS,
+            INTERVAL_MS,
+            pendingServiceIntent(getStartIntent(userContextProvider.userContext)),
+            pendingServiceIntent(getStopIntent(userContextProvider.userContext))
+        )
 
     private fun stopIssueRecordingService() =
-        PendingIntent.getService(
-                userContextProvider.userContext,
-                RecordingService.REQUEST_CODE,
-                IssueRecordingService.getStopIntent(userContextProvider.userContext),
-                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
-            )
+        pendingServiceIntent(getStopIntent(userContextProvider.userContext))
             .send(BroadcastOptions.makeBasic().apply { isInteractive = true }.toBundle())
 
+    private fun pendingServiceIntent(action: Intent) =
+        PendingIntent.getService(
+            userContextProvider.userContext,
+            RecordingService.REQUEST_CODE,
+            action,
+            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+        )
+
     private fun showPrompt(expandable: Expandable?) {
         val dialog: AlertDialog =
             delegateFactory
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt
index 4971fef..0c8a375 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt
@@ -19,6 +19,7 @@
 import android.app.AlertDialog
 import android.app.BroadcastOptions
 import android.app.PendingIntent
+import android.content.Intent
 import android.util.Log
 import com.android.internal.jank.InteractionJankMonitor
 import com.android.systemui.animation.DialogCuj
@@ -27,12 +28,16 @@
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
+import com.android.systemui.qs.tiles.DELAY_MS
+import com.android.systemui.qs.tiles.INTERVAL_MS
 import com.android.systemui.qs.tiles.base.interactor.QSTileInput
 import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
 import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
-import com.android.systemui.recordissue.IssueRecordingService
+import com.android.systemui.recordissue.IssueRecordingService.Companion.getStartIntent
+import com.android.systemui.recordissue.IssueRecordingService.Companion.getStopIntent
 import com.android.systemui.recordissue.RecordIssueDialogDelegate
 import com.android.systemui.recordissue.RecordIssueModule.Companion.TILE_SPEC
+import com.android.systemui.screenrecord.RecordingController
 import com.android.systemui.screenrecord.RecordingService
 import com.android.systemui.settings.UserContextProvider
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil
@@ -53,6 +58,7 @@
     private val panelInteractor: PanelInteractor,
     private val userContextProvider: UserContextProvider,
     private val delegateFactory: RecordIssueDialogDelegate.Factory,
+    private val recordingController: RecordingController,
 ) : QSTileUserActionInteractor<IssueRecordingModel> {
 
     override suspend fun handleInput(input: QSTileInput<IssueRecordingModel>) {
@@ -95,20 +101,22 @@
     }
 
     private fun startIssueRecordingService() =
-        PendingIntent.getForegroundService(
-                userContextProvider.userContext,
-                RecordingService.REQUEST_CODE,
-                IssueRecordingService.getStartIntent(userContextProvider.userContext),
-                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
-            )
-            .send(BroadcastOptions.makeBasic().apply { isInteractive = true }.toBundle())
+        recordingController.startCountdown(
+            DELAY_MS,
+            INTERVAL_MS,
+            pendingServiceIntent(getStartIntent(userContextProvider.userContext)),
+            pendingServiceIntent(getStopIntent(userContextProvider.userContext))
+        )
 
     private fun stopIssueRecordingService() =
-        PendingIntent.getService(
-                userContextProvider.userContext,
-                RecordingService.REQUEST_CODE,
-                IssueRecordingService.getStopIntent(userContextProvider.userContext),
-                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
-            )
+        pendingServiceIntent(getStopIntent(userContextProvider.userContext))
             .send(BroadcastOptions.makeBasic().apply { isInteractive = true }.toBundle())
+
+    private fun pendingServiceIntent(action: Intent) =
+        PendingIntent.getService(
+            userContextProvider.userContext,
+            RecordingService.REQUEST_CODE,
+            action,
+            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+        )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt
index c2d112e..483373d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt
@@ -20,13 +20,16 @@
 import android.content.Context
 import android.os.UserHandle
 import com.android.app.tracing.coroutines.flow.map
+import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.common.shared.model.asIcon
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.qs.tiles.ModesTile
 import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
 import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
 import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
 import com.android.systemui.statusbar.policy.domain.model.ActiveZenModes
+import com.android.systemui.statusbar.policy.domain.model.ZenModeInfo
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.Flow
@@ -61,28 +64,39 @@
     suspend fun getCurrentTileModel() = buildTileData(zenModeInteractor.getActiveModes())
 
     private fun buildTileData(activeModes: ActiveZenModes): ModesTileModel {
-        val modesIconResId = com.android.internal.R.drawable.ic_zen_priority_modes
-
         if (usesModeIcons()) {
-            val mainModeDrawable = activeModes.mainMode?.icon?.drawable
-            val iconResId = if (mainModeDrawable == null) modesIconResId else null
-
+            val tileIcon = getTileIcon(activeModes.mainMode)
             return ModesTileModel(
                 isActivated = activeModes.isAnyActive(),
-                icon = (mainModeDrawable ?: context.getDrawable(modesIconResId)!!).asIcon(),
-                iconResId = iconResId,
+                icon = tileIcon.icon,
+                iconResId = tileIcon.resId,
                 activeModes = activeModes.modeNames
             )
         } else {
             return ModesTileModel(
                 isActivated = activeModes.isAnyActive(),
-                icon = context.getDrawable(modesIconResId)!!.asIcon(),
-                iconResId = modesIconResId,
+                icon = context.getDrawable(ModesTile.ICON_RES_ID)!!.asIcon(),
+                iconResId = ModesTile.ICON_RES_ID,
                 activeModes = activeModes.modeNames
             )
         }
     }
 
+    private data class TileIcon(val icon: Icon.Loaded, val resId: Int?)
+
+    private fun getTileIcon(activeMode: ZenModeInfo?): TileIcon {
+        return if (activeMode != null) {
+            // ZenIconKey.resPackage is null if its resId is a system icon.
+            if (activeMode.icon.key.resPackage == null) {
+                TileIcon(activeMode.icon.drawable.asIcon(), activeMode.icon.key.resId)
+            } else {
+                TileIcon(activeMode.icon.drawable.asIcon(), null)
+            }
+        } else {
+            TileIcon(context.getDrawable(ModesTile.ICON_RES_ID)!!.asIcon(), ModesTile.ICON_RES_ID)
+        }
+    }
+
     override fun availability(user: UserHandle): Flow<Boolean> = flowOf(Flags.modesUi())
 
     private fun usesModeIcons() = Flags.modesApi() && Flags.modesUi() && Flags.modesUiIcons()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt
index 7f571b1..69da313 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt
@@ -36,9 +36,7 @@
 ) : QSTileDataToStateMapper<ModesTileModel> {
     override fun map(config: QSTileConfig, data: ModesTileModel): QSTileState =
         QSTileState.build(resources, theme, config.uiConfig) {
-            if (!android.app.Flags.modesUiIcons()) {
-                iconRes = data.iconResId
-            }
+            iconRes = data.iconResId
             icon = { data.icon }
             activationState =
                 if (data.isActivated) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
index d3dc302..bd1872d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
@@ -18,9 +18,13 @@
 
 import com.android.compose.animation.scene.Back
 import com.android.compose.animation.scene.Swipe
+import com.android.compose.animation.scene.SwipeDirection
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
+import com.android.compose.animation.scene.UserActionResult.ReplaceByOverlay
+import com.android.systemui.scene.shared.model.Overlays
 import com.android.systemui.scene.shared.model.SceneFamilies
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge
 import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
@@ -43,6 +47,13 @@
             .map { editing ->
                 buildMap {
                     put(Swipe.Up, UserActionResult(SceneFamilies.Home))
+                    put(
+                        Swipe(
+                            direction = SwipeDirection.Down,
+                            fromSource = SceneContainerEdge.TopLeft
+                        ),
+                        ReplaceByOverlay(Overlays.NotificationsShade)
+                    )
                     if (!editing) {
                         put(Back, UserActionResult(SceneFamilies.Home))
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
index 3d6d00e..a5f4a89 100644
--- a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
@@ -23,8 +23,6 @@
 import android.content.res.Resources
 import android.net.Uri
 import android.os.Handler
-import android.os.UserHandle
-import android.provider.Settings
 import android.util.Log
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.animation.DialogTransitionAnimator
@@ -50,11 +48,11 @@
     notificationManager: NotificationManager,
     userContextProvider: UserContextProvider,
     keyguardDismissUtil: KeyguardDismissUtil,
-    private val dialogTransitionAnimator: DialogTransitionAnimator,
-    private val panelInteractor: PanelInteractor,
-    private val traceurMessageSender: TraceurMessageSender,
+    dialogTransitionAnimator: DialogTransitionAnimator,
+    panelInteractor: PanelInteractor,
+    traceurMessageSender: TraceurMessageSender,
     private val issueRecordingState: IssueRecordingState,
-    private val iActivityManager: IActivityManager,
+    iActivityManager: IActivityManager,
 ) :
     RecordingService(
         controller,
@@ -66,6 +64,18 @@
         keyguardDismissUtil
     ) {
 
+    private val commandHandler =
+        IssueRecordingServiceCommandHandler(
+            bgExecutor,
+            dialogTransitionAnimator,
+            panelInteractor,
+            traceurMessageSender,
+            issueRecordingState,
+            iActivityManager,
+            notificationManager,
+            userContextProvider,
+        )
+
     override fun getTag(): String = TAG
 
     override fun getChannelId(): String = CHANNEL_ID
@@ -76,10 +86,7 @@
         Log.d(getTag(), "handling action: ${intent?.action}")
         when (intent?.action) {
             ACTION_START -> {
-                bgExecutor.execute {
-                    traceurMessageSender.startTracing(issueRecordingState.traceConfig)
-                }
-                issueRecordingState.isRecording = true
+                commandHandler.handleStartCommand()
                 if (!issueRecordingState.recordScreen) {
                     // If we don't want to record the screen, the ACTION_SHOW_START_NOTIF action
                     // will circumvent the RecordingService's screen recording start code.
@@ -87,41 +94,13 @@
                 }
             }
             ACTION_STOP,
-            ACTION_STOP_NOTIF -> {
-                // ViewCapture needs to save it's data before it is disabled, or else the data will
-                // be lost. This is expected to change in the near future, and when that happens
-                // this line should be removed.
-                bgExecutor.execute {
-                    if (issueRecordingState.traceConfig.longTrace) {
-                        Settings.Global.putInt(
-                            contentResolver,
-                            NOTIFY_SESSION_ENDED_SETTING,
-                            DISABLED
-                        )
-                    }
-                    traceurMessageSender.stopTracing()
-                }
-                issueRecordingState.isRecording = false
-            }
+            ACTION_STOP_NOTIF -> commandHandler.handleStopCommand(contentResolver)
             ACTION_SHARE -> {
-                bgExecutor.execute {
-                    mNotificationManager.cancelAsUser(
-                        null,
-                        intent.getIntExtra(EXTRA_NOTIFICATION_ID, mNotificationId),
-                        UserHandle(mUserContextTracker.userContext.userId)
-                    )
-
-                    val screenRecording = intent.getParcelableExtra(EXTRA_PATH, Uri::class.java)
-                    if (issueRecordingState.takeBugreport) {
-                        iActivityManager.requestBugReportWithExtraAttachment(screenRecording)
-                    } else {
-                        traceurMessageSender.shareTraces(applicationContext, screenRecording)
-                    }
-                }
-
-                dialogTransitionAnimator.disableAllCurrentDialogsExitAnimations()
-                panelInteractor.collapsePanels()
-
+                commandHandler.handleShareCommand(
+                    intent.getIntExtra(EXTRA_NOTIFICATION_ID, mNotificationId),
+                    intent.getParcelableExtra(EXTRA_PATH, Uri::class.java),
+                    this
+                )
                 // Unlike all other actions, action_share has different behavior for the screen
                 // recording qs tile than it does for the record issue qs tile. Return sticky to
                 // avoid running any of the base class' code for this action.
@@ -135,8 +114,6 @@
     companion object {
         private const val TAG = "IssueRecordingService"
         private const val CHANNEL_ID = "issue_record"
-        private const val NOTIFY_SESSION_ENDED_SETTING = "should_notify_trace_session_ended"
-        private const val DISABLED = 0
 
         /**
          * Get an intent to stop the issue recording service.
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceCommandHandler.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceCommandHandler.kt
new file mode 100644
index 0000000..32de0f3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceCommandHandler.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 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.recordissue
+
+import android.app.IActivityManager
+import android.app.NotificationManager
+import android.content.ContentResolver
+import android.content.Context
+import android.net.Uri
+import android.os.UserHandle
+import android.provider.Settings
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
+import com.android.systemui.settings.UserContextProvider
+import java.util.concurrent.Executor
+
+private const val NOTIFY_SESSION_ENDED_SETTING = "should_notify_trace_session_ended"
+private const val DISABLED = 0
+
+/**
+ * This class exists to unit test the business logic encapsulated in IssueRecordingService. Android
+ * specifically calls out that there is no supported way to test IntentServices here:
+ * https://developer.android.com/training/testing/other-components/services
+ */
+class IssueRecordingServiceCommandHandler(
+    private val bgExecutor: Executor,
+    private val dialogTransitionAnimator: DialogTransitionAnimator,
+    private val panelInteractor: PanelInteractor,
+    private val traceurMessageSender: TraceurMessageSender,
+    private val issueRecordingState: IssueRecordingState,
+    private val iActivityManager: IActivityManager,
+    private val notificationManager: NotificationManager,
+    private val userContextProvider: UserContextProvider,
+) {
+
+    fun handleStartCommand() {
+        bgExecutor.execute { traceurMessageSender.startTracing(issueRecordingState.traceConfig) }
+        issueRecordingState.isRecording = true
+    }
+
+    fun handleStopCommand(contentResolver: ContentResolver) {
+        bgExecutor.execute {
+            if (issueRecordingState.traceConfig.longTrace) {
+                Settings.Global.putInt(contentResolver, NOTIFY_SESSION_ENDED_SETTING, DISABLED)
+            }
+            traceurMessageSender.stopTracing()
+        }
+        issueRecordingState.isRecording = false
+    }
+
+    fun handleShareCommand(notificationId: Int, screenRecording: Uri?, context: Context) {
+        bgExecutor.execute {
+            notificationManager.cancelAsUser(
+                null,
+                notificationId,
+                UserHandle(userContextProvider.userContext.userId)
+            )
+
+            if (issueRecordingState.takeBugreport) {
+                iActivityManager.requestBugReportWithExtraAttachment(screenRecording)
+            } else {
+                traceurMessageSender.shareTraces(context, screenRecording)
+            }
+        }
+
+        dialogTransitionAnimator.disableAllCurrentDialogsExitAnimations()
+        panelInteractor.collapsePanels()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
index 00944b8..834db98 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.scene
 
+import androidx.compose.ui.unit.dp
 import com.android.systemui.CoreStartable
 import com.android.systemui.notifications.ui.composable.NotificationsShadeSessionModule
 import com.android.systemui.scene.domain.SceneDomainModule
@@ -30,6 +31,8 @@
 import com.android.systemui.scene.shared.model.Overlays
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.scene.ui.viewmodel.SplitEdgeDetector
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shade.shared.flag.DualShade
 import dagger.Binds
 import dagger.Module
@@ -119,5 +122,15 @@
                         .mapValues { checkNotNull(it.value) }
             )
         }
+
+        @Provides
+        fun splitEdgeDetector(shadeInteractor: ShadeInteractor): SplitEdgeDetector {
+            return SplitEdgeDetector(
+                topEdgeSplitFraction = shadeInteractor::getTopEdgeSplitFraction,
+                // TODO(b/338577208): This should be 60dp at the top in the dual-shade UI. Better to
+                //  replace this constant with dynamic window insets.
+                edgeSize = 40.dp
+            )
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
index 4061ad8..a4c7d00 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.scene
 
+import androidx.compose.ui.unit.dp
 import com.android.systemui.CoreStartable
 import com.android.systemui.notifications.ui.composable.NotificationsShadeSessionModule
 import com.android.systemui.scene.domain.SceneDomainModule
@@ -30,6 +31,8 @@
 import com.android.systemui.scene.shared.model.Overlays
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.scene.ui.viewmodel.SplitEdgeDetector
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shade.shared.flag.DualShade
 import dagger.Binds
 import dagger.Module
@@ -129,5 +132,15 @@
                         .mapValues { checkNotNull(it.value) }
             )
         }
+
+        @Provides
+        fun splitEdgeDetector(shadeInteractor: ShadeInteractor): SplitEdgeDetector {
+            return SplitEdgeDetector(
+                topEdgeSplitFraction = shadeInteractor::getTopEdgeSplitFraction,
+                // TODO(b/338577208): This should be 60dp at the top in the dual-shade UI. Better to
+                //  replace this constant with dynamic window insets.
+                edgeSize = 40.dp
+            )
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index e251c9e..98907b0 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -22,7 +22,9 @@
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.compose.animation.scene.SceneKey
 import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.AuthInteractionProperties
 import com.android.systemui.CoreStartable
+import com.android.systemui.Flags
 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
@@ -73,6 +75,8 @@
 import com.android.systemui.util.kotlin.sample
 import com.android.systemui.util.printSection
 import com.android.systemui.util.println
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.android.msdl.domain.MSDLPlayer
 import dagger.Lazy
 import java.io.PrintWriter
 import java.util.Optional
@@ -139,10 +143,13 @@
     private val statusBarStateController: SysuiStatusBarStateController,
     private val alternateBouncerInteractor: AlternateBouncerInteractor,
     private val vibratorHelper: VibratorHelper,
+    private val msdlPlayer: MSDLPlayer,
 ) : CoreStartable {
     private val centralSurfaces: CentralSurfaces?
         get() = centralSurfacesOptLazy.get().getOrNull()
 
+    private val authInteractionProperties = AuthInteractionProperties()
+
     override fun start() {
         if (SceneContainerFlag.isEnabled) {
             sceneLogger.logFrameworkEnabled(isEnabled = true)
@@ -541,9 +548,16 @@
                             deviceEntryHapticsInteractor.playSuccessHaptic
                                 .sample(sceneInteractor.currentScene)
                                 .collect { currentScene ->
-                                    vibratorHelper.vibrateAuthSuccess(
-                                        "$TAG, $currentScene device-entry::success"
-                                    )
+                                    if (Flags.msdlFeedback()) {
+                                        msdlPlayer.playToken(
+                                            MSDLToken.UNLOCK,
+                                            authInteractionProperties,
+                                        )
+                                    } else {
+                                        vibratorHelper.vibrateAuthSuccess(
+                                            "$TAG, $currentScene device-entry::success"
+                                        )
+                                    }
                                 }
                         }
 
@@ -551,9 +565,16 @@
                             deviceEntryHapticsInteractor.playErrorHaptic
                                 .sample(sceneInteractor.currentScene)
                                 .collect { currentScene ->
-                                    vibratorHelper.vibrateAuthError(
-                                        "$TAG, $currentScene device-entry::error"
-                                    )
+                                    if (Flags.msdlFeedback()) {
+                                        msdlPlayer.playToken(
+                                            MSDLToken.FAILURE,
+                                            authInteractionProperties,
+                                        )
+                                    } else {
+                                        vibratorHelper.vibrateAuthError(
+                                            "$TAG, $currentScene device-entry::error"
+                                        )
+                                    }
                                 }
                         }
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index 4c6341b..5482394 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -19,9 +19,11 @@
 import android.view.MotionEvent
 import androidx.compose.runtime.getValue
 import com.android.compose.animation.scene.ContentKey
+import com.android.compose.animation.scene.DefaultEdgeDetector
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.compose.animation.scene.OverlayKey
 import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.SwipeSourceDetector
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.classifier.Classifier
@@ -33,12 +35,15 @@
 import com.android.systemui.scene.shared.logger.SceneLogger
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.ui.composable.Overlay
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.shared.model.ShadeMode
 import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.map
 
 /** Models UI state for the scene container. */
 class SceneContainerViewModel
@@ -47,6 +52,8 @@
     private val sceneInteractor: SceneInteractor,
     private val falsingInteractor: FalsingInteractor,
     private val powerInteractor: PowerInteractor,
+    private val shadeInteractor: ShadeInteractor,
+    private val splitEdgeDetector: SplitEdgeDetector,
     private val logger: SceneLogger,
     @Assisted private val motionEventHandlerReceiver: (MotionEventHandler?) -> Unit,
 ) : ExclusiveActivatable() {
@@ -59,6 +66,20 @@
     /** Whether the container is visible. */
     val isVisible: Boolean by hydrator.hydratedStateOf("isVisible", sceneInteractor.isVisible)
 
+    /**
+     * The [SwipeSourceDetector] to use for defining which edges of the screen can be defined in the
+     * [UserAction]s for this container.
+     */
+    val edgeDetector: SwipeSourceDetector by
+        hydrator.hydratedStateOf(
+            traceName = "edgeDetector",
+            initialValue = DefaultEdgeDetector,
+            source =
+                shadeInteractor.shadeMode.map {
+                    if (it is ShadeMode.Dual) splitEdgeDetector else DefaultEdgeDetector
+                }
+        )
+
     override suspend fun onActivated(): Nothing {
         try {
             // Sends a MotionEventHandler to the owner of the view-model so they can report
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetector.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetector.kt
new file mode 100644
index 0000000..f88bcb5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetector.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2024 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.scene.ui.viewmodel
+
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
+import com.android.compose.animation.scene.Edge
+import com.android.compose.animation.scene.FixedSizeEdgeDetector
+import com.android.compose.animation.scene.SwipeSource
+import com.android.compose.animation.scene.SwipeSourceDetector
+
+/**
+ * The edge of a [SceneContainer]. It differs from a standard [Edge] by splitting the top edge into
+ * top-left and top-right.
+ */
+enum class SceneContainerEdge(private val resolveEdge: (LayoutDirection) -> Resolved) :
+    SwipeSource {
+    TopLeft(resolveEdge = { Resolved.TopLeft }),
+    TopRight(resolveEdge = { Resolved.TopRight }),
+    TopStart(
+        resolveEdge = { if (it == LayoutDirection.Ltr) Resolved.TopLeft else Resolved.TopRight }
+    ),
+    TopEnd(
+        resolveEdge = { if (it == LayoutDirection.Ltr) Resolved.TopRight else Resolved.TopLeft }
+    ),
+    Bottom(resolveEdge = { Resolved.Bottom }),
+    Left(resolveEdge = { Resolved.Left }),
+    Right(resolveEdge = { Resolved.Right }),
+    Start(resolveEdge = { if (it == LayoutDirection.Ltr) Resolved.Left else Resolved.Right }),
+    End(resolveEdge = { if (it == LayoutDirection.Ltr) Resolved.Right else Resolved.Left });
+
+    override fun resolve(layoutDirection: LayoutDirection): Resolved {
+        return resolveEdge(layoutDirection)
+    }
+
+    enum class Resolved : SwipeSource.Resolved {
+        TopLeft,
+        TopRight,
+        Bottom,
+        Left,
+        Right,
+    }
+}
+
+/**
+ * A [SwipeSourceDetector] that detects edges similarly to [FixedSizeEdgeDetector], except that the
+ * top edge is split in two: top-left and top-right. The split point between the two is dynamic and
+ * may change during runtime.
+ *
+ * Callers who need to detect the start and end edges based on the layout direction (LTR vs RTL)
+ * should subscribe to [SceneContainerEdge.TopStart] and [SceneContainerEdge.TopEnd] instead. These
+ * will be resolved at runtime to [SceneContainerEdge.Resolved.TopLeft] and
+ * [SceneContainerEdge.Resolved.TopRight] appropriately. Similarly, [SceneContainerEdge.Start] and
+ * [SceneContainerEdge.End] will be resolved appropriately to [SceneContainerEdge.Resolved.Left] and
+ * [SceneContainerEdge.Resolved.Right].
+ *
+ * @param topEdgeSplitFraction A function which returns the fraction between [0..1] (i.e.,
+ *   percentage) of screen width to consider the split point between "top-left" and "top-right"
+ *   edges. It is called on each source detection event.
+ * @param edgeSize The fixed size of each edge.
+ */
+class SplitEdgeDetector(
+    val topEdgeSplitFraction: () -> Float,
+    val edgeSize: Dp,
+) : SwipeSourceDetector {
+
+    private val fixedEdgeDetector = FixedSizeEdgeDetector(edgeSize)
+
+    override fun source(
+        layoutSize: IntSize,
+        position: IntOffset,
+        density: Density,
+        orientation: Orientation,
+    ): SceneContainerEdge.Resolved? {
+        val fixedEdge =
+            fixedEdgeDetector.source(
+                layoutSize,
+                position,
+                density,
+                orientation,
+            )
+        return when (fixedEdge) {
+            Edge.Resolved.Top -> {
+                val topEdgeSplitFraction = topEdgeSplitFraction()
+                require(topEdgeSplitFraction in 0f..1f) {
+                    "topEdgeSplitFraction must return a value between 0.0 and 1.0"
+                }
+                val isLeftSide = position.x < layoutSize.width * topEdgeSplitFraction
+                if (isLeftSide) SceneContainerEdge.Resolved.TopLeft
+                else SceneContainerEdge.Resolved.TopRight
+            }
+            Edge.Resolved.Left -> SceneContainerEdge.Resolved.Left
+            Edge.Resolved.Bottom -> SceneContainerEdge.Resolved.Bottom
+            Edge.Resolved.Right -> SceneContainerEdge.Resolved.Right
+            null -> null
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java
index a77375c..f69b0cb 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java
@@ -19,7 +19,6 @@
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
 
-import static com.android.systemui.Flags.screenshotSaveImageExporter;
 import static com.android.systemui.screenshot.LogConfig.DEBUG_ANIM;
 import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK;
 import static com.android.systemui.screenshot.LogConfig.DEBUG_INPUT;
@@ -133,7 +132,6 @@
     private final MessageContainerController mMessageContainerController;
     private final AnnouncementResolver mAnnouncementResolver;
     private Bitmap mScreenBitmap;
-    private SaveImageInBackgroundTask mSaveInBgTask;
     private boolean mScreenshotTakenInPortrait;
     private boolean mAttachRequested;
     private boolean mDetachRequested;
@@ -393,10 +391,6 @@
     // Any cleanup needed when the service is being destroyed.
     @Override
     public void onDestroy() {
-        if (mSaveInBgTask != null) {
-            // just log success/failure for the pre-existing screenshot
-            mSaveInBgTask.setActionsReadyListener(this::logSuccessOnActionsReady);
-        }
         removeWindow();
         releaseMediaPlayer();
         releaseContext();
@@ -598,36 +592,12 @@
         // Play the shutter sound to notify that we've taken a screenshot
         playCameraSoundIfNeeded();
 
-        if (screenshotSaveImageExporter()) {
-            saveScreenshotInBackground(screenshot, UUID.randomUUID(), finisher, result -> {
-                if (result.uri != null) {
-                    mScreenshotHandler.post(() -> Toast.makeText(mContext,
-                            R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show());
-                }
-            });
-        } else {
-            saveScreenshotInWorkerThread(
-                    screenshot.getUserHandle(),
-                    /* onComplete */ finisher,
-                    /* actionsReadyListener */ imageData -> {
-                        if (DEBUG_CALLBACK) {
-                            Log.d(TAG,
-                                    "returning URI to finisher (Consumer<URI>): " + imageData.uri);
-                        }
-                        finisher.accept(imageData.uri);
-                        if (imageData.uri == null) {
-                            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED, 0,
-                                    mPackageName);
-                            mNotificationsController.notifyScreenshotError(
-                                    R.string.screenshot_failed_to_save_text);
-                        } else {
-                            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED, 0, mPackageName);
-                            mScreenshotHandler.post(() -> Toast.makeText(mContext,
-                                    R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show());
-                        }
-                    },
-                    null);
-        }
+        saveScreenshotInBackground(screenshot, UUID.randomUUID(), finisher, result -> {
+            if (result.uri != null) {
+                mScreenshotHandler.post(() -> Toast.makeText(mContext,
+                        R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show());
+            }
+        });
     }
 
     /**
@@ -700,35 +670,6 @@
     }
 
     /**
-     * Creates a new worker thread and saves the screenshot to the media store.
-     */
-    private void saveScreenshotInWorkerThread(
-            UserHandle owner,
-            @NonNull Consumer<Uri> finisher,
-            @Nullable SaveImageInBackgroundTask.ActionsReadyListener actionsReadyListener,
-            @Nullable SaveImageInBackgroundTask.QuickShareActionReadyListener
-                    quickShareActionsReadyListener) {
-        SaveImageInBackgroundTask.SaveImageInBackgroundData
-                data = new SaveImageInBackgroundTask.SaveImageInBackgroundData();
-        data.image = mScreenBitmap;
-        data.finisher = finisher;
-        data.mActionsReadyListener = actionsReadyListener;
-        data.mQuickShareActionsReadyListener = quickShareActionsReadyListener;
-        data.owner = owner;
-        data.displayId = mDisplay.getDisplayId();
-
-        if (mSaveInBgTask != null) {
-            // just log success/failure for the pre-existing screenshot
-            mSaveInBgTask.setActionsReadyListener(this::logSuccessOnActionsReady);
-        }
-
-        mSaveInBgTask = new SaveImageInBackgroundTask(mContext, mFlags, mImageExporter,
-                mScreenshotSmartActions, data,
-                mScreenshotNotificationSmartActionsProvider);
-        mSaveInBgTask.execute();
-    }
-
-    /**
      * Logs success/failure of the screenshot saving task, and shows an error if it failed.
      */
     private void logScreenshotResultStatus(Uri uri, UserHandle owner) {
@@ -745,13 +686,6 @@
         }
     }
 
-    /**
-     * Logs success/failure of the screenshot saving task, and shows an error if it failed.
-     */
-    private void logSuccessOnActionsReady(SaveImageInBackgroundTask.SavedImageData imageData) {
-        logScreenshotResultStatus(imageData.uri, imageData.owner);
-    }
-
     private boolean isUserSetupComplete(UserHandle owner) {
         return Settings.Secure.getInt(mContext.createContextAsUser(owner, 0)
                 .getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
deleted file mode 100644
index 9bc3bd8..0000000
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ /dev/null
@@ -1,399 +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.screenshot;
-
-import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK;
-import static com.android.systemui.screenshot.LogConfig.DEBUG_STORAGE;
-import static com.android.systemui.screenshot.LogConfig.logTag;
-import static com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType;
-
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.ClipData;
-import android.content.ClipDescription;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.Process;
-import android.os.UserHandle;
-import android.provider.DeviceConfig;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
-import com.android.systemui.flags.FeatureFlags;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Random;
-import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
-import java.util.function.Consumer;
-
-/**
- * An AsyncTask that saves an image to the media store in the background.
- */
-class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
-    private static final String TAG = logTag(SaveImageInBackgroundTask.class);
-
-    private static final String SCREENSHOT_ID_TEMPLATE = "Screenshot_%s";
-    private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
-
-    /**
-     * POD used in the AsyncTask which saves an image in the background.
-     */
-    static class SaveImageInBackgroundData {
-        public Bitmap image;
-        public Consumer<Uri> finisher;
-        public ActionsReadyListener mActionsReadyListener;
-        public QuickShareActionReadyListener mQuickShareActionsReadyListener;
-        public UserHandle owner;
-        public int displayId;
-
-        void clearImage() {
-            image = null;
-        }
-    }
-
-    /**
-     * Structure returned by the SaveImageInBackgroundTask
-     */
-    public static class SavedImageData {
-        public Uri uri;
-        public List<Notification.Action> smartActions;
-        public Notification.Action quickShareAction;
-        public UserHandle owner;
-        public String subject;  // Title for sharing
-        public Long imageTime; // Time at which screenshot was saved
-
-        /**
-         * Used to reset the return data on error
-         */
-        public void reset() {
-            uri = null;
-            smartActions = null;
-            quickShareAction = null;
-            subject = null;
-            imageTime = null;
-        }
-    }
-
-    /**
-     * Structure returned by the QueryQuickShareInBackgroundTask
-     */
-    static class QuickShareData {
-        public Notification.Action quickShareAction;
-
-        /**
-         * Used to reset the return data on error
-         */
-        public void reset() {
-            quickShareAction = null;
-        }
-    }
-
-    interface ActionsReadyListener {
-        void onActionsReady(SavedImageData imageData);
-    }
-
-    interface QuickShareActionReadyListener {
-        void onActionsReady(QuickShareData quickShareData);
-    }
-
-    private final Context mContext;
-    private FeatureFlags mFlags;
-    private final ScreenshotSmartActions mScreenshotSmartActions;
-    private final SaveImageInBackgroundData mParams;
-    private final SavedImageData mImageData;
-    private final QuickShareData mQuickShareData;
-
-    private final ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
-    private String mScreenshotId;
-    private final Random mRandom = new Random();
-    private final ImageExporter mImageExporter;
-    private long mImageTime;
-
-    SaveImageInBackgroundTask(
-            Context context,
-            FeatureFlags flags,
-            ImageExporter exporter,
-            ScreenshotSmartActions screenshotSmartActions,
-            SaveImageInBackgroundData data,
-            ScreenshotNotificationSmartActionsProvider
-                    screenshotNotificationSmartActionsProvider
-    ) {
-        mContext = context;
-        mFlags = flags;
-        mScreenshotSmartActions = screenshotSmartActions;
-        mImageData = new SavedImageData();
-        mQuickShareData = new QuickShareData();
-        mImageExporter = exporter;
-
-        // Prepare all the output metadata
-        mParams = data;
-
-        // Initialize screenshot notification smart actions provider.
-        mSmartActionsProvider = screenshotNotificationSmartActionsProvider;
-    }
-
-    @Override
-    protected Void doInBackground(Void... paramsUnused) {
-        if (isCancelled()) {
-            if (DEBUG_STORAGE) {
-                Log.d(TAG, "cancelled! returning null");
-            }
-            return null;
-        }
-        // TODO: move to constructor / from ScreenshotRequest
-        final UUID requestId = UUID.randomUUID();
-
-        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
-
-        Bitmap image = mParams.image;
-        mScreenshotId = String.format(SCREENSHOT_ID_TEMPLATE, requestId);
-
-        boolean savingToOtherUser = mParams.owner != Process.myUserHandle();
-        // Smart actions don't yet work for cross-user saves.
-        boolean smartActionsEnabled = !savingToOtherUser
-                && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
-                SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS,
-                true);
-        try {
-            if (smartActionsEnabled && mParams.mQuickShareActionsReadyListener != null) {
-                // Since Quick Share target recommendation does not rely on image URL, it is
-                // queried and surfaced before image compress/export. Action intent would not be
-                // used, because it does not contain image URL.
-                Notification.Action quickShare =
-                        queryQuickShareAction(mScreenshotId, image, mParams.owner, null);
-                if (quickShare != null) {
-                    mQuickShareData.quickShareAction = quickShare;
-                    mParams.mQuickShareActionsReadyListener.onActionsReady(mQuickShareData);
-                }
-            }
-
-            // Call synchronously here since already on a background thread.
-            ListenableFuture<ImageExporter.Result> future =
-                    mImageExporter.export(Runnable::run, requestId, image, mParams.owner,
-                            mParams.displayId);
-            ImageExporter.Result result = future.get();
-            Log.d(TAG, "Saved screenshot: " + result);
-            final Uri uri = result.uri;
-            mImageTime = result.timestamp;
-
-            CompletableFuture<List<Notification.Action>> smartActionsFuture =
-                    mScreenshotSmartActions.getSmartActionsFuture(
-                            mScreenshotId, uri, image, mSmartActionsProvider,
-                            ScreenshotSmartActionType.REGULAR_SMART_ACTIONS,
-                            smartActionsEnabled, mParams.owner);
-            List<Notification.Action> smartActions = new ArrayList<>();
-            if (smartActionsEnabled) {
-                int timeoutMs = DeviceConfig.getInt(
-                        DeviceConfig.NAMESPACE_SYSTEMUI,
-                        SystemUiDeviceConfigFlags.SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS,
-                        1000);
-                smartActions.addAll(buildSmartActions(
-                        mScreenshotSmartActions.getSmartActions(
-                                mScreenshotId, smartActionsFuture, timeoutMs,
-                                mSmartActionsProvider,
-                                ScreenshotSmartActionType.REGULAR_SMART_ACTIONS),
-                        mContext));
-            }
-
-            mImageData.uri = uri;
-            mImageData.owner = mParams.owner;
-            mImageData.smartActions = smartActions;
-            mImageData.quickShareAction = createQuickShareAction(
-                    mQuickShareData.quickShareAction, mScreenshotId, uri, mImageTime, image,
-                    mParams.owner);
-            mImageData.subject = getSubjectString(mImageTime);
-            mImageData.imageTime = mImageTime;
-
-            mParams.mActionsReadyListener.onActionsReady(mImageData);
-            if (DEBUG_CALLBACK) {
-                Log.d(TAG, "finished background processing, Calling (Consumer<Uri>) "
-                        + "finisher.accept(\"" + mImageData.uri + "\"");
-            }
-            mParams.finisher.accept(mImageData.uri);
-            mParams.image = null;
-        } catch (Exception e) {
-            // IOException/UnsupportedOperationException may be thrown if external storage is
-            // not mounted
-            Log.d(TAG, "Failed to store screenshot", e);
-            mParams.clearImage();
-            mImageData.reset();
-            mQuickShareData.reset();
-            mParams.mActionsReadyListener.onActionsReady(mImageData);
-            if (DEBUG_CALLBACK) {
-                Log.d(TAG, "Calling (Consumer<Uri>) finisher.accept(null)");
-            }
-            mParams.finisher.accept(null);
-        }
-
-        return null;
-    }
-
-    /**
-     * Update the listener run when the saving task completes. Used to avoid showing UI for the
-     * first screenshot when a second one is taken.
-     */
-    void setActionsReadyListener(ActionsReadyListener listener) {
-        mParams.mActionsReadyListener = listener;
-    }
-
-    @Override
-    protected void onCancelled(Void params) {
-        // If we are cancelled while the task is running in the background, we may get null
-        // params. The finisher is expected to always be called back, so just use the baked-in
-        // params from the ctor in any case.
-        mImageData.reset();
-        mQuickShareData.reset();
-        mParams.mActionsReadyListener.onActionsReady(mImageData);
-        if (DEBUG_CALLBACK) {
-            Log.d(TAG, "onCancelled, calling (Consumer<Uri>) finisher.accept(null)");
-        }
-        mParams.finisher.accept(null);
-        mParams.clearImage();
-    }
-
-    private List<Notification.Action> buildSmartActions(
-            List<Notification.Action> actions, Context context) {
-        List<Notification.Action> broadcastActions = new ArrayList<>();
-        for (Notification.Action action : actions) {
-            // Proxy smart actions through {@link SmartActionsReceiver} for logging smart actions.
-            Bundle extras = action.getExtras();
-            String actionType = extras.getString(
-                    ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
-                    ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
-            Intent intent = new Intent(context, SmartActionsReceiver.class)
-                    .putExtra(SmartActionsReceiver.EXTRA_ACTION_INTENT, action.actionIntent)
-                    .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-            addIntentExtras(mScreenshotId, intent, actionType, true /* smartActionsEnabled */);
-            PendingIntent broadcastIntent = PendingIntent.getBroadcast(context,
-                    mRandom.nextInt(),
-                    intent,
-                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
-            broadcastActions.add(new Notification.Action.Builder(action.getIcon(), action.title,
-                    broadcastIntent).setContextual(true).addExtras(extras).build());
-        }
-        return broadcastActions;
-    }
-
-    private static void addIntentExtras(String screenshotId, Intent intent, String actionType,
-            boolean smartActionsEnabled) {
-        intent
-                .putExtra(SmartActionsReceiver.EXTRA_ACTION_TYPE, actionType)
-                .putExtra(SmartActionsReceiver.EXTRA_ID, screenshotId)
-                .putExtra(SmartActionsReceiver.EXTRA_SMART_ACTIONS_ENABLED, smartActionsEnabled);
-    }
-
-    /**
-     * Wrap the quickshare intent and populate the fillin intent with the URI
-     */
-    @VisibleForTesting
-    Notification.Action createQuickShareAction(
-            Notification.Action quickShare, String screenshotId, Uri uri, long imageTime,
-            Bitmap image, UserHandle user) {
-        if (quickShare == null) {
-            return null;
-        } else if (quickShare.actionIntent.isImmutable()) {
-            Notification.Action quickShareWithUri =
-                    queryQuickShareAction(screenshotId, image, user, uri);
-            if (quickShareWithUri == null
-                    || !quickShareWithUri.title.toString().contentEquals(quickShare.title)) {
-                return null;
-            }
-            quickShare = quickShareWithUri;
-        }
-
-        Intent wrappedIntent = new Intent(mContext, SmartActionsReceiver.class)
-                .putExtra(SmartActionsReceiver.EXTRA_ACTION_INTENT, quickShare.actionIntent)
-                .putExtra(SmartActionsReceiver.EXTRA_ACTION_INTENT_FILLIN,
-                        createFillInIntent(uri, imageTime))
-                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-        Bundle extras = quickShare.getExtras();
-        String actionType = extras.getString(
-                ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
-                ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
-        // We only query for quick share actions when smart actions are enabled, so we can assert
-        // that it's true here.
-        addIntentExtras(screenshotId, wrappedIntent, actionType, true /* smartActionsEnabled */);
-        PendingIntent broadcastIntent =
-                PendingIntent.getBroadcast(mContext, mRandom.nextInt(), wrappedIntent,
-                        PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
-        return new Notification.Action.Builder(quickShare.getIcon(), quickShare.title,
-                broadcastIntent)
-                .setContextual(true)
-                .addExtras(extras)
-                .build();
-    }
-
-    private Intent createFillInIntent(Uri uri, long imageTime) {
-        Intent fillIn = new Intent();
-        fillIn.setType("image/png");
-        fillIn.putExtra(Intent.EXTRA_STREAM, uri);
-        fillIn.putExtra(Intent.EXTRA_SUBJECT, getSubjectString(imageTime));
-        // Include URI in ClipData also, so that grantPermission picks it up.
-        // We don't use setData here because some apps interpret this as "to:".
-        ClipData clipData = new ClipData(
-                new ClipDescription("content", new String[]{"image/png"}),
-                new ClipData.Item(uri));
-        fillIn.setClipData(clipData);
-        fillIn.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        return fillIn;
-    }
-
-    /**
-     * Query and surface Quick Share chip if it is available. Action intent would not be used,
-     * because it does not contain image URL which would be populated in {@link
-     * #createQuickShareAction(Notification.Action, String, Uri, long, Bitmap, UserHandle)}
-     */
-
-    @VisibleForTesting
-    Notification.Action queryQuickShareAction(
-            String screenshotId, Bitmap image, UserHandle user, Uri uri) {
-        CompletableFuture<List<Notification.Action>> quickShareActionsFuture =
-                mScreenshotSmartActions.getSmartActionsFuture(
-                        screenshotId, uri, image, mSmartActionsProvider,
-                        ScreenshotSmartActionType.QUICK_SHARE_ACTION,
-                        true /* smartActionsEnabled */, user);
-        int timeoutMs = DeviceConfig.getInt(
-                DeviceConfig.NAMESPACE_SYSTEMUI,
-                SystemUiDeviceConfigFlags.SCREENSHOT_NOTIFICATION_QUICK_SHARE_ACTIONS_TIMEOUT_MS,
-                500);
-        List<Notification.Action> quickShareActions =
-                mScreenshotSmartActions.getSmartActions(
-                        screenshotId, quickShareActionsFuture, timeoutMs,
-                        mSmartActionsProvider,
-                        ScreenshotSmartActionType.QUICK_SHARE_ACTION);
-        if (!quickShareActions.isEmpty()) {
-            return quickShareActions.get(0);
-        }
-        return null;
-    }
-
-    private static String getSubjectString(long imageTime) {
-        String subjectDate = DateFormat.getDateTimeInstance().format(new Date(imageTime));
-        return String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 7b802a2..fe58bc9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -18,7 +18,6 @@
 
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 
-import static com.android.systemui.Flags.screenshotSaveImageExporter;
 import static com.android.systemui.screenshot.LogConfig.DEBUG_ANIM;
 import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK;
 import static com.android.systemui.screenshot.LogConfig.DEBUG_INPUT;
@@ -124,7 +123,6 @@
     private final MessageContainerController mMessageContainerController;
     private final AnnouncementResolver mAnnouncementResolver;
     private Bitmap mScreenBitmap;
-    private SaveImageInBackgroundTask mSaveInBgTask;
     private boolean mScreenshotTakenInPortrait;
     private Animator mScreenshotAnimation;
     private RequestCallback mCurrentRequestCallback;
@@ -373,10 +371,6 @@
     // Any cleanup needed when the service is being destroyed.
     @Override
     public void onDestroy() {
-        if (mSaveInBgTask != null) {
-            // just log success/failure for the pre-existing screenshot
-            mSaveInBgTask.setActionsReadyListener(this::logSuccessOnActionsReady);
-        }
         removeWindow();
         releaseMediaPlayer();
         releaseContext();
@@ -525,36 +519,12 @@
         // Play the shutter sound to notify that we've taken a screenshot
         playCameraSoundIfNeeded();
 
-        if (screenshotSaveImageExporter()) {
-            saveScreenshotInBackground(screenshot, UUID.randomUUID(), finisher, result -> {
-                if (result.uri != null) {
-                    mScreenshotHandler.post(() -> Toast.makeText(mContext,
-                            R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show());
-                }
-            });
-        } else {
-            saveScreenshotInWorkerThread(
-                    screenshot.getUserHandle(),
-                    /* onComplete */ finisher,
-                    /* actionsReadyListener */ imageData -> {
-                        if (DEBUG_CALLBACK) {
-                            Log.d(TAG,
-                                    "returning URI to finisher (Consumer<URI>): " + imageData.uri);
-                        }
-                        finisher.accept(imageData.uri);
-                        if (imageData.uri == null) {
-                            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED, 0,
-                                    mPackageName);
-                            mNotificationsController.notifyScreenshotError(
-                                    R.string.screenshot_failed_to_save_text);
-                        } else {
-                            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED, 0, mPackageName);
-                            mScreenshotHandler.post(() -> Toast.makeText(mContext,
-                                    R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show());
-                        }
-                    },
-                    null);
-        }
+        saveScreenshotInBackground(screenshot, UUID.randomUUID(), finisher, result -> {
+            if (result.uri != null) {
+                mScreenshotHandler.post(() -> Toast.makeText(mContext,
+                        R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show());
+            }
+        });
     }
 
     /**
@@ -627,35 +597,6 @@
     }
 
     /**
-     * Creates a new worker thread and saves the screenshot to the media store.
-     */
-    private void saveScreenshotInWorkerThread(
-            UserHandle owner,
-            @NonNull Consumer<Uri> finisher,
-            @Nullable SaveImageInBackgroundTask.ActionsReadyListener actionsReadyListener,
-            @Nullable SaveImageInBackgroundTask.QuickShareActionReadyListener
-                    quickShareActionsReadyListener) {
-        SaveImageInBackgroundTask.SaveImageInBackgroundData
-                data = new SaveImageInBackgroundTask.SaveImageInBackgroundData();
-        data.image = mScreenBitmap;
-        data.finisher = finisher;
-        data.mActionsReadyListener = actionsReadyListener;
-        data.mQuickShareActionsReadyListener = quickShareActionsReadyListener;
-        data.owner = owner;
-        data.displayId = mDisplay.getDisplayId();
-
-        if (mSaveInBgTask != null) {
-            // just log success/failure for the pre-existing screenshot
-            mSaveInBgTask.setActionsReadyListener(this::logSuccessOnActionsReady);
-        }
-
-        mSaveInBgTask = new SaveImageInBackgroundTask(mContext, mFlags, mImageExporter,
-                mScreenshotSmartActions, data,
-                mScreenshotNotificationSmartActionsProvider);
-        mSaveInBgTask.execute();
-    }
-
-    /**
      * Logs success/failure of the screenshot saving task, and shows an error if it failed.
      */
     private void logScreenshotResultStatus(Uri uri, UserHandle owner) {
@@ -672,13 +613,6 @@
         }
     }
 
-    /**
-     * Logs success/failure of the screenshot saving task, and shows an error if it failed.
-     */
-    private void logSuccessOnActionsReady(SaveImageInBackgroundTask.SavedImageData imageData) {
-        logScreenshotResultStatus(imageData.uri, imageData.owner);
-    }
-
     private boolean isUserSetupComplete(UserHandle owner) {
         return Settings.Secure.getInt(mContext.createContextAsUser(owner, 0)
                 .getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index ed590c3..553d1f5 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -103,11 +103,8 @@
     override val userContentResolver: ContentResolver
         get() = userContext.contentResolver
 
-    override val userInfo: UserInfo
-        get() {
-            val user = userId
-            return userProfiles.first { it.id == user }
-        }
+    override var userInfo: UserInfo by SynchronizedDelegate(UserInfo(context.userId, "", 0))
+        protected set
 
     /**
      * Returns a [List<UserInfo>] of all profiles associated with the current user.
@@ -187,6 +184,7 @@
             userHandle = handle
             userContext = ctx
             userProfiles = profiles.map { UserInfo(it) }
+            userInfo = profiles.first { it.id == user }
         }
         return ctx to profiles
     }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
index 830649b..4ed4af6 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
@@ -42,6 +42,7 @@
 import android.util.MathUtils;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
+import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.WindowInsets;
@@ -463,6 +464,9 @@
         mJavaAdapter.alwaysCollectFlow(
                 mCommunalTransitionViewModelLazy.get().isUmoOnCommunal(),
                 this::setShouldUpdateSquishinessOnMedia);
+        mJavaAdapter.alwaysCollectFlow(
+                mShadeInteractor.isAnyExpanded(),
+                this::onAnyExpandedChanged);
     }
 
     private void initNotificationStackScrollLayoutController() {
@@ -482,6 +486,10 @@
         }
     }
 
+    private void onAnyExpandedChanged(boolean isAnyExpanded) {
+        mQsFrame.setVisibility(isAnyExpanded ? View.VISIBLE : View.INVISIBLE);
+    }
+
     private void onNotificationScrolled(int newScrollPosition) {
         updateExpansionEnabledAmbient();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
index 73e86a2..3cd91be 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.shade.domain.interactor
 
+import androidx.annotation.FloatRange
 import com.android.systemui.shade.shared.model.ShadeMode
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
@@ -69,6 +70,20 @@
      * wide as the entire screen.
      */
     val isShadeLayoutWide: StateFlow<Boolean>
+
+    /**
+     * The fraction between [0..1] (i.e., percentage) of screen width to consider the threshold
+     * between "top-left" and "top-right" for the purposes of dual-shade invocation.
+     *
+     * When the dual-shade is not wide, this always returns 0.5 (the top edge is evenly split). On
+     * wide layouts however, a larger fraction is returned because only the area of the system
+     * status icons is considered top-right.
+     *
+     * Note that this fraction only determines the split between the absolute left and right
+     * directions. In RTL layouts, the "top-start" edge will resolve to "top-right", and "top-end"
+     * will resolve to "top-left".
+     */
+    @FloatRange(from = 0.0, to = 1.0) fun getTopEdgeSplitFraction(): Float
 }
 
 /** ShadeInteractor methods with implementations that differ between non-empty impls. */
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt
index d51fd28..6c0b55a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt
@@ -47,4 +47,6 @@
     override val isExpandToQsEnabled: Flow<Boolean> = inactiveFlowBoolean
     override val shadeMode: StateFlow<ShadeMode> = MutableStateFlow(ShadeMode.Single)
     override val isShadeLayoutWide: StateFlow<Boolean> = inactiveFlowBoolean
+
+    override fun getTopEdgeSplitFraction(): Float = 0.5f
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
index 3552092..b8d2dd2 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.shade.domain.interactor
 
+import androidx.annotation.FloatRange
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.data.repository.KeyguardRepository
@@ -104,6 +105,16 @@
 
     override val isShadeLayoutWide: StateFlow<Boolean> = shadeRepository.isShadeLayoutWide
 
+    @FloatRange(from = 0.0, to = 1.0)
+    override fun getTopEdgeSplitFraction(): Float {
+        // Note: this implicitly relies on isShadeLayoutWide being hot (i.e. collected). This
+        // assumption allows us to query its value on demand (during swipe source detection) instead
+        // of running another infinite coroutine.
+        // TODO(b/338577208): Instead of being fixed at 0.8f, this should dynamically updated based
+        //  on the position of system-status icons in the status bar.
+        return if (shadeRepository.isShadeLayoutWide.value) 0.8f else 0.5f
+    }
+
     override val shadeMode: StateFlow<ShadeMode> =
         isShadeLayoutWide
             .map(this::determineShadeMode)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
index 64dfc6c..735b4c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
@@ -54,6 +54,8 @@
             VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
     private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
             VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
+    private static final VibrationAttributes COMMUNICATION_REQUEST_VIBRATION_ATTRIBUTES =
+            VibrationAttributes.createForUsage(VibrationAttributes.USAGE_COMMUNICATION_REQUEST);
 
     private final Executor mExecutor;
 
@@ -151,7 +153,7 @@
         vibrate(Process.myUid(),
                 "com.android.systemui",
                 BIOMETRIC_SUCCESS_VIBRATION_EFFECT, reason,
-                HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
+                COMMUNICATION_REQUEST_VIBRATION_ATTRIBUTES);
     }
 
     /**
@@ -160,7 +162,7 @@
     public void vibrateAuthError(String reason) {
         vibrate(Process.myUid(), "com.android.systemui",
                 BIOMETRIC_ERROR_VIBRATION_EFFECT, reason,
-                HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
+                COMMUNICATION_REQUEST_VIBRATION_ATTRIBUTES);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/NotificationSettingsRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/NotificationSettingsRepositoryModule.kt
index af21e75..d36412c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/NotificationSettingsRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/NotificationSettingsRepositoryModule.kt
@@ -16,17 +16,23 @@
 
 package com.android.systemui.statusbar.notification.data
 
+import com.android.systemui.CoreStartable
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.settings.SecureSettingsRepositoryModule
 import com.android.systemui.settings.SystemSettingsRepositoryModule
 import com.android.systemui.shared.notifications.data.repository.NotificationSettingsRepository
 import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository
 import com.android.systemui.shared.settings.data.repository.SystemSettingsRepository
+import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionLogger
 import dagger.Module
 import dagger.Provides
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 
 @Module(includes = [SecureSettingsRepositoryModule::class, SystemSettingsRepositoryModule::class])
 object NotificationSettingsRepositoryModule {
@@ -42,6 +48,19 @@
             backgroundScope,
             backgroundDispatcher,
             secureSettingsRepository,
-            systemSettingsRepository
-        )
+            systemSettingsRepository)
+
+    @Provides
+    @IntoMap
+    @ClassKey(NotificationSettingsRepository::class)
+    @SysUISingleton
+    fun provideCoreStartable(
+        @Application applicationScope: CoroutineScope,
+        repository: NotificationSettingsRepository,
+        logger: VisualInterruptionDecisionLogger
+    ) = CoreStartable {
+        applicationScope.launch {
+            repository.isCooldownEnabled.collect { value -> logger.logCooldownSetting(value) }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionLogger.kt
index b83259d..38cab82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionLogger.kt
@@ -102,6 +102,15 @@
             { "AvalancheSuppressor: $str1" }
         )
     }
+
+    fun logCooldownSetting(isEnabled: Boolean) {
+        buffer.log(
+            TAG,
+            INFO,
+            { bool1 = isEnabled },
+            { "Cooldown enabled: $bool1" }
+        )
+    }
 }
 
 private const val TAG = "VisualInterruptionDecisionProvider"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationViewInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationViewInflater.kt
index 2c462b7..77c4130 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationViewInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationViewInflater.kt
@@ -198,12 +198,22 @@
                             parentView,
                             /* attachToRoot= */ false
                         ) as EnRouteView
-
                 InflatedContentViewHolder(newView) {
                     EnRouteViewBinder.bindWhileAttached(newView, createViewModel())
                 }
             }
-            RichOngoingNotificationViewType.Expanded,
+            RichOngoingNotificationViewType.Expanded -> {
+                val newView =
+                    LayoutInflater.from(systemUiContext)
+                        .inflate(
+                            R.layout.notification_template_en_route_expanded,
+                            parentView,
+                            /* attachToRoot= */ false
+                        ) as EnRouteView
+                InflatedContentViewHolder(newView) {
+                    EnRouteViewBinder.bindWhileAttached(newView, createViewModel())
+                }
+            }
             RichOngoingNotificationViewType.HeadsUp -> NullContentView
         }
     }
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 7c01784..1214440a 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
@@ -3691,6 +3691,10 @@
         if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
             switch (event.getAction()) {
                 case MotionEvent.ACTION_SCROLL: {
+                    // If scene container is active, NSSL should not control its own scrolling.
+                    if (SceneContainerFlag.isEnabled()) {
+                        return false;
+                    }
                     if (!mIsBeingDragged) {
                         final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
                         if (vscroll != 0) {
@@ -5400,7 +5404,9 @@
             println(pw, "intrinsicContentHeight", mIntrinsicContentHeight);
             println(pw, "contentHeight", mContentHeight);
             println(pw, "intrinsicPadding", mIntrinsicPadding);
-            println(pw, "topPadding", getTopPadding());
+            if (!SceneContainerFlag.isEnabled()) {
+                println(pw, "topPadding", getTopPadding());
+            }
             println(pw, "bottomPadding", mBottomPadding);
             dumpRoundedRectClipping(pw);
             println(pw, "requestedClipBounds", mRequestedClipBounds);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
index 580431a..969ff1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
@@ -68,6 +68,7 @@
         if (mLabelTextId != null) {
             mLabelView.setText(mLabelTextId);
         }
+        mLabelView.setAccessibilityHeading(true);
     }
 
     @Override
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 ef1bcfc..cccac4b 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
@@ -682,7 +682,10 @@
                 //  doesn't get updated quickly enough and can cause the footer to flash when
                 //  closing the shade. As such, we temporarily also check the ambientState directly.
                 if (((FooterView) view).shouldBeHidden() || !ambientState.isShadeExpanded()) {
-                    viewState.hidden = true;
+                    // Note: This is no longer necessary in flexiglass.
+                    if (!SceneContainerFlag.isEnabled()) {
+                        viewState.hidden = true;
+                    }
                 } else {
                     final float footerEnd = algorithmState.mCurrentExpandedYPosition
                             + view.getIntrinsicHeight();
@@ -691,7 +694,6 @@
                             noSpaceForFooter || (ambientState.isClearAllInProgress()
                                     && !hasNonClearableNotifs(algorithmState));
                 }
-
             } else {
                 final boolean shadeClosed = !ambientState.isShadeExpanded();
                 final boolean isShelfShowing = algorithmState.firstViewInShelf != null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
index d770b20..dc9615c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
@@ -188,15 +188,26 @@
                         .startHistoryIntent(view, /* showHistory= */ true)
                 },
             )
-        launch {
-            viewModel.shouldIncludeFooterView.collect { animatedVisibility ->
-                footerView.setVisible(
-                    /* visible = */ animatedVisibility.value,
-                    /* animate = */ animatedVisibility.isAnimating,
-                )
+        if (SceneContainerFlag.isEnabled) {
+            launch {
+                viewModel.shouldShowFooterView.collect { animatedVisibility ->
+                    footerView.setVisible(
+                        /* visible = */ animatedVisibility.value,
+                        /* animate = */ animatedVisibility.isAnimating,
+                    )
+                }
             }
+        } else {
+            launch {
+                viewModel.shouldIncludeFooterView.collect { animatedVisibility ->
+                    footerView.setVisible(
+                        /* visible = */ animatedVisibility.value,
+                        /* animate = */ animatedVisibility.isAnimating,
+                    )
+                }
+            }
+            launch { viewModel.shouldHideFooterView.collect { footerView.setShouldBeHidden(it) } }
         }
-        launch { viewModel.shouldHideFooterView.collect { footerView.setShouldBeHidden(it) } }
         disposableHandle.awaitCancellationThenDispose()
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
index e55492e6..4e2a46d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
@@ -32,6 +32,7 @@
 import com.android.systemui.statusbar.policy.domain.interactor.UserSetupInteractor
 import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
 import com.android.systemui.util.kotlin.FlowDumperImpl
+import com.android.systemui.util.kotlin.combine
 import com.android.systemui.util.kotlin.sample
 import com.android.systemui.util.ui.AnimatableEvent
 import com.android.systemui.util.ui.AnimatedValue
@@ -120,6 +121,7 @@
      * This essentially corresponds to having the view set to INVISIBLE.
      */
     val shouldHideFooterView: Flow<Boolean> by lazy {
+        SceneContainerFlag.assertInLegacyMode()
         if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
             flowOf(false)
         } else {
@@ -143,6 +145,7 @@
      * be hidden by another condition (see [shouldHideFooterView] above).
      */
     val shouldIncludeFooterView: Flow<AnimatedValue<Boolean>> by lazy {
+        SceneContainerFlag.assertInLegacyMode()
         if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
             flowOf(AnimatedValue.NotAnimating(false))
         } else {
@@ -207,6 +210,76 @@
         }
     }
 
+    // This flow replaces shouldHideFooterView+shouldIncludeFooterView in flexiglass.
+    val shouldShowFooterView: Flow<AnimatedValue<Boolean>> by lazy {
+        if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) {
+            flowOf(AnimatedValue.NotAnimating(false))
+        } else {
+            combine(
+                    activeNotificationsInteractor.areAnyNotificationsPresent,
+                    userSetupInteractor.isUserSetUp,
+                    notificationStackInteractor.isShowingOnLockscreen,
+                    shadeInteractor.isQsFullscreen,
+                    remoteInputInteractor.isRemoteInputActive,
+                    shadeInteractor.shadeExpansion.map { it < 0.5f }.distinctUntilChanged(),
+                ) {
+                    hasNotifications,
+                    isUserSetUp,
+                    isShowingOnLockscreen,
+                    qsFullScreen,
+                    isRemoteInputActive,
+                    shadeLessThanHalfwayExpanded ->
+                    when {
+                        !hasNotifications -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+                        // Hide the footer until the user setup is complete, to prevent access
+                        // to settings (b/193149550).
+                        !isUserSetUp -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+                        // Do not show the footer if the lockscreen is visible (incl. AOD),
+                        // except if the shade is opened on top. See also b/219680200.
+                        // Do not animate, as that makes the footer appear briefly when
+                        // transitioning between the shade and keyguard.
+                        isShowingOnLockscreen -> VisibilityChange.DISAPPEAR_WITHOUT_ANIMATION
+                        // Do not show the footer if quick settings are fully expanded (except
+                        // for the foldable split shade view). See b/201427195 && b/222699879.
+                        qsFullScreen -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+                        // Hide the footer if remote input is active (i.e. user is replying to a
+                        // notification). See b/75984847.
+                        isRemoteInputActive -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+                        // If the shade is not expanded enough, the footer shouldn't be visible.
+                        shadeLessThanHalfwayExpanded -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+                        else -> VisibilityChange.APPEAR_WITH_ANIMATION
+                    }
+                }
+                .distinctUntilChanged(
+                    // Equivalent unless visibility changes
+                    areEquivalent = { a: VisibilityChange, b: VisibilityChange ->
+                        a.visible == b.visible
+                    }
+                )
+                // Should we animate the visibility change?
+                .sample(
+                    // TODO(b/322167853): This check is currently duplicated in FooterViewModel,
+                    //  but instead it should be a field in ShadeAnimationInteractor.
+                    combine(
+                            shadeInteractor.isShadeFullyExpanded,
+                            shadeInteractor.isShadeTouchable,
+                            ::Pair
+                        )
+                        .onStart { emit(Pair(false, false)) }
+                ) { visibilityChange, (isShadeFullyExpanded, animationsEnabled) ->
+                    // Animate if the shade is interactive, but NOT on the lockscreen. Having
+                    // animations enabled while on the lockscreen makes the footer appear briefly
+                    // when transitioning between the shade and keyguard.
+                    val shouldAnimate =
+                        isShadeFullyExpanded && animationsEnabled && visibilityChange.canAnimate
+                    AnimatableEvent(visibilityChange.visible, shouldAnimate)
+                }
+                .toAnimatedValueFlow()
+                .dumpWhileCollecting("shouldShowFooterView")
+                .flowOn(bgDispatcher)
+        }
+    }
+
     enum class VisibilityChange(val visible: Boolean, val canAnimate: Boolean) {
         DISAPPEAR_WITHOUT_ANIMATION(visible = false, canAnimate = false),
         DISAPPEAR_WITH_ANIMATION(visible = false, canAnimate = true),
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 43f9af6..f3b9371 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -182,6 +182,7 @@
     private boolean mBouncerShowingOverDream;
     private int mAttemptsToShowBouncer = 0;
     private DelayableExecutor mExecutor;
+    private boolean mIsSleeping = false;
 
     private final PrimaryBouncerExpansionCallback mExpansionCallback =
             new PrimaryBouncerExpansionCallback() {
@@ -713,7 +714,11 @@
      * {@link #needsFullscreenBouncer()}.
      */
     protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing, boolean isFalsingReset) {
-        if (needsFullscreenBouncer() && !mDozing) {
+        boolean showBouncer = needsFullscreenBouncer() && !mDozing;
+        if (Flags.simPinRaceConditionOnRestart()) {
+            showBouncer = showBouncer && !mIsSleeping;
+        }
+        if (showBouncer) {
             // The keyguard might be showing (already). So we need to hide it.
             if (!primaryBouncerIsShowing()) {
                 if (SceneContainerFlag.isEnabled()) {
@@ -992,7 +997,7 @@
             } else {
                 showBouncerOrKeyguard(hideBouncerWhenShowing, isFalsingReset);
             }
-            if (!SceneContainerFlag.isEnabled() && hideBouncerWhenShowing) {
+            if (!SceneContainerFlag.isEnabled() && hideBouncerWhenShowing && isBouncerShowing()) {
                 hideAlternateBouncer(true);
                 mDismissCallbackRegistry.notifyDismissCancelled();
                 mPrimaryBouncerInteractor.setDismissAction(null, null);
@@ -1041,6 +1046,7 @@
 
     @Override
     public void onStartedWakingUp() {
+        mIsSleeping = false;
         setRootViewAnimationDisabled(false);
         NavigationBarView navBarView = mCentralSurfaces.getNavigationBarView();
         if (navBarView != null) {
@@ -1054,6 +1060,7 @@
 
     @Override
     public void onStartedGoingToSleep() {
+        mIsSleeping = true;
         setRootViewAnimationDisabled(true);
         NavigationBarView navBarView = mCentralSurfaces.getNavigationBarView();
         if (navBarView != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
index 85bbe7e..d601319 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
@@ -100,7 +100,14 @@
     val showSpn = getBooleanExtra(EXTRA_SHOW_SPN, false)
     val spn =
         if (statusBarSwitchToSpnFromDataSpn()) {
-            getStringExtra(EXTRA_SPN)
+            // Context: b/358669494. Use DATA_SPN if it exists, since that allows carriers to
+            // customize the display name. Otherwise, fall back to the SPN
+            val dataSpn = getStringExtra(EXTRA_DATA_SPN)
+            if (dataSpn.isNullOrEmpty()) {
+                getStringExtra(EXTRA_SPN)
+            } else {
+                dataSpn
+            }
         } else {
             getStringExtra(EXTRA_DATA_SPN)
         }
@@ -109,10 +116,8 @@
     val plmn = getStringExtra(EXTRA_PLMN)
 
     val str = StringBuilder()
-    val strData = StringBuilder()
     if (showPlmn && plmn != null) {
         str.append(plmn)
-        strData.append(plmn)
     }
     if (showSpn && spn != null) {
         if (str.isNotEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt
index 152d181..7163e67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt
@@ -101,29 +101,20 @@
 
     private fun FakeWifiEventModel.Wifi.toWifiNetworkModel(): WifiNetworkModel =
         WifiNetworkModel.Active(
-            networkId = DEMO_NET_ID,
             isValidated = validated ?: true,
             level = level ?: 0,
             ssid = ssid ?: DEMO_NET_SSID,
             hotspotDeviceType = hotspotDeviceType,
-
-            // These fields below aren't supported in demo mode, since they aren't needed to satisfy
-            // the interface.
-            isPasspointAccessPoint = false,
-            isOnlineSignUpForPasspointAccessPoint = false,
-            passpointProviderFriendlyName = null,
         )
 
     private fun FakeWifiEventModel.CarrierMerged.toCarrierMergedModel(): WifiNetworkModel =
         WifiNetworkModel.CarrierMerged(
-            networkId = DEMO_NET_ID,
             subscriptionId = subscriptionId,
             level = level,
             numberOfLevels = numberOfLevels,
         )
 
     companion object {
-        private const val DEMO_NET_ID = 1234
         private const val DEMO_NET_SSID = "Demo SSID"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index 7df4b2c..b6e73e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -250,7 +250,6 @@
             WifiNetworkModel.Invalid(CARRIER_MERGED_INVALID_SUB_ID_REASON)
         } else {
             WifiNetworkModel.CarrierMerged(
-                networkId = NETWORK_ID,
                 subscriptionId = this.subscriptionId,
                 level = this.level,
                 // WifiManager APIs to calculate the signal level start from 0, so
@@ -261,7 +260,17 @@
     }
 
     private fun WifiEntry.convertNormalToModel(): WifiNetworkModel {
-        if (this.level == WIFI_LEVEL_UNREACHABLE || this.level !in WIFI_LEVEL_MIN..WIFI_LEVEL_MAX) {
+        // WifiEntry instance values aren't guaranteed to be stable between method calls because
+        // WifiPickerTracker is continuously updating the same object. Save the level in a local
+        // variable so that checking the level validity here guarantees that the level will still be
+        // valid when we create the `WifiNetworkModel.Active` instance later. Otherwise, the level
+        // could be valid here but become invalid later, and `WifiNetworkModel.Active` will throw
+        // an exception. See b/362384551.
+        val currentLevel = this.level
+        if (
+            currentLevel == WIFI_LEVEL_UNREACHABLE ||
+                currentLevel !in WIFI_LEVEL_MIN..WIFI_LEVEL_MAX
+        ) {
             // If our level means the network is unreachable or the level is otherwise invalid, we
             // don't have an active network.
             return WifiNetworkModel.Inactive
@@ -275,19 +284,10 @@
             }
 
         return WifiNetworkModel.Active(
-            networkId = NETWORK_ID,
             isValidated = this.hasInternetAccess(),
-            level = this.level,
+            level = currentLevel,
             ssid = this.title,
             hotspotDeviceType = hotspotDeviceType,
-            // With WifiTrackerLib, [WifiEntry.title] will appropriately fetch the  SSID for
-            // typical wifi networks *and* passpoint/OSU APs. So, the AP-specific values can
-            // always be false/null in this repository.
-            // TODO(b/292534484): Remove these fields from the wifi network model once this
-            //  repository is fully enabled.
-            isPasspointAccessPoint = false,
-            isOnlineSignUpForPasspointAccessPoint = false,
-            passpointProviderFriendlyName = null,
         )
     }
 
@@ -428,19 +428,5 @@
         val ACTIVITY_DEFAULT = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
 
         private const val TAG = "WifiTrackerLibInputLog"
-
-        /**
-         * [WifiNetworkModel.Active.networkId] is only used at the repository layer. It's used by
-         * [WifiRepositoryImpl], which tracks the ID in order to correctly apply the framework
-         * callbacks within the repository.
-         *
-         * Since this class does not need to manually apply framework callbacks and since the
-         * network ID is not used beyond the repository, it's safe to use an invalid ID in this
-         * repository.
-         *
-         * The [WifiNetworkModel.Active.networkId] field should be deleted once we've fully migrated
-         * to [WifiRepositoryImpl].
-         */
-        private const val NETWORK_ID = -1
     }
 }
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 110e339..c0b0c4a 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
@@ -83,8 +83,6 @@
                 is WifiNetworkModel.CarrierMerged -> null
                 is WifiNetworkModel.Active ->
                     when {
-                        info.isPasspointAccessPoint || info.isOnlineSignUpForPasspointAccessPoint ->
-                            info.passpointProviderFriendlyName
                         info.hasValidSsid() -> info.ssid
                         else -> null
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt
index 7078a2e..39842fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.log.table.TableRowLogger
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
 import com.android.wifitrackerlib.HotspotNetworkEntry.DeviceType
+import com.android.wifitrackerlib.WifiEntry
 
 /** Provides information about the current wifi network. */
 sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
@@ -38,6 +39,7 @@
      */
     object Unavailable : WifiNetworkModel() {
         override fun toString() = "WifiNetwork.Unavailable"
+
         override fun logDiffs(prevVal: WifiNetworkModel, row: TableRowLogger) {
             if (prevVal is Unavailable) {
                 return
@@ -48,16 +50,12 @@
 
         override fun logFull(row: TableRowLogger) {
             row.logChange(COL_NETWORK_TYPE, TYPE_UNAVAILABLE)
-            row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
             row.logChange(COL_SUB_ID, SUB_ID_DEFAULT)
             row.logChange(COL_VALIDATED, false)
             row.logChange(COL_LEVEL, LEVEL_DEFAULT)
             row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT)
             row.logChange(COL_SSID, null)
             row.logChange(COL_HOTSPOT, null)
-            row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
-            row.logChange(COL_ONLINE_SIGN_UP, false)
-            row.logChange(COL_PASSPOINT_NAME, null)
         }
     }
 
@@ -67,6 +65,7 @@
         val invalidReason: String,
     ) : WifiNetworkModel() {
         override fun toString() = "WifiNetwork.Invalid[$invalidReason]"
+
         override fun logDiffs(prevVal: WifiNetworkModel, row: TableRowLogger) {
             if (prevVal !is Invalid) {
                 logFull(row)
@@ -80,16 +79,12 @@
 
         override fun logFull(row: TableRowLogger) {
             row.logChange(COL_NETWORK_TYPE, "$TYPE_UNAVAILABLE $invalidReason")
-            row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
             row.logChange(COL_SUB_ID, SUB_ID_DEFAULT)
             row.logChange(COL_VALIDATED, false)
             row.logChange(COL_LEVEL, LEVEL_DEFAULT)
             row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT)
             row.logChange(COL_SSID, null)
             row.logChange(COL_HOTSPOT, null)
-            row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
-            row.logChange(COL_ONLINE_SIGN_UP, false)
-            row.logChange(COL_PASSPOINT_NAME, null)
         }
     }
 
@@ -108,16 +103,12 @@
 
         override fun logFull(row: TableRowLogger) {
             row.logChange(COL_NETWORK_TYPE, TYPE_INACTIVE)
-            row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
             row.logChange(COL_SUB_ID, SUB_ID_DEFAULT)
             row.logChange(COL_VALIDATED, false)
             row.logChange(COL_LEVEL, LEVEL_DEFAULT)
             row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT)
             row.logChange(COL_SSID, null)
             row.logChange(COL_HOTSPOT, null)
-            row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
-            row.logChange(COL_ONLINE_SIGN_UP, false)
-            row.logChange(COL_PASSPOINT_NAME, null)
         }
     }
 
@@ -129,14 +120,6 @@
      */
     data class CarrierMerged(
         /**
-         * The [android.net.Network.netId] we received from
-         * [android.net.ConnectivityManager.NetworkCallback] in association with this wifi network.
-         *
-         * Importantly, **not** [android.net.wifi.WifiInfo.getNetworkId].
-         */
-        val networkId: Int,
-
-        /**
          * The subscription ID that this connection represents.
          *
          * Comes from [android.net.wifi.WifiInfo.getSubscriptionId].
@@ -154,7 +137,8 @@
     ) : WifiNetworkModel() {
         init {
             require(level in MIN_VALID_LEVEL..numberOfLevels) {
-                "0 <= wifi level <= $numberOfLevels required; level was $level"
+                "CarrierMerged: $MIN_VALID_LEVEL <= wifi level <= $numberOfLevels required; " +
+                    "level was $level"
             }
             require(subscriptionId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
                 "subscription ID cannot be invalid"
@@ -167,9 +151,6 @@
                 return
             }
 
-            if (prevVal.networkId != networkId) {
-                row.logChange(COL_NETWORK_ID, networkId)
-            }
             if (prevVal.subscriptionId != subscriptionId) {
                 row.logChange(COL_SUB_ID, subscriptionId)
             }
@@ -183,29 +164,17 @@
 
         override fun logFull(row: TableRowLogger) {
             row.logChange(COL_NETWORK_TYPE, TYPE_CARRIER_MERGED)
-            row.logChange(COL_NETWORK_ID, networkId)
             row.logChange(COL_SUB_ID, subscriptionId)
             row.logChange(COL_VALIDATED, true)
             row.logChange(COL_LEVEL, level)
             row.logChange(COL_NUM_LEVELS, numberOfLevels)
             row.logChange(COL_SSID, null)
             row.logChange(COL_HOTSPOT, null)
-            row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
-            row.logChange(COL_ONLINE_SIGN_UP, false)
-            row.logChange(COL_PASSPOINT_NAME, null)
         }
     }
 
     /** Provides information about an active wifi network. */
     data class Active(
-        /**
-         * The [android.net.Network.netId] we received from
-         * [android.net.ConnectivityManager.NetworkCallback] in association with this wifi network.
-         *
-         * Importantly, **not** [android.net.wifi.WifiInfo.getNetworkId].
-         */
-        val networkId: Int,
-
         /** See [android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED]. */
         val isValidated: Boolean = false,
 
@@ -220,19 +189,11 @@
          * isn't a hotspot connection.
          */
         val hotspotDeviceType: HotspotDeviceType = WifiNetworkModel.HotspotDeviceType.NONE,
-
-        /** See [android.net.wifi.WifiInfo.isPasspointAp]. */
-        val isPasspointAccessPoint: Boolean = false,
-
-        /** See [android.net.wifi.WifiInfo.isOsuAp]. */
-        val isOnlineSignUpForPasspointAccessPoint: Boolean = false,
-
-        /** See [android.net.wifi.WifiInfo.passpointProviderFriendlyName]. */
-        val passpointProviderFriendlyName: String? = null,
     ) : WifiNetworkModel() {
         init {
             require(level in MIN_VALID_LEVEL..MAX_VALID_LEVEL) {
-                "0 <= wifi level <= 4 required; level was $level"
+                "Active: $MIN_VALID_LEVEL <= wifi level <= $MAX_VALID_LEVEL required; " +
+                    "level was $level"
             }
         }
 
@@ -247,9 +208,6 @@
                 return
             }
 
-            if (prevVal.networkId != networkId) {
-                row.logChange(COL_NETWORK_ID, networkId)
-            }
             if (prevVal.isValidated != isValidated) {
                 row.logChange(COL_VALIDATED, isValidated)
             }
@@ -262,68 +220,25 @@
             if (prevVal.hotspotDeviceType != hotspotDeviceType) {
                 row.logChange(COL_HOTSPOT, hotspotDeviceType.name)
             }
-
-            // TODO(b/238425913): The passpoint-related values are frequently never used, so it
-            //   would be great to not log them when they're not used.
-            if (prevVal.isPasspointAccessPoint != isPasspointAccessPoint) {
-                row.logChange(COL_PASSPOINT_ACCESS_POINT, isPasspointAccessPoint)
-            }
-            if (
-                prevVal.isOnlineSignUpForPasspointAccessPoint !=
-                    isOnlineSignUpForPasspointAccessPoint
-            ) {
-                row.logChange(COL_ONLINE_SIGN_UP, isOnlineSignUpForPasspointAccessPoint)
-            }
-            if (prevVal.passpointProviderFriendlyName != passpointProviderFriendlyName) {
-                row.logChange(COL_PASSPOINT_NAME, passpointProviderFriendlyName)
-            }
         }
 
         override fun logFull(row: TableRowLogger) {
             row.logChange(COL_NETWORK_TYPE, TYPE_ACTIVE)
-            row.logChange(COL_NETWORK_ID, networkId)
             row.logChange(COL_SUB_ID, null)
             row.logChange(COL_VALIDATED, isValidated)
             row.logChange(COL_LEVEL, level)
             row.logChange(COL_NUM_LEVELS, null)
             row.logChange(COL_SSID, ssid)
             row.logChange(COL_HOTSPOT, hotspotDeviceType.name)
-            row.logChange(COL_PASSPOINT_ACCESS_POINT, isPasspointAccessPoint)
-            row.logChange(COL_ONLINE_SIGN_UP, isOnlineSignUpForPasspointAccessPoint)
-            row.logChange(COL_PASSPOINT_NAME, passpointProviderFriendlyName)
-        }
-
-        override fun toString(): String {
-            // Only include the passpoint-related values in the string if we have them. (Most
-            // networks won't have them so they'll be mostly clutter.)
-            val passpointString =
-                if (
-                    isPasspointAccessPoint ||
-                        isOnlineSignUpForPasspointAccessPoint ||
-                        passpointProviderFriendlyName != null
-                ) {
-                    ", isPasspointAp=$isPasspointAccessPoint, " +
-                        "isOnlineSignUpForPasspointAp=$isOnlineSignUpForPasspointAccessPoint, " +
-                        "passpointName=$passpointProviderFriendlyName"
-                } else {
-                    ""
-                }
-
-            return "WifiNetworkModel.Active(networkId=$networkId, isValidated=$isValidated, " +
-                "level=$level, ssid=$ssid$passpointString)"
         }
 
         companion object {
-            // TODO(b/292534484): Use [com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX] instead
-            // once the migration to WifiTrackerLib is complete.
-            @VisibleForTesting internal const val MAX_VALID_LEVEL = 4
+            @VisibleForTesting internal const val MAX_VALID_LEVEL = WifiEntry.WIFI_LEVEL_MAX
         }
     }
 
     companion object {
-        // TODO(b/292534484): Use [com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MIN] instead
-        // once the migration to WifiTrackerLib is complete.
-        @VisibleForTesting internal const val MIN_VALID_LEVEL = 0
+        @VisibleForTesting internal const val MIN_VALID_LEVEL = WifiEntry.WIFI_LEVEL_MIN
     }
 
     /**
@@ -367,18 +282,13 @@
 const val TYPE_ACTIVE = "Active"
 
 const val COL_NETWORK_TYPE = "type"
-const val COL_NETWORK_ID = "networkId"
 const val COL_SUB_ID = "subscriptionId"
 const val COL_VALIDATED = "isValidated"
 const val COL_LEVEL = "level"
 const val COL_NUM_LEVELS = "maxLevel"
 const val COL_SSID = "ssid"
 const val COL_HOTSPOT = "hotspot"
-const val COL_PASSPOINT_ACCESS_POINT = "isPasspointAccessPoint"
-const val COL_ONLINE_SIGN_UP = "isOnlineSignUpForPasspointAccessPoint"
-const val COL_PASSPOINT_NAME = "passpointProviderFriendlyName"
 
 val LEVEL_DEFAULT: String? = null
 val NUM_LEVELS_DEFAULT: String? = null
-val NETWORK_ID_DEFAULT: String? = null
 val SUB_ID_DEFAULT: String? = null
diff --git a/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt b/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt
index 4b0e5d1..6d99183 100644
--- a/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt
@@ -29,11 +29,12 @@
 class TelephonyInteractor
 @Inject
 constructor(
-    repository: TelephonyRepository,
+    private val repository: TelephonyRepository,
 ) {
     @Annotation.CallState val callState: Flow<Int> = repository.callState
 
     val isInCall: StateFlow<Boolean> = repository.isInCall
 
-    val hasTelephonyRadio: Boolean = repository.hasTelephonyRadio
+    val hasTelephonyRadio: Boolean
+        get() = repository.hasTelephonyRadio
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 8934d8f..d9e72bf 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -1305,13 +1305,12 @@
             if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
                 final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
                         STREAM_UNKNOWN);
-                final int level = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
                 final int oldLevel = intent
                         .getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);
                 if (D.BUG) Log.d(TAG, "onReceive VOLUME_CHANGED_ACTION stream=" + stream
-                        + " level=" + level + " oldLevel=" + oldLevel);
+                        + " oldLevel=" + oldLevel);
                 if (stream != STREAM_UNKNOWN) {
-                    changed = updateStreamLevelW(stream, level);
+                    changed |= onVolumeChangedW(stream, 0);
                 }
             } else if (action.equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION)) {
                 final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/CaptioningModule.kt b/packages/SystemUI/src/com/android/systemui/volume/dagger/CaptioningModule.kt
index 9715772..28a43df 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dagger/CaptioningModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/CaptioningModule.kt
@@ -16,35 +16,16 @@
 
 package com.android.systemui.volume.dagger
 
-import android.view.accessibility.CaptioningManager
 import com.android.systemui.accessibility.data.repository.CaptioningRepository
 import com.android.systemui.accessibility.data.repository.CaptioningRepositoryImpl
-import com.android.systemui.accessibility.domain.interactor.CaptioningInteractor
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Background
+import dagger.Binds
 import dagger.Module
-import dagger.Provides
-import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.CoroutineScope
 
 @Module
 interface CaptioningModule {
 
-    companion object {
-
-        @Provides
-        @SysUISingleton
-        fun provideCaptioningRepository(
-            captioningManager: CaptioningManager,
-            @Background coroutineContext: CoroutineContext,
-            @Application coroutineScope: CoroutineScope,
-        ): CaptioningRepository =
-            CaptioningRepositoryImpl(captioningManager, coroutineContext, coroutineScope)
-
-        @Provides
-        @SysUISingleton
-        fun provideCaptioningInteractor(repository: CaptioningRepository): CaptioningInteractor =
-            CaptioningInteractor(repository)
-    }
+    @Binds
+    @SysUISingleton
+    fun bindCaptioningRepository(impl: CaptioningRepositoryImpl): CaptioningRepository
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt
index 52f2ce6..2e5e389 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt
@@ -26,7 +26,7 @@
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.flow.stateIn
 
 @VolumePanelScope
 class CaptioningAvailabilityCriteria
@@ -45,7 +45,7 @@
                     else VolumePanelUiEvent.VOLUME_PANEL_LIVE_CAPTION_TOGGLE_GONE
                 )
             }
-            .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
     override fun isAvailable(): Flow<Boolean> = availability
 }
diff --git a/packages/SystemUI/tests/goldens/bouncerPredictiveBackMotion.json b/packages/SystemUI/tests/goldens/bouncerPredictiveBackMotion.json
new file mode 100644
index 0000000..f37580d
--- /dev/null
+++ b/packages/SystemUI/tests/goldens/bouncerPredictiveBackMotion.json
@@ -0,0 +1,831 @@
+{
+  "frame_ids": [
+    "before",
+    0,
+    16,
+    32,
+    48,
+    64,
+    80,
+    96,
+    112,
+    128,
+    144,
+    160,
+    176,
+    192,
+    208,
+    224,
+    240,
+    256,
+    272,
+    288,
+    304,
+    320,
+    336,
+    352,
+    368,
+    384,
+    400,
+    416,
+    432,
+    448,
+    464,
+    480,
+    496,
+    512,
+    528,
+    544,
+    560,
+    576,
+    592,
+    608,
+    624,
+    640,
+    656,
+    672,
+    688,
+    704,
+    720,
+    736,
+    752,
+    768,
+    784,
+    800,
+    816,
+    832,
+    848,
+    864,
+    880,
+    896,
+    912,
+    928,
+    944,
+    960,
+    976,
+    992,
+    1008,
+    1024,
+    "after"
+  ],
+  "features": [
+    {
+      "name": "content_alpha",
+      "type": "float",
+      "data_points": [
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        0.9954499,
+        0.9805035,
+        0.9527822,
+        0.9092045,
+        0.84588075,
+        0.7583043,
+        0.6424476,
+        0.49766344,
+        0.33080608,
+        0.15650165,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        {
+          "type": "not_found"
+        }
+      ]
+    },
+    {
+      "name": "content_scale",
+      "type": "scale",
+      "data_points": [
+        "default",
+        {
+          "x": 0.9995097,
+          "y": 0.9995097,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.997352,
+          "y": 0.997352,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.990635,
+          "y": 0.990635,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.97249764,
+          "y": 0.97249764,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.94287145,
+          "y": 0.94287145,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.9128026,
+          "y": 0.9128026,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8859569,
+          "y": 0.8859569,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8629254,
+          "y": 0.8629254,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8442908,
+          "y": 0.8442908,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8303209,
+          "y": 0.8303209,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8205137,
+          "y": 0.8205137,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.81387186,
+          "y": 0.81387186,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.80941653,
+          "y": 0.80941653,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.80641484,
+          "y": 0.80641484,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.80437464,
+          "y": 0.80437464,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.80297637,
+          "y": 0.80297637,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.80201286,
+          "y": 0.80201286,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8013477,
+          "y": 0.8013477,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8008894,
+          "y": 0.8008894,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8005756,
+          "y": 0.8005756,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.80036324,
+          "y": 0.80036324,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8002219,
+          "y": 0.8002219,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.80012995,
+          "y": 0.80012995,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8000721,
+          "y": 0.8000721,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.80003715,
+          "y": 0.80003715,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8000173,
+          "y": 0.8000173,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.800007,
+          "y": 0.800007,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8000022,
+          "y": 0.8000022,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8000004,
+          "y": 0.8000004,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.79999995,
+          "y": 0.79999995,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "x": 0.8,
+          "y": 0.8,
+          "pivot": "unspecified"
+        },
+        {
+          "type": "not_found"
+        }
+      ]
+    },
+    {
+      "name": "content_offset",
+      "type": "dpOffset",
+      "data_points": [
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "x": 0,
+          "y": 0.5714286
+        },
+        {
+          "x": 0,
+          "y": 2.857143
+        },
+        {
+          "x": 0,
+          "y": 7.142857
+        },
+        {
+          "x": 0,
+          "y": 13.714286
+        },
+        {
+          "x": 0,
+          "y": 23.142857
+        },
+        {
+          "x": 0,
+          "y": 36.285713
+        },
+        {
+          "x": 0,
+          "y": 53.714287
+        },
+        {
+          "x": 0,
+          "y": 75.42857
+        },
+        {
+          "x": 0,
+          "y": 100.28571
+        },
+        {
+          "x": 0,
+          "y": 126.57143
+        },
+        {
+          "x": 0,
+          "y": 151.42857
+        },
+        {
+          "x": 0,
+          "y": 174
+        },
+        {
+          "x": 0,
+          "y": 193.42857
+        },
+        {
+          "x": 0,
+          "y": 210.28572
+        },
+        {
+          "x": 0,
+          "y": 224.85715
+        },
+        {
+          "x": 0,
+          "y": 237.14285
+        },
+        {
+          "x": 0,
+          "y": 247.71428
+        },
+        {
+          "x": 0,
+          "y": 256.85715
+        },
+        {
+          "x": 0,
+          "y": 264.57144
+        },
+        {
+          "x": 0,
+          "y": 271.42856
+        },
+        {
+          "x": 0,
+          "y": 277.14285
+        },
+        {
+          "x": 0,
+          "y": 282
+        },
+        {
+          "x": 0,
+          "y": 286.2857
+        },
+        {
+          "x": 0,
+          "y": 289.7143
+        },
+        {
+          "x": 0,
+          "y": 292.57144
+        },
+        {
+          "x": 0,
+          "y": 294.85715
+        },
+        {
+          "x": 0,
+          "y": 296.85715
+        },
+        {
+          "x": 0,
+          "y": 298.2857
+        },
+        {
+          "x": 0,
+          "y": 299.14285
+        },
+        {
+          "x": 0,
+          "y": 299.7143
+        },
+        {
+          "x": 0,
+          "y": 300
+        },
+        {
+          "x": 0,
+          "y": 0
+        },
+        {
+          "type": "not_found"
+        }
+      ]
+    },
+    {
+      "name": "background_alpha",
+      "type": "float",
+      "data_points": [
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        0.9900334,
+        0.8403853,
+        0.71002257,
+        0.5979084,
+        0.50182605,
+        0.41945767,
+        0.34874845,
+        0.28797746,
+        0.23573697,
+        0.19087732,
+        0.1524564,
+        0.11970067,
+        0.091962695,
+        0.068702936,
+        0.049464583,
+        0.033859253,
+        0.021552086,
+        0.012255073,
+        0.005717635,
+        0.0017191172,
+        6.711483e-05,
+        0,
+        {
+          "type": "not_found"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
index a8ab922..d85b774 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
@@ -446,14 +446,10 @@
         assertFalse(mWifiRepository.isWifiConnectedWithValidSsid());
         mWifiRepository.setWifiNetwork(
                 new WifiNetworkModel.Active(
-                        /* networkId= */ 0,
                         /* isValidated= */ false,
                         /* level= */ 0,
                         /* ssid= */ "",
-                        /* hotspotDeviceType= */ WifiNetworkModel.HotspotDeviceType.NONE,
-                        /* isPasspointAccessPoint= */ false,
-                        /* isOnlineSignUpForPasspointAccessPoint= */ false,
-                        /* passpointProviderFriendlyName= */ null));
+                        /* hotspotDeviceType= */ WifiNetworkModel.HotspotDeviceType.NONE));
         assertTrue(mWifiRepository.isWifiConnectedWithValidSsid());
 
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
index 43a78035..c42e25b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
@@ -29,7 +29,7 @@
 import com.android.internal.widget.LockPatternUtils
 import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.haptics.msdl.FakeMSDLPlayer
+import com.android.systemui.haptics.msdl.fakeMSDLPlayer
 import com.android.systemui.haptics.msdl.msdlPlayer
 import com.android.systemui.shade.ShadeController
 import com.android.systemui.statusbar.policy.ConfigurationController
@@ -72,7 +72,7 @@
     val mainExecutor = FakeExecutor(fakeSystemClock)
     val backgroundExecutor = FakeExecutor(fakeSystemClock)
     private val kosmos = testKosmos()
-    private val msdlPlayer: FakeMSDLPlayer = kosmos.msdlPlayer
+    private val msdlPlayer = kosmos.fakeMSDLPlayer
 
     lateinit var underTest: EmergencyButtonController
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonModeObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonModeObserverTest.java
index 4a5c1be..038ec40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonModeObserverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonModeObserverTest.java
@@ -32,12 +32,14 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.SecureSettings;
 
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
@@ -66,7 +68,7 @@
                 Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
                 Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR, MY_USER_ID);
         mAccessibilityButtonModeObserver = new AccessibilityButtonModeObserver(mContext,
-                mUserTracker);
+                mUserTracker, Mockito.mock(SecureSettings.class));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserverTest.java
index a5a7a4a..f564926 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserverTest.java
@@ -31,12 +31,14 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.SecureSettings;
 
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
@@ -62,7 +64,7 @@
     public void setUp() {
         when(mUserTracker.getUserId()).thenReturn(MY_USER_ID);
         mAccessibilityButtonTargetsObserver = new AccessibilityButtonTargetsObserver(mContext,
-                mUserTracker);
+                mUserTracker, Mockito.mock(SecureSettings.class));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserverTest.java
index ba990ef..afed12f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserverTest.java
@@ -31,12 +31,14 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.SecureSettings;
 
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
@@ -62,7 +64,7 @@
     public void setUp() {
         when(mUserTracker.getUserId()).thenReturn(MY_USER_ID);
         mAccessibilityGestureTargetsObserver = new AccessibilityGestureTargetsObserver(mContext,
-                mUserTracker);
+                mUserTracker, Mockito.mock(SecureSettings.class));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/SecureSettingsContentObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/SecureSettingsContentObserverTest.java
index 9222fc2..1d88b90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/SecureSettingsContentObserverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/SecureSettingsContentObserverTest.java
@@ -27,6 +27,7 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.SecureSettings;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -72,7 +73,7 @@
 
         protected FakeSecureSettingsContentObserver(Context context, UserTracker userTracker,
                 String secureSettingsKey) {
-            super(context, userTracker, secureSettingsKey);
+            super(context, userTracker, Mockito.mock(SecureSettings.class), secureSettingsKey);
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
index d3b7d22..662815e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
@@ -52,7 +52,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.logging.UiEventLogger;
 import com.android.settingslib.bluetooth.BluetoothEventManager;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
@@ -92,6 +91,7 @@
     @Rule
     public MockitoRule mockito = MockitoJUnit.rule();
 
+    private static final int TEST_LAUNCH_SOURCE_ID = 1;
     private static final String DEVICE_ADDRESS = "AA:BB:CC:DD:EE:FF";
     private static final String DEVICE_NAME = "test_name";
     private static final String TEST_PKG = "pkg";
@@ -124,7 +124,7 @@
     @Mock
     private AudioManager mAudioManager;
     @Mock
-    private UiEventLogger mUiEventLogger;
+    private HearingDevicesUiEventLogger mUiEventLogger;
     @Mock
     private CachedBluetoothDevice mCachedDevice;
     @Mock
@@ -182,7 +182,8 @@
                 anyInt(), any());
         assertThat(intentCaptor.getValue().getAction()).isEqualTo(
                 Settings.ACTION_HEARING_DEVICE_PAIRING_SETTINGS);
-        verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_PAIR);
+        verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_PAIR,
+                TEST_LAUNCH_SOURCE_ID);
     }
 
     @Test
@@ -196,7 +197,8 @@
                 anyInt(), any());
         assertThat(intentCaptor.getValue().getAction()).isEqualTo(
                 HearingDevicesDialogDelegate.ACTION_BLUETOOTH_DEVICE_DETAILS);
-        verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_GEAR_CLICK);
+        verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_GEAR_CLICK,
+                TEST_LAUNCH_SOURCE_ID);
     }
 
     @Test
@@ -207,7 +209,8 @@
         mDialogDelegate.onDeviceItemClicked(mHearingDeviceItem, new View(mContext));
 
         verify(mCachedDevice).disconnect();
-        verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_DISCONNECT);
+        verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_DISCONNECT,
+                TEST_LAUNCH_SOURCE_ID);
     }
 
     @Test
@@ -304,6 +307,7 @@
         mDialogDelegate = new HearingDevicesDialogDelegate(
                 mContext,
                 true,
+                TEST_LAUNCH_SOURCE_ID,
                 mDialogFactory,
                 mActivityStarter,
                 mDialogTransitionAnimator,
@@ -327,6 +331,7 @@
         mDialogDelegate = new HearingDevicesDialogDelegate(
                 mContext,
                 false,
+                TEST_LAUNCH_SOURCE_ID,
                 mDialogFactory,
                 mActivityStarter,
                 mDialogTransitionAnimator,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
index 1e23690..7889b3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
@@ -61,10 +61,12 @@
 import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel
 import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel
 import com.android.systemui.display.data.repository.FakeDisplayRepository
+import com.android.systemui.haptics.msdl.msdlPlayer
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.statusbar.events.ANIMATING_OUT
+import com.android.systemui.testKosmos
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.time.FakeSystemClock
@@ -145,6 +147,9 @@
     private val credentialViewModel = CredentialViewModel(mContext, bpCredentialInteractor)
     private val defaultLogoIcon = context.getDrawable(R.drawable.ic_android)
 
+    private val kosmos = testKosmos()
+    private val msdlPlayer = kosmos.msdlPlayer
+
     private var authContainer: TestAuthContainerView? = null
 
     @Before
@@ -668,7 +673,8 @@
             { credentialViewModel },
             fakeExecutor,
             vibrator,
-            lazyViewCapture
+            lazyViewCapture,
+            msdlPlayer,
         ) {
         override fun postOnAnimation(runnable: Runnable) {
             runnable.run()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
index 4fc4166..55fd344 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
@@ -37,12 +37,15 @@
 import android.hardware.face.FaceSensorPropertiesInternal
 import android.hardware.fingerprint.FingerprintSensorProperties
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
+import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
 import android.view.HapticFeedbackConstants
 import android.view.MotionEvent
 import android.view.Surface
 import androidx.test.filters.SmallTest
 import com.android.app.activityTaskManager
+import com.android.keyguard.AuthInteractionProperties
+import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.biometrics.Utils.toBitmap
@@ -72,6 +75,7 @@
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.res.R
 import com.android.systemui.util.mockito.withArgCaptor
+import com.google.android.msdl.data.model.MSDLToken
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.first
@@ -124,6 +128,7 @@
     private val defaultLogoDescriptionFromActivityInfo = "Test Coke App"
     private val logoDescriptionFromApp = "Test Cake App"
     private val packageNameForLogoWithOverrides = "should.use.overridden.logo"
+    private val authInteractionProperties = AuthInteractionProperties()
 
     /** Prompt panel size padding */
     private val smallHorizontalGuidelinePadding =
@@ -707,31 +712,66 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun set_haptic_on_confirm_when_confirmation_required_otherwise_on_authenticated() =
         runGenericTest {
             val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
 
             kosmos.promptViewModel.showAuthenticated(testCase.authenticatedModality, 1_000L)
 
-            val confirmHaptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
-            assertThat(confirmHaptics?.hapticFeedbackConstant)
-                .isEqualTo(
-                    if (expectConfirmation) HapticFeedbackConstants.NO_HAPTICS
-                    else HapticFeedbackConstants.BIOMETRIC_CONFIRM
-                )
-            assertThat(confirmHaptics?.flag).isNull()
+            val hapticsPreConfirm by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+            if (expectConfirmation) {
+                assertThat(hapticsPreConfirm).isEqualTo(PromptViewModel.HapticsToPlay.None)
+            } else {
+                val confirmHaptics =
+                    hapticsPreConfirm as PromptViewModel.HapticsToPlay.HapticConstant
+                assertThat(confirmHaptics.constant)
+                    .isEqualTo(HapticFeedbackConstants.BIOMETRIC_CONFIRM)
+                assertThat(confirmHaptics.flag).isNull()
+            }
 
             if (expectConfirmation) {
                 kosmos.promptViewModel.confirmAuthenticated()
             }
 
-            val confirmedHaptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
-            assertThat(confirmedHaptics?.hapticFeedbackConstant)
+            val hapticsPostConfirm by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+            val confirmedHaptics =
+                hapticsPostConfirm as PromptViewModel.HapticsToPlay.HapticConstant
+            assertThat(confirmedHaptics.constant)
                 .isEqualTo(HapticFeedbackConstants.BIOMETRIC_CONFIRM)
-            assertThat(confirmedHaptics?.flag).isNull()
+            assertThat(confirmedHaptics.flag).isNull()
         }
 
     @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun set_msdl_haptic_on_confirm_when_confirmation_required_otherwise_on_authenticated() =
+        runGenericTest {
+            val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
+
+            kosmos.promptViewModel.showAuthenticated(testCase.authenticatedModality, 1_000L)
+
+            val hapticsPreConfirm by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+
+            if (expectConfirmation) {
+                assertThat(hapticsPreConfirm).isEqualTo(PromptViewModel.HapticsToPlay.None)
+            } else {
+                val confirmHaptics = hapticsPreConfirm as PromptViewModel.HapticsToPlay.MSDL
+                assertThat(confirmHaptics.token).isEqualTo(MSDLToken.UNLOCK)
+                assertThat(confirmHaptics.properties).isEqualTo(authInteractionProperties)
+            }
+
+            if (expectConfirmation) {
+                kosmos.promptViewModel.confirmAuthenticated()
+            }
+
+            val hapticsPostConfirm by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+            val confirmedHaptics = hapticsPostConfirm as PromptViewModel.HapticsToPlay.MSDL
+            assertThat(confirmedHaptics.token).isEqualTo(MSDLToken.UNLOCK)
+            assertThat(confirmedHaptics.properties).isEqualTo(authInteractionProperties)
+        }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun playSuccessHaptic_SetsConfirmConstant() = runGenericTest {
         val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
         kosmos.promptViewModel.showAuthenticated(testCase.authenticatedModality, 1_000L)
@@ -740,20 +780,48 @@
             kosmos.promptViewModel.confirmAuthenticated()
         }
 
-        val currentHaptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
-        assertThat(currentHaptics?.hapticFeedbackConstant)
-            .isEqualTo(HapticFeedbackConstants.BIOMETRIC_CONFIRM)
-        assertThat(currentHaptics?.flag).isNull()
+        val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+        val currentHaptics = haptics as PromptViewModel.HapticsToPlay.HapticConstant
+        assertThat(currentHaptics.constant).isEqualTo(HapticFeedbackConstants.BIOMETRIC_CONFIRM)
+        assertThat(currentHaptics.flag).isNull()
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun playSuccessHaptic_SetsUnlockMSDLFeedback() = runGenericTest {
+        val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
+        kosmos.promptViewModel.showAuthenticated(testCase.authenticatedModality, 1_000L)
+
+        if (expectConfirmation) {
+            kosmos.promptViewModel.confirmAuthenticated()
+        }
+
+        val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+        val currentHaptics = haptics as PromptViewModel.HapticsToPlay.MSDL
+        assertThat(currentHaptics.token).isEqualTo(MSDLToken.UNLOCK)
+        assertThat(currentHaptics.properties).isEqualTo(authInteractionProperties)
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun playErrorHaptic_SetsRejectConstant() = runGenericTest {
         kosmos.promptViewModel.showTemporaryError("test", "messageAfterError", false)
 
-        val currentHaptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
-        assertThat(currentHaptics?.hapticFeedbackConstant)
-            .isEqualTo(HapticFeedbackConstants.BIOMETRIC_REJECT)
-        assertThat(currentHaptics?.flag).isNull()
+        val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+        val currentHaptics = haptics as PromptViewModel.HapticsToPlay.HapticConstant
+        assertThat(currentHaptics.constant).isEqualTo(HapticFeedbackConstants.BIOMETRIC_REJECT)
+        assertThat(currentHaptics.flag).isNull()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun playErrorHaptic_SetsFailureMSDLFeedback() = runGenericTest {
+        kosmos.promptViewModel.showTemporaryError("test", "messageAfterError", false)
+
+        val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+        val currentHaptics = haptics as PromptViewModel.HapticsToPlay.MSDL
+        assertThat(currentHaptics.token).isEqualTo(MSDLToken.FAILURE)
+        assertThat(currentHaptics.properties).isEqualTo(authInteractionProperties)
     }
 
     // biometricprompt_sfps_fingerprint_authenticating reused across rotations
@@ -855,6 +923,7 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun set_haptic_on_errors() = runGenericTest {
         kosmos.promptViewModel.showTemporaryError(
             "so sad",
@@ -863,13 +932,30 @@
             hapticFeedback = true,
         )
 
-        val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
-        assertThat(haptics?.hapticFeedbackConstant)
-            .isEqualTo(HapticFeedbackConstants.BIOMETRIC_REJECT)
-        assertThat(haptics?.flag).isNull()
+        val hapticsToPlay by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+        val haptics = hapticsToPlay as PromptViewModel.HapticsToPlay.HapticConstant
+        assertThat(haptics.constant).isEqualTo(HapticFeedbackConstants.BIOMETRIC_REJECT)
+        assertThat(haptics.flag).isNull()
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun set_msdl_haptic_on_errors() = runGenericTest {
+        kosmos.promptViewModel.showTemporaryError(
+            "so sad",
+            messageAfterError = "",
+            authenticateAfterError = false,
+            hapticFeedback = true,
+        )
+
+        val hapticsToPlay by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+        val haptics = hapticsToPlay as PromptViewModel.HapticsToPlay.MSDL
+        assertThat(haptics.token).isEqualTo(MSDLToken.FAILURE)
+        assertThat(haptics.properties).isEqualTo(authInteractionProperties)
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun plays_haptic_on_errors_unless_skipped() = runGenericTest {
         kosmos.promptViewModel.showTemporaryError(
             "still sad",
@@ -878,11 +964,26 @@
             hapticFeedback = false,
         )
 
-        val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
-        assertThat(haptics?.hapticFeedbackConstant).isEqualTo(HapticFeedbackConstants.NO_HAPTICS)
+        val hapticsToPlay by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+        assertThat(hapticsToPlay).isEqualTo(PromptViewModel.HapticsToPlay.None)
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun plays_msdl_haptic_on_errors_unless_skipped() = runGenericTest {
+        kosmos.promptViewModel.showTemporaryError(
+            "still sad",
+            messageAfterError = "",
+            authenticateAfterError = false,
+            hapticFeedback = false,
+        )
+
+        val hapticsToPlay by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+        assertThat(hapticsToPlay).isEqualTo(PromptViewModel.HapticsToPlay.None)
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
     fun plays_haptic_on_error_after_auth_when_confirmation_needed() = runGenericTest {
         val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
         kosmos.promptViewModel.showAuthenticated(testCase.authenticatedModality, 0)
@@ -894,17 +995,39 @@
             hapticFeedback = true,
         )
 
-        val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+        val hapticsToPlay by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+        val haptics = hapticsToPlay as PromptViewModel.HapticsToPlay.HapticConstant
         if (expectConfirmation) {
-            assertThat(haptics?.hapticFeedbackConstant)
-                .isEqualTo(HapticFeedbackConstants.BIOMETRIC_REJECT)
-            assertThat(haptics?.flag).isNull()
+            assertThat(haptics.constant).isEqualTo(HapticFeedbackConstants.BIOMETRIC_REJECT)
+            assertThat(haptics.flag).isNull()
         } else {
-            assertThat(haptics?.hapticFeedbackConstant)
-                .isEqualTo(HapticFeedbackConstants.BIOMETRIC_CONFIRM)
+            assertThat(haptics.constant).isEqualTo(HapticFeedbackConstants.BIOMETRIC_CONFIRM)
         }
     }
 
+    @Test
+    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+    fun plays_msdl_haptic_on_error_after_auth_when_confirmation_needed() = runGenericTest {
+        val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
+        kosmos.promptViewModel.showAuthenticated(testCase.authenticatedModality, 0)
+
+        kosmos.promptViewModel.showTemporaryError(
+            "still sad",
+            messageAfterError = "",
+            authenticateAfterError = false,
+            hapticFeedback = true,
+        )
+
+        val hapticsToPlay by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+        val haptics = hapticsToPlay as PromptViewModel.HapticsToPlay.MSDL
+        if (expectConfirmation) {
+            assertThat(haptics.token).isEqualTo(MSDLToken.FAILURE)
+        } else {
+            assertThat(haptics.token).isEqualTo(MSDLToken.UNLOCK)
+        }
+        assertThat(haptics.properties).isEqualTo(authInteractionProperties)
+    }
+
     private suspend fun TestScope.showTemporaryErrors(
         restart: Boolean,
         helpAfterError: String = "",
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt
new file mode 100644
index 0000000..22946c8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2024 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.bouncer.ui.composable
+
+import android.app.AlertDialog
+import android.platform.test.annotations.MotionTest
+import android.testing.TestableLooper.RunWithLooper
+import androidx.activity.BackEventCompat
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.layout.Box
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.isFinite
+import androidx.compose.ui.geometry.isUnspecified
+import androidx.compose.ui.semantics.SemanticsNode
+import androidx.compose.ui.test.junit4.AndroidComposeTestRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.compose.animation.scene.Scale
+import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.SceneScope
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
+import com.android.compose.animation.scene.isElement
+import com.android.compose.animation.scene.testing.lastAlphaForTesting
+import com.android.compose.animation.scene.testing.lastScaleForTesting
+import com.android.compose.theme.PlatformTheme
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
+import com.android.systemui.bouncer.ui.BouncerDialogFactory
+import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel
+import com.android.systemui.bouncer.ui.viewmodel.BouncerUserActionsViewModel
+import com.android.systemui.bouncer.ui.viewmodel.bouncerSceneContentViewModel
+import com.android.systemui.classifier.domain.interactor.falsingInteractor
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.lifecycle.ExclusiveActivatable
+import com.android.systemui.lifecycle.rememberViewModel
+import com.android.systemui.motion.createSysUiComposeMotionTestRule
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.domain.startable.sceneContainerStartable
+import com.android.systemui.scene.shared.logger.sceneLogger
+import com.android.systemui.scene.shared.model.SceneContainerConfig
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.scene.shared.model.sceneDataSourceDelegator
+import com.android.systemui.scene.ui.composable.Scene
+import com.android.systemui.scene.ui.composable.SceneContainer
+import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
+import com.android.systemui.scene.ui.viewmodel.splitEdgeDetector
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.testKosmos
+import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
+import org.json.JSONObject
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.MockitoAnnotations
+import platform.test.motion.compose.ComposeFeatureCaptures.positionInRoot
+import platform.test.motion.compose.ComposeRecordingSpec
+import platform.test.motion.compose.MotionControl
+import platform.test.motion.compose.feature
+import platform.test.motion.compose.recordMotion
+import platform.test.motion.compose.runTest
+import platform.test.motion.golden.DataPoint
+import platform.test.motion.golden.DataPointType
+import platform.test.motion.golden.DataPointTypes
+import platform.test.motion.golden.FeatureCapture
+import platform.test.motion.golden.UnknownTypeException
+import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.Displays.Phone
+
+/** MotionTest for the Bouncer Predictive Back animation */
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+@RunWithLooper
+@EnableSceneContainer
+@MotionTest
+class BouncerPredictiveBackTest : SysuiTestCase() {
+
+    private val deviceSpec = DeviceEmulationSpec(Phone)
+    private val kosmos = testKosmos()
+
+    @get:Rule val motionTestRule = createSysUiComposeMotionTestRule(kosmos, deviceSpec)
+    private val androidComposeTestRule =
+        motionTestRule.toolkit.composeContentTestRule as AndroidComposeTestRule<*, *>
+
+    private val sceneInteractor by lazy { kosmos.sceneInteractor }
+    private val Kosmos.sceneKeys by Fixture { listOf(Scenes.Lockscreen, Scenes.Bouncer) }
+    private val Kosmos.initialSceneKey by Fixture { Scenes.Bouncer }
+    private val Kosmos.sceneContainerConfig by Fixture {
+        val navigationDistances =
+            mapOf(
+                Scenes.Lockscreen to 1,
+                Scenes.Bouncer to 0,
+            )
+        SceneContainerConfig(sceneKeys, initialSceneKey, emptyList(), navigationDistances)
+    }
+
+    private val transitionState by lazy {
+        MutableStateFlow<ObservableTransitionState>(
+            ObservableTransitionState.Idle(kosmos.sceneContainerConfig.initialSceneKey)
+        )
+    }
+    private val sceneContainerViewModel by lazy {
+        SceneContainerViewModel(
+                sceneInteractor = kosmos.sceneInteractor,
+                falsingInteractor = kosmos.falsingInteractor,
+                powerInteractor = kosmos.powerInteractor,
+                shadeInteractor = kosmos.shadeInteractor,
+                splitEdgeDetector = kosmos.splitEdgeDetector,
+                logger = kosmos.sceneLogger,
+                motionEventHandlerReceiver = {},
+            )
+            .apply { setTransitionState(transitionState) }
+    }
+
+    private val bouncerDialogFactory =
+        object : BouncerDialogFactory {
+            override fun invoke(): AlertDialog {
+                throw AssertionError()
+            }
+        }
+    private val bouncerSceneActionsViewModelFactory =
+        object : BouncerUserActionsViewModel.Factory {
+            override fun create() = BouncerUserActionsViewModel(kosmos.bouncerInteractor)
+        }
+    private lateinit var bouncerSceneContentViewModel: BouncerSceneContentViewModel
+    private val bouncerSceneContentViewModelFactory =
+        object : BouncerSceneContentViewModel.Factory {
+            override fun create() = bouncerSceneContentViewModel
+        }
+    private val bouncerScene =
+        BouncerScene(
+            bouncerSceneActionsViewModelFactory,
+            bouncerSceneContentViewModelFactory,
+            bouncerDialogFactory
+        )
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        bouncerSceneContentViewModel = kosmos.bouncerSceneContentViewModel
+
+        val startable = kosmos.sceneContainerStartable
+        startable.start()
+    }
+
+    @Test
+    fun bouncerPredictiveBackMotion() =
+        motionTestRule.runTest {
+            val motion =
+                recordMotion(
+                    content = { play ->
+                        PlatformTheme {
+                            BackGestureAnimation(play)
+                            SceneContainer(
+                                viewModel =
+                                    rememberViewModel("BouncerPredictiveBackTest") {
+                                        sceneContainerViewModel
+                                    },
+                                sceneByKey =
+                                    mapOf(
+                                        Scenes.Lockscreen to FakeLockscreen(),
+                                        Scenes.Bouncer to bouncerScene
+                                    ),
+                                initialSceneKey = Scenes.Bouncer,
+                                overlayByKey = emptyMap(),
+                                dataSourceDelegator = kosmos.sceneDataSourceDelegator
+                            )
+                        }
+                    },
+                    ComposeRecordingSpec(
+                        MotionControl(
+                            delayRecording = {
+                                awaitCondition {
+                                    sceneInteractor.transitionState.value.isTransitioning()
+                                }
+                            }
+                        ) {
+                            awaitCondition {
+                                sceneInteractor.transitionState.value.isIdle(Scenes.Lockscreen)
+                            }
+                        }
+                    ) {
+                        feature(isElement(Bouncer.Elements.Content), elementAlpha, "content_alpha")
+                        feature(isElement(Bouncer.Elements.Content), elementScale, "content_scale")
+                        feature(
+                            isElement(Bouncer.Elements.Content),
+                            positionInRoot,
+                            "content_offset"
+                        )
+                        feature(
+                            isElement(Bouncer.Elements.Background),
+                            elementAlpha,
+                            "background_alpha"
+                        )
+                    }
+                )
+
+            assertThat(motion).timeSeriesMatchesGolden()
+        }
+
+    @Composable
+    private fun BackGestureAnimation(play: Boolean) {
+        val backProgress = remember { Animatable(0f) }
+
+        LaunchedEffect(play) {
+            if (play) {
+                val dispatcher = androidComposeTestRule.activity.onBackPressedDispatcher
+                androidComposeTestRule.runOnUiThread {
+                    dispatcher.dispatchOnBackStarted(backEvent())
+                }
+                backProgress.animateTo(
+                    targetValue = 1f,
+                    animationSpec = tween(durationMillis = 500)
+                ) {
+                    androidComposeTestRule.runOnUiThread {
+                        dispatcher.dispatchOnBackProgressed(
+                            backEvent(progress = backProgress.value)
+                        )
+                        if (backProgress.value == 1f) {
+                            dispatcher.onBackPressed()
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private fun backEvent(progress: Float = 0f): BackEventCompat {
+        return BackEventCompat(
+            touchX = 0f,
+            touchY = 0f,
+            progress = progress,
+            swipeEdge = BackEventCompat.EDGE_LEFT,
+        )
+    }
+
+    private class FakeLockscreen : ExclusiveActivatable(), Scene {
+        override val key: SceneKey = Scenes.Lockscreen
+        override val userActions: Flow<Map<UserAction, UserActionResult>> = flowOf()
+
+        @Composable
+        override fun SceneScope.Content(modifier: Modifier) {
+            Box(modifier = modifier, contentAlignment = Alignment.Center) {
+                Text(text = "Fake Lockscreen")
+            }
+        }
+
+        override suspend fun onActivated() = awaitCancellation()
+    }
+
+    companion object {
+        private val elementAlpha =
+            FeatureCapture<SemanticsNode, Float>("alpha") {
+                DataPoint.of(it.lastAlphaForTesting, DataPointTypes.float)
+            }
+
+        private val elementScale =
+            FeatureCapture<SemanticsNode, Scale>("scale") {
+                DataPoint.of(it.lastScaleForTesting, scale)
+            }
+
+        private val scale: DataPointType<Scale> =
+            DataPointType(
+                "scale",
+                jsonToValue = {
+                    when (it) {
+                        "unspecified" -> Scale.Unspecified
+                        "default" -> Scale.Default
+                        "zero" -> Scale.Zero
+                        is JSONObject -> {
+                            val pivot = it.get("pivot")
+                            Scale(
+                                scaleX = it.getDouble("x").toFloat(),
+                                scaleY = it.getDouble("y").toFloat(),
+                                pivot =
+                                    when (pivot) {
+                                        "unspecified" -> Offset.Unspecified
+                                        "infinite" -> Offset.Infinite
+                                        is JSONObject ->
+                                            Offset(
+                                                pivot.getDouble("x").toFloat(),
+                                                pivot.getDouble("y").toFloat()
+                                            )
+                                        else -> throw UnknownTypeException()
+                                    }
+                            )
+                        }
+                        else -> throw UnknownTypeException()
+                    }
+                },
+                valueToJson = {
+                    when (it) {
+                        Scale.Unspecified -> "unspecified"
+                        Scale.Default -> "default"
+                        Scale.Zero -> "zero"
+                        else -> {
+                            JSONObject().apply {
+                                put("x", it.scaleX)
+                                put("y", it.scaleY)
+                                put(
+                                    "pivot",
+                                    when {
+                                        it.pivot.isUnspecified -> "unspecified"
+                                        !it.pivot.isFinite -> "infinite"
+                                        else ->
+                                            JSONObject().apply {
+                                                put("x", it.pivot.x)
+                                                put("y", it.pivot.y)
+                                            }
+                                    }
+                                )
+                            }
+                        }
+                    }
+                }
+            )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
index a1bea06..6377717 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
@@ -104,6 +104,7 @@
         when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
         when(mKeyguardStateController.isShowing()).thenReturn(true);
         when(mFalsingDataProvider.isUnfolded()).thenReturn(false);
+        when(mFalsingDataProvider.isTouchScreenSource()).thenReturn(true);
         mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
                 mMetricsLogger, mClassifiers, mSingleTapClassfier, mLongTapClassifier,
                 mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
index 7cc9185..bfb8a57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryBackgroundViewModel
 import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryForegroundViewModel
 import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
+import com.android.systemui.log.logcatLogBuffer
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.res.R
 import com.android.systemui.shade.NotificationPanelView
@@ -86,6 +87,7 @@
                 { mock(DeviceEntryBackgroundViewModel::class.java) },
                 { falsingManager },
                 { mock(VibratorHelper::class.java) },
+                logcatLogBuffer(),
             )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
index ad7a5b6..3c74374 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
@@ -967,7 +967,8 @@
         assertThat(data.resumption).isTrue()
         assertThat(data.song).isEqualTo(SESSION_TITLE)
         assertThat(data.app).isEqualTo(APP_NAME)
-        assertThat(data.actions).hasSize(1)
+        // resume button is a semantic action.
+        assertThat(data.actions).hasSize(0)
         assertThat(data.semanticActions!!.playOrPause).isNotNull()
         assertThat(data.lastActive).isAtLeast(currentTime)
         verify(logger).logResumeMediaAdded(anyInt(), eq(PACKAGE_NAME), eq(data.instanceId))
@@ -994,7 +995,8 @@
         assertThat(data.resumption).isTrue()
         assertThat(data.song).isEqualTo(SESSION_TITLE)
         assertThat(data.app).isEqualTo(APP_NAME)
-        assertThat(data.actions).hasSize(1)
+        // resume button is a semantic action.
+        assertThat(data.actions).hasSize(0)
         assertThat(data.semanticActions!!.playOrPause).isNotNull()
         assertThat(data.lastActive).isAtLeast(currentTime)
         assertThat(data.isExplicit).isTrue()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
index c0f503d..4cf7de3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
@@ -69,6 +69,8 @@
 import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
 import com.android.systemui.media.controls.domain.resume.MediaResumeListener
 import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser
+import com.android.systemui.media.controls.shared.mediaLogger
+import com.android.systemui.media.controls.shared.mockMediaLogger
 import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_SOURCE
 import com.android.systemui.media.controls.shared.model.EXTRA_VALUE_TRIGGER_PERIODIC
 import com.android.systemui.media.controls.shared.model.MediaData
@@ -140,7 +142,7 @@
 @RunWith(ParameterizedAndroidJunit4::class)
 @EnableSceneContainer
 class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
-    private val kosmos = testKosmos()
+    private val kosmos = testKosmos().apply { mediaLogger = mockMediaLogger }
     private val testDispatcher = kosmos.testDispatcher
     private val testScope = kosmos.testScope
     private val settings = kosmos.fakeSettings
@@ -257,6 +259,7 @@
                 keyguardUpdateMonitor = keyguardUpdateMonitor,
                 mediaDataRepository = kosmos.mediaDataRepository,
                 mediaDataLoader = { kosmos.mediaDataLoader },
+                mediaLogger = kosmos.mediaLogger,
             )
         mediaDataProcessor.start()
         testScope.runCurrent()
@@ -984,7 +987,8 @@
         assertThat(data.resumption).isTrue()
         assertThat(data.song).isEqualTo(SESSION_TITLE)
         assertThat(data.app).isEqualTo(APP_NAME)
-        assertThat(data.actions).hasSize(1)
+        // resume button is a semantic action.
+        assertThat(data.actions).hasSize(0)
         assertThat(data.semanticActions!!.playOrPause).isNotNull()
         assertThat(data.lastActive).isAtLeast(currentTime)
         verify(logger).logResumeMediaAdded(anyInt(), eq(PACKAGE_NAME), eq(data.instanceId))
@@ -1011,7 +1015,8 @@
         assertThat(data.resumption).isTrue()
         assertThat(data.song).isEqualTo(SESSION_TITLE)
         assertThat(data.app).isEqualTo(APP_NAME)
-        assertThat(data.actions).hasSize(1)
+        // resume button is a semantic action.
+        assertThat(data.actions).hasSize(0)
         assertThat(data.semanticActions!!.playOrPause).isNotNull()
         assertThat(data.lastActive).isAtLeast(currentTime)
         assertThat(data.isExplicit).isTrue()
@@ -2476,6 +2481,55 @@
         assertThat(mediaDataCaptor.value.artwork).isNull()
     }
 
+    @Test
+    @EnableFlags(Flags.FLAG_MEDIA_CONTROLS_POSTS_OPTIMIZATION)
+    fun postDuplicateNotification_doesNotCallListeners() {
+        whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
+        whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
+
+        mediaDataProcessor.addInternalListener(mediaDataFilter)
+        mediaDataFilter.mediaDataProcessor = mediaDataProcessor
+        addNotificationAndLoad()
+        reset(listener)
+        mediaDataProcessor.onNotificationAdded(KEY, mediaNotification)
+
+        testScope.assertRunAllReady(foreground = 0, background = 1)
+        verify(listener, never())
+            .onMediaDataLoaded(
+                eq(KEY),
+                eq(KEY),
+                capture(mediaDataCaptor),
+                eq(true),
+                eq(0),
+                eq(false)
+            )
+        verify(kosmos.mediaLogger).logDuplicateMediaNotification(eq(KEY))
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MEDIA_CONTROLS_POSTS_OPTIMIZATION)
+    fun postDuplicateNotification_callsListeners() {
+        whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
+        whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
+
+        mediaDataProcessor.addInternalListener(mediaDataFilter)
+        mediaDataFilter.mediaDataProcessor = mediaDataProcessor
+        addNotificationAndLoad()
+        reset(listener)
+        mediaDataProcessor.onNotificationAdded(KEY, mediaNotification)
+        testScope.assertRunAllReady(foreground = 1, background = 1)
+        verify(listener)
+            .onMediaDataLoaded(
+                eq(KEY),
+                eq(KEY),
+                capture(mediaDataCaptor),
+                eq(true),
+                eq(0),
+                eq(false)
+            )
+        verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY))
+    }
+
     private fun TestScope.assertRunAllReady(foreground: Int = 0, background: Int = 0) {
         runCurrent()
         if (Flags.mediaLoadMetadataViaMediaDataLoader()) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
index c1bba4d..680df15 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
@@ -72,7 +72,6 @@
     @Mock private lateinit var mediaController: MediaController
     @Mock private lateinit var logger: MediaTimeoutLogger
     @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
-    private lateinit var executor: FakeExecutor
     @Mock private lateinit var timeoutCallback: (String, Boolean) -> Unit
     @Mock private lateinit var stateCallback: (String, PlaybackState) -> Unit
     @Mock private lateinit var sessionCallback: (String) -> Unit
@@ -88,6 +87,9 @@
     private lateinit var resumeData: MediaData
     private lateinit var mediaTimeoutListener: MediaTimeoutListener
     private var clock = FakeSystemClock()
+    private lateinit var mainExecutor: FakeExecutor
+    private lateinit var bgExecutor: FakeExecutor
+    private lateinit var uiExecutor: FakeExecutor
     @Mock private lateinit var mediaFlags: MediaFlags
     @Mock private lateinit var smartspaceData: SmartspaceMediaData
 
@@ -95,11 +97,15 @@
     fun setup() {
         whenever(mediaControllerFactory.create(any())).thenReturn(mediaController)
         whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
-        executor = FakeExecutor(clock)
+        mainExecutor = FakeExecutor(clock)
+        bgExecutor = FakeExecutor(clock)
+        uiExecutor = FakeExecutor(clock)
         mediaTimeoutListener =
             MediaTimeoutListener(
                 mediaControllerFactory,
-                executor,
+                bgExecutor,
+                uiExecutor,
+                mainExecutor,
                 logger,
                 statusBarStateController,
                 clock,
@@ -143,30 +149,31 @@
         whenever(playingState.state).thenReturn(PlaybackState.STATE_PLAYING)
 
         whenever(mediaController.playbackState).thenReturn(playingState)
-        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+        loadMediaData(KEY, null, mediaData)
         verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
         verify(logger).logPlaybackState(eq(KEY), eq(playingState))
 
         // Ignores if same key
         clearInvocations(mediaController)
-        mediaTimeoutListener.onMediaDataLoaded(KEY, KEY, mediaData)
+        loadMediaData(KEY, KEY, mediaData)
         verify(mediaController, never()).registerCallback(anyObject())
     }
 
     @Test
     fun testOnMediaDataLoaded_registersTimeout_whenPaused() {
-        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+        loadMediaData(KEY, null, mediaData)
         verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
         verify(timeoutCallback, never()).invoke(anyString(), anyBoolean())
         verify(logger).logScheduleTimeout(eq(KEY), eq(false), eq(false))
-        assertThat(executor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
+        assertThat(mainExecutor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
     }
 
     @Test
     fun testOnMediaDataRemoved_unregistersPlaybackListener() {
-        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+        loadMediaData(KEY, null, mediaData)
         mediaTimeoutListener.onMediaDataRemoved(KEY, false)
+        assertThat(bgExecutor.runAllReady()).isEqualTo(1)
         verify(mediaController).unregisterCallback(anyObject())
 
         // Ignores duplicate requests
@@ -178,50 +185,50 @@
     @Test
     fun testOnMediaDataRemoved_clearsTimeout() {
         // GIVEN media that is paused
-        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
-        assertThat(executor.numPending()).isEqualTo(1)
+        loadMediaData(KEY, null, mediaData)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
         // WHEN the media is removed
         mediaTimeoutListener.onMediaDataRemoved(KEY, false)
         // THEN the timeout runnable is cancelled
-        assertThat(executor.numPending()).isEqualTo(0)
+        assertThat(mainExecutor.numPending()).isEqualTo(0)
     }
 
     @Test
     fun testOnMediaDataLoaded_migratesKeys() {
         val newKey = "NEWKEY"
         // From not playing
-        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+        loadMediaData(KEY, null, mediaData)
         clearInvocations(mediaController)
 
         // To playing
         val playingState = mock(android.media.session.PlaybackState::class.java)
         whenever(playingState.state).thenReturn(PlaybackState.STATE_PLAYING)
         whenever(mediaController.playbackState).thenReturn(playingState)
-        mediaTimeoutListener.onMediaDataLoaded(newKey, KEY, mediaData)
+        loadMediaData(newKey, KEY, mediaData)
         verify(mediaController).unregisterCallback(anyObject())
         verify(mediaController).registerCallback(anyObject())
         verify(logger).logMigrateListener(eq(KEY), eq(newKey), eq(true))
 
         // Enqueues callback
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
     }
 
     @Test
     fun testOnMediaDataLoaded_migratesKeys_noTimeoutExtension() {
         val newKey = "NEWKEY"
         // From not playing
-        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+        loadMediaData(KEY, null, mediaData)
         clearInvocations(mediaController)
 
         // Migrate, still not playing
         val playingState = mock(android.media.session.PlaybackState::class.java)
         whenever(playingState.state).thenReturn(PlaybackState.STATE_PAUSED)
         whenever(mediaController.playbackState).thenReturn(playingState)
-        mediaTimeoutListener.onMediaDataLoaded(newKey, KEY, mediaData)
+        loadMediaData(newKey, KEY, mediaData)
 
         // The number of queued timeout tasks remains the same. The timeout task isn't cancelled nor
         // is another scheduled
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
         verify(logger).logUpdateListener(eq(newKey), eq(false))
     }
 
@@ -233,8 +240,8 @@
         mediaCallbackCaptor.value.onPlaybackStateChanged(
             PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 0f).build()
         )
-        assertThat(executor.numPending()).isEqualTo(1)
-        assertThat(executor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
     }
 
     @Test
@@ -245,7 +252,7 @@
         mediaCallbackCaptor.value.onPlaybackStateChanged(
             PlaybackState.Builder().setState(PlaybackState.STATE_PLAYING, 0L, 0f).build()
         )
-        assertThat(executor.numPending()).isEqualTo(0)
+        assertThat(mainExecutor.numPending()).isEqualTo(0)
         verify(logger).logTimeoutCancelled(eq(KEY), any())
     }
 
@@ -257,7 +264,7 @@
         mediaCallbackCaptor.value.onPlaybackStateChanged(
             PlaybackState.Builder().setState(PlaybackState.STATE_STOPPED, 0L, 0f).build()
         )
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
     }
 
     @Test
@@ -265,7 +272,7 @@
         // Assuming we're have a pending timeout
         testOnPlaybackStateChanged_schedulesTimeout_whenPaused()
 
-        with(executor) {
+        with(mainExecutor) {
             advanceClockToNext()
             runAllReady()
         }
@@ -274,7 +281,7 @@
 
     @Test
     fun testIsTimedOut() {
-        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+        loadMediaData(KEY, null, mediaData)
         assertThat(mediaTimeoutListener.isTimedOut(KEY)).isFalse()
     }
 
@@ -282,16 +289,17 @@
     fun testOnSessionDestroyed_active_clearsTimeout() {
         // GIVEN media that is paused
         val mediaPaused = mediaData.copy(isPlaying = false)
-        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaPaused)
+        loadMediaData(KEY, null, mediaPaused)
         verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
 
         // WHEN the session is destroyed
         mediaCallbackCaptor.value.onSessionDestroyed()
 
         // THEN the controller is unregistered and timeout run
+        assertThat(bgExecutor.runAllReady()).isEqualTo(1)
         verify(mediaController).unregisterCallback(anyObject())
-        assertThat(executor.numPending()).isEqualTo(0)
+        assertThat(mainExecutor.numPending()).isEqualTo(0)
         verify(logger).logSessionDestroyed(eq(KEY))
         verify(sessionCallback).invoke(eq(KEY))
     }
@@ -306,11 +314,11 @@
         whenever(playingState.state).thenReturn(PlaybackState.STATE_PLAYING)
         whenever(mediaController.playbackState).thenReturn(playingState)
         val mediaPlaying = mediaData.copy(isPlaying = true)
-        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaPlaying)
+        loadMediaData(KEY, null, mediaPlaying)
 
         // THEN the timeout runnable will update the state
-        assertThat(executor.numPending()).isEqualTo(1)
-        with(executor) {
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
+        with(mainExecutor) {
             advanceClockToNext()
             runAllReady()
         }
@@ -322,31 +330,32 @@
     fun testOnSessionDestroyed_resume_continuesTimeout() {
         // GIVEN resume media with session info
         val resumeWithSession = resumeData.copy(token = session.sessionToken)
-        mediaTimeoutListener.onMediaDataLoaded(PACKAGE, null, resumeWithSession)
+        loadMediaData(PACKAGE, null, resumeWithSession)
         verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
 
         // WHEN the session is destroyed
         mediaCallbackCaptor.value.onSessionDestroyed()
 
         // THEN the controller is unregistered, but the timeout is still scheduled
+        assertThat(bgExecutor.runAllReady()).isEqualTo(1)
         verify(mediaController).unregisterCallback(anyObject())
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
         verify(sessionCallback, never()).invoke(eq(KEY))
     }
 
     @Test
     fun testOnMediaDataLoaded_activeToResume_registersTimeout() {
         // WHEN a regular media is loaded
-        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+        loadMediaData(KEY, null, mediaData)
 
         // AND it turns into a resume control
-        mediaTimeoutListener.onMediaDataLoaded(PACKAGE, KEY, resumeData)
+        loadMediaData(PACKAGE, KEY, resumeData)
 
         // THEN we register a timeout
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
         verify(timeoutCallback, never()).invoke(anyString(), anyBoolean())
-        assertThat(executor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
+        assertThat(mainExecutor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
     }
 
     @Test
@@ -355,42 +364,42 @@
         val pausedState =
             PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 0f).build()
         whenever(mediaController.playbackState).thenReturn(pausedState)
-        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
-        assertThat(executor.numPending()).isEqualTo(1)
+        loadMediaData(KEY, null, mediaData)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
 
         // AND it turns into a resume control
-        mediaTimeoutListener.onMediaDataLoaded(PACKAGE, KEY, resumeData)
+        loadMediaData(PACKAGE, KEY, resumeData)
 
         // THEN we update the timeout length
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
         verify(timeoutCallback, never()).invoke(anyString(), anyBoolean())
-        assertThat(executor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
+        assertThat(mainExecutor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
     }
 
     @Test
     fun testOnMediaDataLoaded_resumption_registersTimeout() {
         // WHEN a resume media is loaded
-        mediaTimeoutListener.onMediaDataLoaded(PACKAGE, null, resumeData)
+        loadMediaData(PACKAGE, null, resumeData)
 
         // THEN we register a timeout
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
         verify(timeoutCallback, never()).invoke(anyString(), anyBoolean())
-        assertThat(executor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
+        assertThat(mainExecutor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
     }
 
     @Test
     fun testOnMediaDataLoaded_resumeToActive_updatesTimeout() {
         // WHEN we have a resume control
-        mediaTimeoutListener.onMediaDataLoaded(PACKAGE, null, resumeData)
+        loadMediaData(PACKAGE, null, resumeData)
 
         // AND that media is resumed
         val playingState =
             PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 0f).build()
         whenever(mediaController.playbackState).thenReturn(playingState)
-        mediaTimeoutListener.onMediaDataLoaded(KEY, PACKAGE, mediaData)
+        loadMediaData(oldKey = PACKAGE, data = mediaData)
 
         // THEN the timeout length is changed to a regular media control
-        assertThat(executor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
+        assertThat(mainExecutor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
     }
 
     @Test
@@ -401,7 +410,7 @@
         mediaTimeoutListener.onMediaDataRemoved(PACKAGE, false)
 
         // THEN the timeout runnable is cancelled
-        assertThat(executor.numPending()).isEqualTo(0)
+        assertThat(mainExecutor.numPending()).isEqualTo(0)
     }
 
     @Test
@@ -427,6 +436,7 @@
         // When the playback state changes, and has different actions
         val playingState = PlaybackState.Builder().setActions(PlaybackState.ACTION_PLAY).build()
         mediaCallbackCaptor.value.onPlaybackStateChanged(playingState)
+        assertThat(uiExecutor.runAllReady()).isEqualTo(1)
 
         // Then the callback is invoked
         verify(stateCallback).invoke(eq(KEY), eq(playingState!!))
@@ -463,6 +473,7 @@
                 .addCustomAction(customTwo)
                 .build()
         mediaCallbackCaptor.value.onPlaybackStateChanged(pausedStateTwoActions)
+        assertThat(uiExecutor.runAllReady()).isEqualTo(1)
 
         // Then the callback is invoked
         verify(stateCallback).invoke(eq(KEY), eq(pausedStateTwoActions!!))
@@ -534,6 +545,7 @@
         val playingState =
             PlaybackState.Builder().setState(PlaybackState.STATE_PLAYING, 0L, 1f).build()
         mediaCallbackCaptor.value.onPlaybackStateChanged(playingState)
+        uiExecutor.runAllReady()
 
         // Then the callback is invoked
         verify(stateCallback).invoke(eq(KEY), eq(playingState!!))
@@ -567,7 +579,7 @@
         // And we doze past the scheduled timeout
         val time = clock.currentTimeMillis()
         clock.setElapsedRealtime(time + PAUSED_MEDIA_TIMEOUT)
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
 
         // Then when no longer dozing, the timeout runs immediately
         dozingCallbackCaptor.value.onDozingChanged(false)
@@ -576,7 +588,7 @@
 
         // and cancel any later scheduled timeout
         verify(logger).logTimeoutCancelled(eq(KEY), any())
-        assertThat(executor.numPending()).isEqualTo(0)
+        assertThat(mainExecutor.numPending()).isEqualTo(0)
     }
 
     @Test
@@ -592,12 +604,12 @@
 
         // And we doze, but not past the scheduled timeout
         clock.setElapsedRealtime(time + PAUSED_MEDIA_TIMEOUT / 2L)
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
 
         // Then when no longer dozing, the timeout remains scheduled
         dozingCallbackCaptor.value.onDozingChanged(false)
         verify(timeoutCallback, never()).invoke(eq(KEY), eq(true))
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
     }
 
     @Test
@@ -610,8 +622,8 @@
         whenever(smartspaceData.expiryTimeMs).thenReturn(expireTime)
 
         mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
-        assertThat(executor.numPending()).isEqualTo(1)
-        assertThat(executor.advanceClockToNext()).isEqualTo(duration)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.advanceClockToNext()).isEqualTo(duration)
     }
 
     @Test
@@ -619,7 +631,7 @@
         // Given a pending timeout
         testSmartspaceDataLoaded_schedulesTimeout()
 
-        executor.runAllReady()
+        mainExecutor.runAllReady()
         verify(timeoutCallback).invoke(eq(SMARTSPACE_KEY), eq(true))
     }
 
@@ -634,14 +646,14 @@
         whenever(smartspaceData.expiryTimeMs).thenReturn(expireTime)
 
         mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
 
         val expiryLonger = expireTime + duration
         whenever(smartspaceData.expiryTimeMs).thenReturn(expiryLonger)
         mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
-        assertThat(executor.numPending()).isEqualTo(1)
-        assertThat(executor.advanceClockToNext()).isEqualTo(duration * 2)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.advanceClockToNext()).isEqualTo(duration * 2)
     }
 
     @Test
@@ -649,10 +661,10 @@
         whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
 
         mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
 
         mediaTimeoutListener.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
-        assertThat(executor.numPending()).isEqualTo(0)
+        assertThat(mainExecutor.numPending()).isEqualTo(0)
     }
 
     @Test
@@ -667,12 +679,12 @@
         whenever(smartspaceData.expiryTimeMs).thenReturn(expireTime)
 
         mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
 
         // And we doze past the scheduled timeout
         val time = clock.currentTimeMillis()
         clock.setElapsedRealtime(time + duration * 2)
-        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(mainExecutor.numPending()).isEqualTo(1)
 
         // Then when no longer dozing, the timeout runs immediately
         dozingCallbackCaptor.value.onDozingChanged(false)
@@ -680,12 +692,18 @@
         verify(logger).logTimeout(eq(SMARTSPACE_KEY))
 
         // and cancel any later scheduled timeout
-        assertThat(executor.numPending()).isEqualTo(0)
+        assertThat(mainExecutor.numPending()).isEqualTo(0)
     }
 
     private fun loadMediaDataWithPlaybackState(state: PlaybackState) {
         whenever(mediaController.playbackState).thenReturn(state)
-        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+        loadMediaData(data = mediaData)
         verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
     }
+
+    private fun loadMediaData(key: String = KEY, oldKey: String? = null, data: MediaData) {
+        mediaTimeoutListener.onMediaDataLoaded(key, oldKey, data)
+        bgExecutor.runAllReady()
+        uiExecutor.runAllReady()
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt
index 1260a65..68a5d93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt
@@ -79,6 +79,7 @@
 import com.android.systemui.media.controls.shared.model.MediaButton
 import com.android.systemui.media.controls.shared.model.MediaData
 import com.android.systemui.media.controls.shared.model.MediaDeviceData
+import com.android.systemui.media.controls.shared.model.MediaNotificationAction
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
 import com.android.systemui.media.controls.ui.binder.SeekBarObserver
 import com.android.systemui.media.controls.ui.view.GutsViewHolder
@@ -236,6 +237,19 @@
     @Mock private lateinit var recProgressBar3: SeekBar
     @Mock private lateinit var globalSettings: GlobalSettings
 
+    private val intent =
+        Intent().apply {
+            putExtras(Bundle().also { it.putString(KEY_SMARTSPACE_APP_NAME, REC_APP_NAME) })
+            setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+        }
+    private val pendingIntent =
+        PendingIntent.getActivity(
+            mContext,
+            0,
+            intent.setPackage(mContext.packageName),
+            PendingIntent.FLAG_MUTABLE
+        )
+
     @JvmField @Rule val mockito = MockitoJUnit.rule()
 
     @Before
@@ -989,14 +1003,13 @@
     @Test
     fun bindNotificationActions() {
         val icon = context.getDrawable(android.R.drawable.ic_media_play)
-        val bg = context.getDrawable(R.drawable.qs_media_round_button_background)
         val actions =
             listOf(
-                MediaAction(icon, Runnable {}, "previous", bg),
-                MediaAction(icon, Runnable {}, "play", bg),
-                MediaAction(icon, null, "next", bg),
-                MediaAction(icon, null, "custom 0", bg),
-                MediaAction(icon, Runnable {}, "custom 1", bg)
+                MediaNotificationAction(true, actionIntent = pendingIntent, icon, "previous"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, icon, "play"),
+                MediaNotificationAction(true, actionIntent = null, icon, "next"),
+                MediaNotificationAction(true, actionIntent = null, icon, "custom 0"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, icon, "custom 1")
             )
         val state =
             mediaData.copy(
@@ -1684,11 +1697,11 @@
     fun actionCustom2Click_isLogged() {
         val actions =
             listOf(
-                MediaAction(null, Runnable {}, "action 0", null),
-                MediaAction(null, Runnable {}, "action 1", null),
-                MediaAction(null, Runnable {}, "action 2", null),
-                MediaAction(null, Runnable {}, "action 3", null),
-                MediaAction(null, Runnable {}, "action 4", null)
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 0"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 1"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 2"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 3"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 4")
             )
         val data = mediaData.copy(actions = actions)
 
@@ -1703,11 +1716,11 @@
     fun actionCustom3Click_isLogged() {
         val actions =
             listOf(
-                MediaAction(null, Runnable {}, "action 0", null),
-                MediaAction(null, Runnable {}, "action 1", null),
-                MediaAction(null, Runnable {}, "action 2", null),
-                MediaAction(null, Runnable {}, "action 3", null),
-                MediaAction(null, Runnable {}, "action 4", null)
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 0"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 1"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 2"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 3"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 4")
             )
         val data = mediaData.copy(actions = actions)
 
@@ -1722,11 +1735,11 @@
     fun actionCustom4Click_isLogged() {
         val actions =
             listOf(
-                MediaAction(null, Runnable {}, "action 0", null),
-                MediaAction(null, Runnable {}, "action 1", null),
-                MediaAction(null, Runnable {}, "action 2", null),
-                MediaAction(null, Runnable {}, "action 3", null),
-                MediaAction(null, Runnable {}, "action 4", null)
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 0"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 1"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 2"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 3"),
+                MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 4")
             )
         val data = mediaData.copy(actions = actions)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
index c1cf91d..bc0ec2d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
@@ -22,6 +22,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.systemui.Flags.FLAG_QS_CUSTOM_TILE_CLICK_GUARANTEED_BUG_FIX;
+import static com.android.systemui.Flags.FLAG_QS_QUICK_REBIND_ACTIVE_TILES;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -75,6 +76,8 @@
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
+import com.google.common.truth.Truth;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -95,7 +98,8 @@
 
     @Parameters(name = "{0}")
     public static List<FlagsParameterization> getParams() {
-        return allCombinationsOf(FLAG_QS_CUSTOM_TILE_CLICK_GUARANTEED_BUG_FIX);
+        return allCombinationsOf(FLAG_QS_CUSTOM_TILE_CLICK_GUARANTEED_BUG_FIX,
+                FLAG_QS_QUICK_REBIND_ACTIVE_TILES);
     }
 
     private final PackageManagerAdapter mMockPackageManagerAdapter =
@@ -154,7 +158,8 @@
                 mUser,
                 mActivityManager,
                 mDeviceIdleController,
-                mExecutor);
+                mExecutor,
+                mClock);
     }
 
     @After
@@ -169,12 +174,12 @@
         mStateManager.handleDestroy();
     }
 
-    private void setPackageEnabled(boolean enabled) throws Exception {
+    private void setPackageEnabledAndActive(boolean enabled, boolean active) throws Exception {
         ServiceInfo defaultServiceInfo = null;
         if (enabled) {
             defaultServiceInfo = new ServiceInfo();
             defaultServiceInfo.metaData = new Bundle();
-            defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_ACTIVE_TILE, true);
+            defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_ACTIVE_TILE, active);
             defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_TOGGLEABLE_TILE, true);
         }
         when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt(), anyInt()))
@@ -186,6 +191,10 @@
                 .thenReturn(defaultPackageInfo);
     }
 
+    private void setPackageEnabled(boolean enabled) throws Exception {
+        setPackageEnabledAndActive(enabled, true);
+    }
+
     private void setPackageInstalledForUser(
             boolean installed,
             boolean active,
@@ -396,13 +405,40 @@
     }
 
     @Test
-    public void testKillProcess() throws Exception {
+    public void testKillProcessWhenTileServiceIsNotActive() throws Exception {
+        setPackageEnabledAndActive(true, false);
         mStateManager.onStartListening();
         mStateManager.executeSetBindService(true);
         mExecutor.runAllReady();
+        verifyBind(1);
+        verify(mMockTileService, times(1)).onStartListening();
+
         mStateManager.onBindingDied(mTileServiceComponentName);
         mExecutor.runAllReady();
-        mClock.advanceTime(5000);
+        mClock.advanceTime(1000);
+        mExecutor.runAllReady();
+
+        // still 4 seconds left because non active tile service rebind time is 5 seconds
+        Truth.assertThat(mContext.isBound(mTileServiceComponentName)).isFalse();
+
+        mClock.advanceTime(4000); // 5 seconds delay for nonActive service rebinding
+        mExecutor.runAllReady();
+        verifyBind(2);
+        verify(mMockTileService, times(2)).onStartListening();
+    }
+
+    @EnableFlags(FLAG_QS_QUICK_REBIND_ACTIVE_TILES)
+    @Test
+    public void testKillProcessWhenTileServiceIsActive_withRebindFlagOn() throws Exception {
+        mStateManager.onStartListening();
+        mStateManager.executeSetBindService(true);
+        mExecutor.runAllReady();
+        verifyBind(1);
+        verify(mMockTileService, times(1)).onStartListening();
+
+        mStateManager.onBindingDied(mTileServiceComponentName);
+        mExecutor.runAllReady();
+        mClock.advanceTime(1000);
         mExecutor.runAllReady();
 
         // Two calls: one for the first bind, one for the restart.
@@ -410,6 +446,86 @@
         verify(mMockTileService, times(2)).onStartListening();
     }
 
+    @DisableFlags(FLAG_QS_QUICK_REBIND_ACTIVE_TILES)
+    @Test
+    public void testKillProcessWhenTileServiceIsActive_withRebindFlagOff() throws Exception {
+        mStateManager.onStartListening();
+        mStateManager.executeSetBindService(true);
+        mExecutor.runAllReady();
+        verifyBind(1);
+        verify(mMockTileService, times(1)).onStartListening();
+
+        mStateManager.onBindingDied(mTileServiceComponentName);
+        mExecutor.runAllReady();
+        mClock.advanceTime(1000);
+        mExecutor.runAllReady();
+        verifyBind(0); // the rebind happens after 4 more seconds
+
+        mClock.advanceTime(4000);
+        mExecutor.runAllReady();
+        verifyBind(1);
+    }
+
+    @EnableFlags(FLAG_QS_QUICK_REBIND_ACTIVE_TILES)
+    @Test
+    public void testKillProcessWhenTileServiceIsActiveTwice_withRebindFlagOn_delaysSecondRebind()
+            throws Exception {
+        mStateManager.onStartListening();
+        mStateManager.executeSetBindService(true);
+        mExecutor.runAllReady();
+        verifyBind(1);
+        verify(mMockTileService, times(1)).onStartListening();
+
+        mStateManager.onBindingDied(mTileServiceComponentName);
+        mExecutor.runAllReady();
+        mClock.advanceTime(1000);
+        mExecutor.runAllReady();
+
+        // Two calls: one for the first bind, one for the restart.
+        verifyBind(2);
+        verify(mMockTileService, times(2)).onStartListening();
+
+        mStateManager.onBindingDied(mTileServiceComponentName);
+        mExecutor.runAllReady();
+        mClock.advanceTime(1000);
+        mExecutor.runAllReady();
+        // because active tile will take 5 seconds to bind the second time, not 1
+        verifyBind(0);
+
+        mClock.advanceTime(4000);
+        mExecutor.runAllReady();
+        verifyBind(1);
+    }
+
+    @DisableFlags(FLAG_QS_QUICK_REBIND_ACTIVE_TILES)
+    @Test
+    public void testKillProcessWhenTileServiceIsActiveTwice_withRebindFlagOff_rebindsFromFirstKill()
+            throws Exception {
+        mStateManager.onStartListening();
+        mStateManager.executeSetBindService(true);
+        mExecutor.runAllReady();
+        verifyBind(1);
+        verify(mMockTileService, times(1)).onStartListening();
+
+        mStateManager.onBindingDied(mTileServiceComponentName); // rebind scheduled for 5 seconds
+        mExecutor.runAllReady();
+        mClock.advanceTime(1000);
+        mExecutor.runAllReady();
+
+        verifyBind(0); // it would bind in 4 more seconds
+
+        mStateManager.onBindingDied(mTileServiceComponentName); // this does not affect the rebind
+        mExecutor.runAllReady();
+        mClock.advanceTime(1000);
+        mExecutor.runAllReady();
+
+        verifyBind(0); // only 2 seconds passed from first kill
+
+        mClock.advanceTime(3000);
+        mExecutor.runAllReady();
+        verifyBind(1); // the rebind scheduled 5 seconds from the first kill should now happen
+    }
+
     @Test
     public void testKillProcessLowMemory() throws Exception {
         doAnswer(invocation -> {
@@ -510,7 +626,8 @@
                 mUser,
                 mActivityManager,
                 mDeviceIdleController,
-                mExecutor);
+                mExecutor,
+                mClock);
 
         manager.executeSetBindService(true);
         mExecutor.runAllReady();
@@ -533,7 +650,8 @@
                 mUser,
                 mActivityManager,
                 mDeviceIdleController,
-                mExecutor);
+                mExecutor,
+                mClock);
 
         manager.executeSetBindService(true);
         mExecutor.runAllReady();
@@ -556,7 +674,8 @@
                 mUser,
                 mActivityManager,
                 mDeviceIdleController,
-                mExecutor);
+                mExecutor,
+                mClock);
 
         manager.executeSetBindService(true);
         mExecutor.runAllReady();
@@ -581,7 +700,8 @@
                 mUser,
                 mActivityManager,
                 mDeviceIdleController,
-                mExecutor);
+                mExecutor,
+                mClock);
 
         manager.executeSetBindService(true);
         mExecutor.runAllReady();
@@ -607,7 +727,8 @@
                 mUser,
                 mActivityManager,
                 mDeviceIdleController,
-                mExecutor);
+                mExecutor,
+                mClock);
 
         assertThat(manager.isActiveTile()).isTrue();
     }
@@ -626,7 +747,8 @@
                 mUser,
                 mActivityManager,
                 mDeviceIdleController,
-                mExecutor);
+                mExecutor,
+                mClock);
 
         assertThat(manager.isActiveTile()).isTrue();
     }
@@ -644,7 +766,8 @@
                 mUser,
                 mActivityManager,
                 mDeviceIdleController,
-                mExecutor);
+                mExecutor,
+                mClock);
 
         assertThat(manager.isToggleableTile()).isTrue();
     }
@@ -663,7 +786,8 @@
                 mUser,
                 mActivityManager,
                 mDeviceIdleController,
-                mExecutor);
+                mExecutor,
+                mClock);
 
         assertThat(manager.isToggleableTile()).isTrue();
     }
@@ -682,7 +806,8 @@
                 mUser,
                 mActivityManager,
                 mDeviceIdleController,
-                mExecutor);
+                mExecutor,
+                mClock);
 
         assertThat(manager.isToggleableTile()).isFalse();
         assertThat(manager.isActiveTile()).isFalse();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
index 76c8cf0..7d41a20 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.qs.tiles;
 
+import static com.android.systemui.accessibility.hearingaid.HearingDevicesUiEventLogger.LAUNCH_SOURCE_QS_TILE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -151,7 +153,7 @@
         mTile.handleClick(expandable);
         mTestableLooper.processAllMessages();
 
-        verify(mHearingDevicesDialogManager).showDialog(expandable);
+        verify(mHearingDevicesDialogManager).showDialog(expandable, LAUNCH_SOURCE_QS_TILE);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt
index 828c7b2..e6ec07e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt
@@ -259,7 +259,6 @@
         const val WIFI_SSID = "test ssid"
         val ACTIVE_WIFI =
             WifiNetworkModel.Active(
-                networkId = 1,
                 isValidated = true,
                 level = 4,
                 ssid = WIFI_SSID,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt
index 73548ba..ca518f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.recordissue.RecordIssueDialogDelegate
 import com.android.systemui.recordissue.TraceurMessageSender
 import com.android.systemui.res.R
+import com.android.systemui.screenrecord.RecordingController
 import com.android.systemui.settings.UserContextProvider
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil
 import com.android.systemui.statusbar.phone.SystemUIDialog
@@ -65,6 +66,7 @@
     @Mock private lateinit var qsEventLogger: QsEventLogger
     @Mock private lateinit var metricsLogger: MetricsLogger
     @Mock private lateinit var statusBarStateController: StatusBarStateController
+    @Mock private lateinit var recordingController: RecordingController
     @Mock private lateinit var activityStarter: ActivityStarter
     @Mock private lateinit var qsLogger: QSLogger
     @Mock private lateinit var keyguardDismissUtil: KeyguardDismissUtil
@@ -109,6 +111,7 @@
                 Executors.newSingleThreadExecutor(),
                 issueRecordingState,
                 delegateFactory,
+                recordingController,
             )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingServiceCommandHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingServiceCommandHandlerTest.kt
new file mode 100644
index 0000000..57cfe1b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingServiceCommandHandlerTest.kt
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 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.recordissue
+
+import android.app.IActivityManager
+import android.app.NotificationManager
+import android.net.Uri
+import android.os.UserHandle
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.dialogTransitionAnimator
+import com.android.systemui.concurrency.fakeExecutor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testCase
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
+import com.android.systemui.settings.UserContextProvider
+import com.android.systemui.settings.userFileManager
+import com.android.systemui.settings.userTracker
+import com.android.traceur.TraceConfig
+import com.google.common.truth.Truth
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.kotlin.any
+import org.mockito.kotlin.isNull
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class IssueRecordingServiceCommandHandlerTest : SysuiTestCase() {
+
+    private val kosmos = Kosmos().also { it.testCase = this }
+    private val bgExecutor = kosmos.fakeExecutor
+    private val userContextProvider: UserContextProvider = kosmos.userTracker
+    private val dialogTransitionAnimator: DialogTransitionAnimator = kosmos.dialogTransitionAnimator
+    private lateinit var traceurMessageSender: TraceurMessageSender
+    private val issueRecordingState =
+        IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+    private val iActivityManager = mock<IActivityManager>()
+    private val notificationManager = mock<NotificationManager>()
+    private val panelInteractor = mock<PanelInteractor>()
+
+    private lateinit var underTest: IssueRecordingServiceCommandHandler
+
+    @Before
+    fun setup() {
+        traceurMessageSender = mock<TraceurMessageSender>()
+        underTest =
+            IssueRecordingServiceCommandHandler(
+                bgExecutor,
+                dialogTransitionAnimator,
+                panelInteractor,
+                traceurMessageSender,
+                issueRecordingState,
+                iActivityManager,
+                notificationManager,
+                userContextProvider
+            )
+    }
+
+    @Test
+    fun startsTracing_afterReceivingActionStartCommand() {
+        underTest.handleStartCommand()
+        bgExecutor.runAllReady()
+
+        Truth.assertThat(issueRecordingState.isRecording).isTrue()
+        verify(traceurMessageSender).startTracing(any<TraceConfig>())
+    }
+
+    @Test
+    fun stopsTracing_afterReceivingStopTracingCommand() {
+        underTest.handleStopCommand(mContext.contentResolver)
+        bgExecutor.runAllReady()
+
+        Truth.assertThat(issueRecordingState.isRecording).isFalse()
+        verify(traceurMessageSender).stopTracing()
+    }
+
+    @Test
+    fun cancelsNotification_afterReceivingShareCommand() {
+        underTest.handleShareCommand(0, null, mContext)
+        bgExecutor.runAllReady()
+
+        verify(notificationManager).cancelAsUser(isNull(), anyInt(), any<UserHandle>())
+    }
+
+    @Test
+    fun requestBugreport_afterReceivingShareCommand_withTakeBugreportTrue() {
+        issueRecordingState.takeBugreport = true
+        val uri = mock<Uri>()
+
+        underTest.handleShareCommand(0, uri, mContext)
+        bgExecutor.runAllReady()
+
+        verify(iActivityManager).requestBugReportWithExtraAttachment(uri)
+    }
+
+    @Test
+    fun sharesTracesDirectly_afterReceivingShareCommand_withTakeBugreportFalse() {
+        issueRecordingState.takeBugreport = false
+        val uri = mock<Uri>()
+
+        underTest.handleShareCommand(0, uri, mContext)
+        bgExecutor.runAllReady()
+
+        verify(traceurMessageSender).shareTraces(mContext, uri)
+    }
+
+    @Test
+    fun closesShade_afterReceivingShareCommand() {
+        val uri = mock<Uri>()
+
+        underTest.handleShareCommand(0, uri, mContext)
+        bgExecutor.runAllReady()
+
+        verify(panelInteractor).collapsePanels()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/SaveImageInBackgroundTaskTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/SaveImageInBackgroundTaskTest.kt
deleted file mode 100644
index 5e07aef..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/SaveImageInBackgroundTaskTest.kt
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (C) 2023 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.Notification
-import android.app.PendingIntent
-import android.content.ComponentName
-import android.content.Intent
-import android.graphics.Bitmap
-import android.graphics.drawable.Icon
-import android.net.Uri
-import android.os.UserHandle
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
-import java.util.concurrent.CompletableFuture
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertNull
-import org.junit.Before
-import org.junit.Test
-
-@SmallTest
-class SaveImageInBackgroundTaskTest : SysuiTestCase() {
-    private val imageExporter = mock<ImageExporter>()
-    private val smartActions = mock<ScreenshotSmartActions>()
-    private val smartActionsProvider = mock<ScreenshotNotificationSmartActionsProvider>()
-    private val saveImageData = SaveImageInBackgroundTask.SaveImageInBackgroundData()
-    private val testScreenshotId: String = "testScreenshotId"
-    private val testBitmap = mock<Bitmap>()
-    private val testUser = UserHandle.getUserHandleForUid(0)
-    private val testIcon = mock<Icon>()
-    private val testImageTime = 1234.toLong()
-    private val flags = FakeFeatureFlags()
-
-    private val smartActionsUriFuture = mock<CompletableFuture<List<Notification.Action>>>()
-    private val smartActionsFuture = mock<CompletableFuture<List<Notification.Action>>>()
-
-    private val testUri: Uri = Uri.parse("testUri")
-    private val intent =
-        Intent(Intent.ACTION_SEND)
-            .setComponent(
-                ComponentName.unflattenFromString(
-                    "com.google.android.test/com.google.android.test.TestActivity"
-                )
-            )
-    private val immutablePendingIntent =
-        PendingIntent.getBroadcast(
-            mContext,
-            0,
-            intent,
-            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
-        )
-    private val mutablePendingIntent =
-        PendingIntent.getBroadcast(
-            mContext,
-            0,
-            intent,
-            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_MUTABLE
-        )
-
-    private val saveImageTask =
-        SaveImageInBackgroundTask(
-            mContext,
-            flags,
-            imageExporter,
-            smartActions,
-            saveImageData,
-            smartActionsProvider,
-        )
-
-    @Before
-    fun setup() {
-        whenever(
-                smartActions.getSmartActionsFuture(
-                    eq(testScreenshotId),
-                    any(Uri::class.java),
-                    eq(testBitmap),
-                    eq(smartActionsProvider),
-                    any(ScreenshotSmartActionType::class.java),
-                    any(Boolean::class.java),
-                    eq(testUser)
-                )
-            )
-            .thenReturn(smartActionsUriFuture)
-        whenever(
-                smartActions.getSmartActionsFuture(
-                    eq(testScreenshotId),
-                    eq(null),
-                    eq(testBitmap),
-                    eq(smartActionsProvider),
-                    any(ScreenshotSmartActionType::class.java),
-                    any(Boolean::class.java),
-                    eq(testUser)
-                )
-            )
-            .thenReturn(smartActionsFuture)
-    }
-
-    @Test
-    fun testQueryQuickShare_noAction() {
-        whenever(
-                smartActions.getSmartActions(
-                    eq(testScreenshotId),
-                    eq(smartActionsFuture),
-                    any(Int::class.java),
-                    eq(smartActionsProvider),
-                    eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
-                )
-            )
-            .thenReturn(ArrayList<Notification.Action>())
-
-        val quickShareAction =
-            saveImageTask.queryQuickShareAction(testScreenshotId, testBitmap, testUser, testUri)
-
-        assertNull(quickShareAction)
-    }
-
-    @Test
-    fun testQueryQuickShare_withActions() {
-        val actions = ArrayList<Notification.Action>()
-        actions.add(constructAction("Action One", mutablePendingIntent))
-        actions.add(constructAction("Action Two", mutablePendingIntent))
-        whenever(
-                smartActions.getSmartActions(
-                    eq(testScreenshotId),
-                    eq(smartActionsUriFuture),
-                    any(Int::class.java),
-                    eq(smartActionsProvider),
-                    eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
-                )
-            )
-            .thenReturn(actions)
-
-        val quickShareAction =
-            saveImageTask.queryQuickShareAction(testScreenshotId, testBitmap, testUser, testUri)!!
-
-        assertEquals("Action One", quickShareAction.title)
-        assertEquals(mutablePendingIntent, quickShareAction.actionIntent)
-    }
-
-    @Test
-    fun testCreateQuickShareAction_originalWasNull_returnsNull() {
-        val quickShareAction =
-            saveImageTask.createQuickShareAction(
-                null,
-                testScreenshotId,
-                testUri,
-                testImageTime,
-                testBitmap,
-                testUser
-            )
-
-        assertNull(quickShareAction)
-    }
-
-    @Test
-    fun testCreateQuickShareAction_immutableIntentDifferentAction_returnsNull() {
-        val actions = ArrayList<Notification.Action>()
-        actions.add(constructAction("New Test Action", immutablePendingIntent))
-        whenever(
-                smartActions.getSmartActions(
-                    eq(testScreenshotId),
-                    eq(smartActionsUriFuture),
-                    any(Int::class.java),
-                    eq(smartActionsProvider),
-                    eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
-                )
-            )
-            .thenReturn(actions)
-        val origAction = constructAction("Old Test Action", immutablePendingIntent)
-
-        val quickShareAction =
-            saveImageTask.createQuickShareAction(
-                origAction,
-                testScreenshotId,
-                testUri,
-                testImageTime,
-                testBitmap,
-                testUser,
-            )
-
-        assertNull(quickShareAction)
-    }
-
-    @Test
-    fun testCreateQuickShareAction_mutableIntent_returnsSafeIntent() {
-        val actions = ArrayList<Notification.Action>()
-        val action = constructAction("Action One", mutablePendingIntent)
-        actions.add(action)
-        whenever(
-                smartActions.getSmartActions(
-                    eq(testScreenshotId),
-                    eq(smartActionsUriFuture),
-                    any(Int::class.java),
-                    eq(smartActionsProvider),
-                    eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
-                )
-            )
-            .thenReturn(actions)
-
-        val quickShareAction =
-            saveImageTask.createQuickShareAction(
-                constructAction("Test Action", mutablePendingIntent),
-                testScreenshotId,
-                testUri,
-                testImageTime,
-                testBitmap,
-                testUser
-            )
-        val quickSharePendingIntent =
-            quickShareAction.actionIntent.intent.extras!!.getParcelable(
-                SmartActionsReceiver.EXTRA_ACTION_INTENT,
-                PendingIntent::class.java
-            )
-
-        assertEquals("Test Action", quickShareAction.title)
-        assertEquals(mutablePendingIntent, quickSharePendingIntent)
-    }
-
-    @Test
-    fun testCreateQuickShareAction_immutableIntent_returnsSafeIntent() {
-        val actions = ArrayList<Notification.Action>()
-        val action = constructAction("Test Action", immutablePendingIntent)
-        actions.add(action)
-        whenever(
-                smartActions.getSmartActions(
-                    eq(testScreenshotId),
-                    eq(smartActionsUriFuture),
-                    any(Int::class.java),
-                    eq(smartActionsProvider),
-                    eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
-                )
-            )
-            .thenReturn(actions)
-
-        val quickShareAction =
-            saveImageTask.createQuickShareAction(
-                constructAction("Test Action", immutablePendingIntent),
-                testScreenshotId,
-                testUri,
-                testImageTime,
-                testBitmap,
-                testUser,
-            )!!
-
-        assertEquals("Test Action", quickShareAction.title)
-        assertEquals(
-            immutablePendingIntent,
-            quickShareAction.actionIntent.intent.extras!!.getParcelable(
-                SmartActionsReceiver.EXTRA_ACTION_INTENT,
-                PendingIntent::class.java
-            )
-        )
-    }
-
-    private fun constructAction(title: String, intent: PendingIntent): Notification.Action {
-        return Notification.Action.Builder(testIcon, title, intent).build()
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
index 263b001..78764c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
@@ -79,21 +79,6 @@
 
     @Test
     fun callsCallbackAndUpdatesProfilesWhenAnIntentReceived() = runTest {
-        tracker =
-            UserTrackerImpl(
-                context,
-                { fakeFeatures },
-                userManager,
-                iActivityManager,
-                dumpManager,
-                this,
-                testDispatcher,
-                handler
-            )
-        tracker.initialize(0)
-        tracker.addCallback(callback, executor)
-        val profileID = tracker.userId + 10
-
         `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation ->
             val id = invocation.getArgument<Int>(0)
             val info = UserInfo(id, "", UserInfo.FLAG_FULL)
@@ -109,6 +94,21 @@
             listOf(info, infoProfile)
         }
 
+        tracker =
+            UserTrackerImpl(
+                context,
+                { fakeFeatures },
+                userManager,
+                iActivityManager,
+                dumpManager,
+                this,
+                testDispatcher,
+                handler
+            )
+        tracker.initialize(0)
+        tracker.addCallback(callback, executor)
+        val profileID = tracker.userId + 10
+
         tracker.onReceive(context, Intent(intentAction))
 
         verify(callback, times(0)).onUserChanged(anyInt(), any())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 3e3c046..1d74331 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -779,6 +779,26 @@
 
     @Test
     @DisableSceneContainer
+    public void testResetDoesNotHideBouncerWhenNotShowing() {
+        reset(mDismissCallbackRegistry);
+        reset(mPrimaryBouncerInteractor);
+
+        // GIVEN the keyguard is showing
+        reset(mAlternateBouncerInteractor);
+        when(mKeyguardStateController.isShowing()).thenReturn(true);
+        when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(false);
+
+        // WHEN SBKV is reset with hideBouncerWhenShowing=true
+        mStatusBarKeyguardViewManager.reset(true);
+
+        // THEN no calls to hide should be made
+        verify(mAlternateBouncerInteractor, never()).hide();
+        verify(mDismissCallbackRegistry, never()).notifyDismissCancelled();
+        verify(mPrimaryBouncerInteractor, never()).setDismissAction(eq(null), eq(null));
+    }
+
+    @Test
+    @DisableSceneContainer
     public void testResetHideBouncerWhenShowing_alternateBouncerHides() {
         reset(mDismissCallbackRegistry);
         reset(mPrimaryBouncerInteractor);
@@ -786,6 +806,7 @@
         // GIVEN the keyguard is showing
         reset(mAlternateBouncerInteractor);
         when(mKeyguardStateController.isShowing()).thenReturn(true);
+        when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true);
 
         // WHEN SBKV is reset with hideBouncerWhenShowing=true
         mStatusBarKeyguardViewManager.reset(true);
@@ -1091,9 +1112,11 @@
     public void testShowBouncerOrKeyguard_showsKeyguardIfShowBouncerReturnsFalse() {
         when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
                 KeyguardSecurityModel.SecurityMode.SimPin);
+        // Returning false means unable to show the bouncer
         when(mPrimaryBouncerInteractor.show(true)).thenReturn(false);
         when(mKeyguardTransitionInteractor.getTransitionState().getValue().getTo())
                 .thenReturn(KeyguardState.LOCKSCREEN);
+        mStatusBarKeyguardViewManager.onStartedWakingUp();
 
         reset(mCentralSurfaces);
         // Advance past reattempts
@@ -1106,6 +1129,23 @@
 
     @Test
     @DisableSceneContainer
+    @EnableFlags(Flags.FLAG_SIM_PIN_RACE_CONDITION_ON_RESTART)
+    public void testShowBouncerOrKeyguard_showsKeyguardIfSleeping() {
+        when(mKeyguardTransitionInteractor.getTransitionState().getValue().getTo())
+                .thenReturn(KeyguardState.LOCKSCREEN);
+        mStatusBarKeyguardViewManager.onStartedGoingToSleep();
+
+        reset(mCentralSurfaces);
+        reset(mPrimaryBouncerInteractor);
+        mStatusBarKeyguardViewManager.showBouncerOrKeyguard(
+                /* hideBouncerWhenShowing= */true, false);
+        verify(mCentralSurfaces).showKeyguard();
+        verify(mPrimaryBouncerInteractor).hide();
+    }
+
+
+    @Test
+    @DisableSceneContainer
     public void testShowBouncerOrKeyguard_needsFullScreen_bouncerAlreadyShowing() {
         boolean isFalsingReset = false;
         when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
index 237aabc..b6e23c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
@@ -104,7 +104,7 @@
                 underTest.dataConnectionState.onEach { latestConnState = it }.launchIn(this)
             val netJob = underTest.resolvedNetworkType.onEach { latestNetType = it }.launchIn(this)
 
-            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = NET_ID, level = 1))
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(level = 1))
 
             assertThat(latestConnState).isEqualTo(DataConnectionState.Disconnected)
             assertThat(latestNetType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
@@ -124,7 +124,6 @@
 
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId = NET_ID,
                     subscriptionId = SUB_ID,
                     level = 3,
                 )
@@ -145,7 +144,6 @@
             wifiRepository.setIsWifiDefault(true)
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId = NET_ID,
                     subscriptionId = SUB_ID,
                     level = 3,
                 )
@@ -183,7 +181,6 @@
 
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId = NET_ID,
                     subscriptionId = SUB_ID + 10,
                     level = 3,
                 )
@@ -205,7 +202,6 @@
 
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId = NET_ID,
                     subscriptionId = SUB_ID,
                     level = 3,
                 )
@@ -226,7 +222,6 @@
 
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId = NET_ID,
                     subscriptionId = SUB_ID,
                     level = 3,
                 )
@@ -246,7 +241,6 @@
 
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId = NET_ID,
                     subscriptionId = SUB_ID,
                     level = 1,
                     numberOfLevels = 6,
@@ -310,7 +304,6 @@
             whenever(telephonyManager.simOperatorName).thenReturn("New SIM name")
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId = NET_ID,
                     subscriptionId = SUB_ID,
                     level = 3,
                 )
@@ -331,6 +324,5 @@
 
     private companion object {
         const val SUB_ID = 123
-        const val NET_ID = 456
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
index c029850..a03980a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
@@ -487,10 +487,8 @@
             val job = underTest.primaryLevel.launchIn(this)
 
             // WHEN we set up carrier merged info
-            val networkId = 2
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId,
                     SUB_ID,
                     level = 3,
                 )
@@ -502,7 +500,6 @@
             // WHEN we update the info
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId,
                     SUB_ID,
                     level = 1,
                 )
@@ -540,10 +537,8 @@
             assertThat(dumpBuffer()).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}1")
 
             // WHEN isCarrierMerged is set to true
-            val networkId = 2
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId,
                     SUB_ID,
                     level = 3,
                 )
@@ -556,7 +551,6 @@
             // WHEN the carrier merge network is updated
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId,
                     SUB_ID,
                     level = 4,
                 )
@@ -607,10 +601,8 @@
                 .onSignalStrengthsChanged(signalStrength)
 
             // THEN updates to the carrier merged level aren't logged
-            val networkId = 2
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId,
                     SUB_ID,
                     level = 4,
                 )
@@ -619,7 +611,6 @@
 
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
-                    networkId,
                     SUB_ID,
                     level = 3,
                 )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
index fe408e3..7634490 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
@@ -817,7 +817,7 @@
             captor.lastValue.onReceive(context, intent)
 
             // spnIntent() sets all values to true and test strings
-            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
 
             job.cancel()
         }
@@ -852,7 +852,7 @@
             verify(context).registerReceiver(captor.capture(), any())
             captor.lastValue.onReceive(context, intent)
 
-            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
 
             // WHEN an intent with a different subId is sent
             val wrongSubIntent = spnIntent(subId = 101)
@@ -860,7 +860,7 @@
             captor.lastValue.onReceive(context, wrongSubIntent)
 
             // THEN the previous intent's name is still used
-            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
 
             job.cancel()
         }
@@ -902,7 +902,7 @@
             verify(context).registerReceiver(captor.capture(), any())
             captor.lastValue.onReceive(context, intent)
 
-            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
 
             val intentWithoutInfo =
                 spnIntent(
@@ -961,7 +961,7 @@
 
             // The value is still there despite no active subscribers
             assertThat(underTest.networkName.value)
-                .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+                .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
         }
 
     @Test
@@ -986,7 +986,7 @@
 
     @Test
     @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
-    fun networkName_allFieldsSet_doesNotUseDataSpn() =
+    fun networkName_allFieldsSet_prioritizesDataSpnOverSpn() =
         testScope.runTest {
             val latest by collectLastValue(underTest.networkName)
             val captor = argumentCaptor<BroadcastReceiver>()
@@ -1002,6 +1002,27 @@
                     plmn = PLMN,
                 )
             captor.lastValue.onReceive(context, intent)
+            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
+        }
+
+    @Test
+    @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
+    fun networkName_spnAndPlmn_fallbackToSpnWhenNullDataSpn() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.networkName)
+            val captor = argumentCaptor<BroadcastReceiver>()
+            verify(context).registerReceiver(captor.capture(), any())
+
+            val intent =
+                spnIntent(
+                    subId = SUB_1_ID,
+                    showSpn = true,
+                    spn = SPN,
+                    dataSpn = null,
+                    showPlmn = true,
+                    plmn = PLMN,
+                )
+            captor.lastValue.onReceive(context, intent)
             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
         }
 
@@ -1043,7 +1064,27 @@
                     plmn = PLMN,
                 )
             captor.lastValue.onReceive(context, intent)
-            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN"))
+            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
+        }
+
+    @Test
+    @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
+    fun networkName_showPlmn_plmnNotNull_showSpn_spnNotNull_dataSpnNull() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.networkName)
+            val captor = argumentCaptor<BroadcastReceiver>()
+            verify(context).registerReceiver(captor.capture(), any())
+            val intent =
+                spnIntent(
+                    subId = SUB_1_ID,
+                    showSpn = true,
+                    spn = SPN,
+                    dataSpn = null,
+                    showPlmn = true,
+                    plmn = PLMN,
+                )
+            captor.lastValue.onReceive(context, intent)
+            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
         }
 
     @Test
@@ -1102,10 +1143,50 @@
                     plmn = null,
                 )
             captor.lastValue.onReceive(context, intent)
+            assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$DATA_SPN"))
+        }
+
+    @Test
+    @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
+    fun networkName_showPlmn_plmnNull_showSpn_dataSpnNull() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.networkName)
+            val captor = argumentCaptor<BroadcastReceiver>()
+            verify(context).registerReceiver(captor.capture(), any())
+            val intent =
+                spnIntent(
+                    subId = SUB_1_ID,
+                    showSpn = true,
+                    spn = SPN,
+                    dataSpn = null,
+                    showPlmn = true,
+                    plmn = null,
+                )
+            captor.lastValue.onReceive(context, intent)
             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$SPN"))
         }
 
     @Test
+    @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
+    fun networkName_showPlmn_plmnNull_showSpn_bothSpnNull() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.networkName)
+            val captor = argumentCaptor<BroadcastReceiver>()
+            verify(context).registerReceiver(captor.capture(), any())
+            val intent =
+                spnIntent(
+                    subId = SUB_1_ID,
+                    showSpn = true,
+                    spn = null,
+                    dataSpn = null,
+                    showPlmn = true,
+                    plmn = null,
+                )
+            captor.lastValue.onReceive(context, intent)
+            assertThat(latest).isEqualTo(DEFAULT_NAME_MODEL)
+        }
+
+    @Test
     @DisableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
     fun networkName_showPlmn_plmnNull_showSpn_flagOff() =
         testScope.runTest {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
index dbb77d5..a1cb29b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
@@ -574,7 +574,7 @@
             val latest by collectLastValue(underTest.isWifiActive)
 
             // WHEN wifi is active
-            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1))
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(level = 1))
 
             // THEN the interactor returns true due to the wifi network being active
             assertThat(latest).isTrue()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
index bf31f1e..c1abf98 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
@@ -375,7 +375,7 @@
             repo.isSatelliteProvisioned.value = true
 
             // GIVEN wifi network is active
-            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1))
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(level = 1))
 
             // THEN icon is null because the device is connected to wifi
             assertThat(latest).isNull()
@@ -573,7 +573,7 @@
             repo.isSatelliteProvisioned.value = true
 
             // GIVEN wifi network is active
-            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1))
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(level = 1))
 
             // THEN carrier text is null because the device is connected to wifi
             assertThat(latest).isNull()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
index 50f262c..fed3317 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
@@ -155,7 +155,6 @@
 
             val networkModel =
                 WifiNetworkModel.Active(
-                    networkId = 1,
                     level = 4,
                     ssid = "test ssid",
                 )
@@ -185,7 +184,6 @@
 
             val networkModel =
                 WifiNetworkModel.Active(
-                    networkId = 1,
                     level = 4,
                     ssid = "test ssid",
                     hotspotDeviceType = WifiNetworkModel.HotspotDeviceType.NONE,
@@ -393,7 +391,6 @@
     private fun setWifiNetworkWithHotspot(hotspot: WifiNetworkModel.HotspotDeviceType) {
         val networkModel =
             WifiNetworkModel.Active(
-                networkId = 1,
                 level = 4,
                 ssid = "test ssid",
                 hotspotDeviceType = hotspot,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
index b9c57d8..46f34e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
@@ -283,27 +283,6 @@
         }
 
     @Test
-    fun accessPointInfo_alwaysFalse() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(3)
-                    whenever(this.title).thenReturn(TITLE)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            val latestActive = latest as WifiNetworkModel.Active
-            assertThat(latestActive.isPasspointAccessPoint).isFalse()
-            assertThat(latestActive.isOnlineSignUpForPasspointAccessPoint).isFalse()
-            assertThat(latestActive.passpointProviderFriendlyName).isNull()
-        }
-
-    @Test
     fun wifiNetwork_unreachableLevel_inactiveNetwork() =
         testScope.runTest {
             val latest by collectLastValue(underTest.wifiNetwork)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt
index eb6b068..92860ef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt
@@ -34,31 +34,30 @@
     @Test
     fun active_levelsInValidRange_noException() {
         (MIN_VALID_LEVEL..MAX_VALID_LEVEL).forEach { level ->
-            WifiNetworkModel.Active(NETWORK_ID, level = level)
+            WifiNetworkModel.Active(level = level)
             // No assert, just need no crash
         }
     }
 
     @Test(expected = IllegalArgumentException::class)
     fun active_levelNegative_exceptionThrown() {
-        WifiNetworkModel.Active(NETWORK_ID, level = MIN_VALID_LEVEL - 1)
+        WifiNetworkModel.Active(level = MIN_VALID_LEVEL - 1)
     }
 
     @Test(expected = IllegalArgumentException::class)
     fun active_levelTooHigh_exceptionThrown() {
-        WifiNetworkModel.Active(NETWORK_ID, level = MAX_VALID_LEVEL + 1)
+        WifiNetworkModel.Active(level = MAX_VALID_LEVEL + 1)
     }
 
     @Test(expected = IllegalArgumentException::class)
     fun carrierMerged_invalidSubId_exceptionThrown() {
-        WifiNetworkModel.CarrierMerged(NETWORK_ID, INVALID_SUBSCRIPTION_ID, 1)
+        WifiNetworkModel.CarrierMerged(INVALID_SUBSCRIPTION_ID, 1)
     }
 
     @Test
     fun active_hasValidSsid_nullSsid_false() {
         val network =
             WifiNetworkModel.Active(
-                NETWORK_ID,
                 level = MAX_VALID_LEVEL,
                 ssid = null,
             )
@@ -70,7 +69,6 @@
     fun active_hasValidSsid_unknownSsid_false() {
         val network =
             WifiNetworkModel.Active(
-                NETWORK_ID,
                 level = MAX_VALID_LEVEL,
                 ssid = UNKNOWN_SSID,
             )
@@ -82,7 +80,6 @@
     fun active_hasValidSsid_validSsid_true() {
         val network =
             WifiNetworkModel.Active(
-                NETWORK_ID,
                 level = MAX_VALID_LEVEL,
                 ssid = "FakeSsid",
             )
@@ -97,7 +94,6 @@
         val logger = TestLogger()
         val prevVal =
             WifiNetworkModel.CarrierMerged(
-                networkId = 5,
                 subscriptionId = 3,
                 level = 1,
             )
@@ -105,7 +101,6 @@
         WifiNetworkModel.Inactive.logDiffs(prevVal, logger)
 
         assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_INACTIVE))
-        assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, NETWORK_ID_DEFAULT.toString()))
         assertThat(logger.changes).contains(Pair(COL_VALIDATED, "false"))
         assertThat(logger.changes).contains(Pair(COL_LEVEL, LEVEL_DEFAULT.toString()))
         assertThat(logger.changes).contains(Pair(COL_SSID, "null"))
@@ -116,7 +111,6 @@
         val logger = TestLogger()
         val carrierMerged =
             WifiNetworkModel.CarrierMerged(
-                networkId = 6,
                 subscriptionId = 3,
                 level = 2,
             )
@@ -124,7 +118,6 @@
         carrierMerged.logDiffs(prevVal = WifiNetworkModel.Inactive, logger)
 
         assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_CARRIER_MERGED))
-        assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, "6"))
         assertThat(logger.changes).contains(Pair(COL_SUB_ID, "3"))
         assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true"))
         assertThat(logger.changes).contains(Pair(COL_LEVEL, "2"))
@@ -136,7 +129,6 @@
         val logger = TestLogger()
         val activeNetwork =
             WifiNetworkModel.Active(
-                networkId = 5,
                 isValidated = true,
                 level = 3,
                 ssid = "Test SSID",
@@ -146,27 +138,21 @@
         activeNetwork.logDiffs(prevVal = WifiNetworkModel.Inactive, logger)
 
         assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_ACTIVE))
-        assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, "5"))
         assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true"))
         assertThat(logger.changes).contains(Pair(COL_LEVEL, "3"))
         assertThat(logger.changes).contains(Pair(COL_SSID, "Test SSID"))
         assertThat(logger.changes).contains(Pair(COL_HOTSPOT, "LAPTOP"))
     }
+
     @Test
     fun logDiffs_activeToInactive_resetsAllActiveFields() {
         val logger = TestLogger()
         val activeNetwork =
-            WifiNetworkModel.Active(
-                networkId = 5,
-                isValidated = true,
-                level = 3,
-                ssid = "Test SSID"
-            )
+            WifiNetworkModel.Active(isValidated = true, level = 3, ssid = "Test SSID")
 
         WifiNetworkModel.Inactive.logDiffs(prevVal = activeNetwork, logger)
 
         assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_INACTIVE))
-        assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, NETWORK_ID_DEFAULT.toString()))
         assertThat(logger.changes).contains(Pair(COL_VALIDATED, "false"))
         assertThat(logger.changes).contains(Pair(COL_LEVEL, LEVEL_DEFAULT.toString()))
         assertThat(logger.changes).contains(Pair(COL_SSID, "null"))
@@ -178,7 +164,6 @@
         val logger = TestLogger()
         val activeNetwork =
             WifiNetworkModel.Active(
-                networkId = 5,
                 isValidated = true,
                 level = 3,
                 ssid = "Test SSID",
@@ -186,7 +171,6 @@
             )
         val prevVal =
             WifiNetworkModel.CarrierMerged(
-                networkId = 5,
                 subscriptionId = 3,
                 level = 1,
             )
@@ -194,25 +178,19 @@
         activeNetwork.logDiffs(prevVal, logger)
 
         assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_ACTIVE))
-        assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, "5"))
         assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true"))
         assertThat(logger.changes).contains(Pair(COL_LEVEL, "3"))
         assertThat(logger.changes).contains(Pair(COL_SSID, "Test SSID"))
         assertThat(logger.changes).contains(Pair(COL_HOTSPOT, "AUTO"))
     }
+
     @Test
     fun logDiffs_activeToCarrierMerged_logsAllFields() {
         val logger = TestLogger()
         val activeNetwork =
-            WifiNetworkModel.Active(
-                networkId = 5,
-                isValidated = true,
-                level = 3,
-                ssid = "Test SSID"
-            )
+            WifiNetworkModel.Active(isValidated = true, level = 3, ssid = "Test SSID")
         val carrierMerged =
             WifiNetworkModel.CarrierMerged(
-                networkId = 6,
                 subscriptionId = 3,
                 level = 2,
             )
@@ -220,7 +198,6 @@
         carrierMerged.logDiffs(prevVal = activeNetwork, logger)
 
         assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_CARRIER_MERGED))
-        assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, "6"))
         assertThat(logger.changes).contains(Pair(COL_SUB_ID, "3"))
         assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true"))
         assertThat(logger.changes).contains(Pair(COL_LEVEL, "2"))
@@ -231,19 +208,9 @@
     fun logDiffs_activeChangesLevel_onlyLevelLogged() {
         val logger = TestLogger()
         val prevActiveNetwork =
-            WifiNetworkModel.Active(
-                networkId = 5,
-                isValidated = true,
-                level = 3,
-                ssid = "Test SSID"
-            )
+            WifiNetworkModel.Active(isValidated = true, level = 3, ssid = "Test SSID")
         val newActiveNetwork =
-            WifiNetworkModel.Active(
-                networkId = 5,
-                isValidated = true,
-                level = 2,
-                ssid = "Test SSID"
-            )
+            WifiNetworkModel.Active(isValidated = true, level = 2, ssid = "Test SSID")
 
         newActiveNetwork.logDiffs(prevActiveNetwork, logger)
 
@@ -265,8 +232,4 @@
             changes.add(Pair(columnName, value.toString()))
         }
     }
-
-    companion object {
-        private const val NETWORK_ID = 2
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
index 161c4f5..ff398f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
@@ -195,9 +195,7 @@
     @Test
     fun isIconVisible_notEnabled_outputsFalse() {
         wifiRepository.setIsWifiEnabled(false)
-        wifiRepository.setWifiNetwork(
-            WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 2)
-        )
+        wifiRepository.setWifiNetwork(WifiNetworkModel.Active(isValidated = true, level = 2))
 
         val view = ModernStatusBarWifiView.constructAndBind(context, SLOT_NAME, viewModel)
 
@@ -212,9 +210,7 @@
     @Test
     fun isIconVisible_enabled_outputsTrue() {
         wifiRepository.setIsWifiEnabled(true)
-        wifiRepository.setWifiNetwork(
-            WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 2)
-        )
+        wifiRepository.setWifiNetwork(WifiNetworkModel.Active(isValidated = true, level = 2))
 
         val view = ModernStatusBarWifiView.constructAndBind(context, SLOT_NAME, viewModel)
 
@@ -272,4 +268,3 @@
 }
 
 private const val SLOT_NAME = "TestSlotName"
-private const val NETWORK_ID = 200
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
index d2a4bf3..82acb40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
@@ -206,8 +206,7 @@
                 // Enabled = false => no networks shown
                 TestCase(
                     enabled = false,
-                    network =
-                        WifiNetworkModel.CarrierMerged(NETWORK_ID, subscriptionId = 1, level = 1),
+                    network = WifiNetworkModel.CarrierMerged(subscriptionId = 1, level = 1),
                     expected = null,
                 ),
                 TestCase(
@@ -217,20 +216,19 @@
                 ),
                 TestCase(
                     enabled = false,
-                    network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 1),
+                    network = WifiNetworkModel.Active(isValidated = false, level = 1),
                     expected = null,
                 ),
                 TestCase(
                     enabled = false,
-                    network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 3),
+                    network = WifiNetworkModel.Active(isValidated = true, level = 3),
                     expected = null,
                 ),
 
                 // forceHidden = true => no networks shown
                 TestCase(
                     forceHidden = true,
-                    network =
-                        WifiNetworkModel.CarrierMerged(NETWORK_ID, subscriptionId = 1, level = 1),
+                    network = WifiNetworkModel.CarrierMerged(subscriptionId = 1, level = 1),
                     expected = null,
                 ),
                 TestCase(
@@ -240,12 +238,12 @@
                 ),
                 TestCase(
                     enabled = false,
-                    network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 2),
+                    network = WifiNetworkModel.Active(isValidated = false, level = 2),
                     expected = null,
                 ),
                 TestCase(
                     forceHidden = true,
-                    network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 1),
+                    network = WifiNetworkModel.Active(isValidated = true, level = 1),
                     expected = null,
                 ),
 
@@ -265,7 +263,7 @@
                 ),
                 TestCase(
                     alwaysShowIconWhenEnabled = true,
-                    network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 4),
+                    network = WifiNetworkModel.Active(isValidated = false, level = 4),
                     expected =
                         Expected(
                             iconResource = WIFI_NO_INTERNET_ICONS[4],
@@ -278,7 +276,7 @@
                 ),
                 TestCase(
                     alwaysShowIconWhenEnabled = true,
-                    network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 2),
+                    network = WifiNetworkModel.Active(isValidated = true, level = 2),
                     expected =
                         Expected(
                             iconResource = WIFI_FULL_ICONS[2],
@@ -305,7 +303,7 @@
                 ),
                 TestCase(
                     hasDataCapabilities = false,
-                    network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 2),
+                    network = WifiNetworkModel.Active(isValidated = false, level = 2),
                     expected =
                         Expected(
                             iconResource = WIFI_NO_INTERNET_ICONS[2],
@@ -318,7 +316,7 @@
                 ),
                 TestCase(
                     hasDataCapabilities = false,
-                    network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 0),
+                    network = WifiNetworkModel.Active(isValidated = true, level = 0),
                     expected =
                         Expected(
                             iconResource = WIFI_FULL_ICONS[0],
@@ -345,7 +343,7 @@
                 ),
                 TestCase(
                     isDefault = true,
-                    network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 3),
+                    network = WifiNetworkModel.Active(isValidated = false, level = 3),
                     expected =
                         Expected(
                             iconResource = WIFI_NO_INTERNET_ICONS[3],
@@ -358,7 +356,7 @@
                 ),
                 TestCase(
                     isDefault = true,
-                    network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 1),
+                    network = WifiNetworkModel.Active(isValidated = true, level = 1),
                     expected =
                         Expected(
                             iconResource = WIFI_FULL_ICONS[1],
@@ -374,8 +372,7 @@
                     enabled = true,
                     isDefault = true,
                     forceHidden = false,
-                    network =
-                        WifiNetworkModel.CarrierMerged(NETWORK_ID, subscriptionId = 1, level = 1),
+                    network = WifiNetworkModel.CarrierMerged(subscriptionId = 1, level = 1),
                     expected = null,
                 ),
 
@@ -392,7 +389,7 @@
                 ),
                 TestCase(
                     isDefault = false,
-                    network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 3),
+                    network = WifiNetworkModel.Active(isValidated = false, level = 3),
                     expected = null,
                 ),
 
@@ -400,7 +397,7 @@
                 // because wifi isn't the default connection (b/272509965).
                 TestCase(
                     isDefault = false,
-                    network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 4),
+                    network = WifiNetworkModel.Active(isValidated = true, level = 4),
                     expected = null,
                 ),
             )
@@ -408,4 +405,3 @@
 }
 
 private val IMMEDIATE = Dispatchers.Main.immediate
-private const val NETWORK_ID = 789
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java
index 0358474..3041240 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.hardware.display.DisplayManager;
 import android.os.Handler;
 import android.os.UserHandle;
@@ -40,6 +41,7 @@
     @GuardedBy("mRegisteredReceivers")
     private final Set<BroadcastReceiver> mRegisteredReceivers = new ArraySet<>();
     private final Map<UserHandle, Context> mContextForUser = new HashMap<>();
+    private final Map<String, Context> mContextForPackage = new HashMap<>();
 
     public SysuiTestableContext(Context base) {
         super(base);
@@ -175,4 +177,22 @@
         }
         return super.createContextAsUser(user, flags);
     }
+
+    /**
+     * Sets a Context object that will be returned as the result of {@link #createPackageContext}
+     * for a specific {@code packageName}.
+     */
+    public void prepareCreatePackageContext(String packageName, Context context) {
+        mContextForPackage.put(packageName, context);
+    }
+
+    @Override
+    public Context createPackageContext(String packageName, int flags)
+            throws PackageManager.NameNotFoundException {
+        Context packageContext = mContextForPackage.get(packageName);
+        if (packageContext != null) {
+            return packageContext;
+        }
+        return super.createPackageContext(packageName, flags);
+    }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeCaptioningRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeCaptioningRepository.kt
index 2a0e764..a639463 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeCaptioningRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeCaptioningRepository.kt
@@ -16,25 +16,31 @@
 
 package com.android.systemui.accessibility.data.repository
 
+import com.android.systemui.accessibility.data.model.CaptioningModel
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
 
 class FakeCaptioningRepository : CaptioningRepository {
 
-    private val mutableIsSystemAudioCaptioningEnabled = MutableStateFlow(false)
-    override val isSystemAudioCaptioningEnabled: StateFlow<Boolean>
-        get() = mutableIsSystemAudioCaptioningEnabled.asStateFlow()
-
-    private val mutableIsSystemAudioCaptioningUiEnabled = MutableStateFlow(false)
-    override val isSystemAudioCaptioningUiEnabled: StateFlow<Boolean>
-        get() = mutableIsSystemAudioCaptioningUiEnabled.asStateFlow()
+    private val mutableCaptioningModel = MutableStateFlow<CaptioningModel?>(null)
+    override val captioningModel: StateFlow<CaptioningModel?> = mutableCaptioningModel.asStateFlow()
 
     override suspend fun setIsSystemAudioCaptioningEnabled(isEnabled: Boolean) {
-        mutableIsSystemAudioCaptioningEnabled.value = isEnabled
+        mutableCaptioningModel.value =
+            CaptioningModel(
+                isSystemAudioCaptioningEnabled = isEnabled,
+                isSystemAudioCaptioningUiEnabled =
+                    mutableCaptioningModel.value?.isSystemAudioCaptioningUiEnabled == true,
+            )
     }
 
-    fun setIsSystemAudioCaptioningUiEnabled(isSystemAudioCaptioningUiEnabled: Boolean) {
-        mutableIsSystemAudioCaptioningUiEnabled.value = isSystemAudioCaptioningUiEnabled
+    fun setIsSystemAudioCaptioningUiEnabled(isEnabled: Boolean) {
+        mutableCaptioningModel.value =
+            CaptioningModel(
+                isSystemAudioCaptioningEnabled =
+                    mutableCaptioningModel.value?.isSystemAudioCaptioningEnabled == true,
+                isSystemAudioCaptioningUiEnabled = isEnabled,
+            )
     }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt
index 5ced578..3087d01 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.mobileConnectionsRepository
 import com.android.systemui.telephony.domain.interactor.telephonyInteractor
 import com.android.systemui.user.domain.interactor.selectedUserInteractor
@@ -50,5 +51,6 @@
             },
         metricsLogger = metricsLogger,
         dozeLogger = mock(),
+        sceneInteractor = { sceneInteractor },
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/MSDLPlayerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/MSDLPlayerKosmos.kt
index f5a05b4..4f5c32a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/MSDLPlayerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/MSDLPlayerKosmos.kt
@@ -17,5 +17,7 @@
 package com.android.systemui.haptics.msdl
 
 import com.android.systemui.kosmos.Kosmos
+import com.google.android.msdl.domain.MSDLPlayer
 
-val Kosmos.msdlPlayer by Kosmos.Fixture { FakeMSDLPlayer() }
+var Kosmos.msdlPlayer: MSDLPlayer by Kosmos.Fixture { fakeMSDLPlayer }
+val Kosmos.fakeMSDLPlayer by Kosmos.Fixture { FakeMSDLPlayer() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt
index 1e95fc1..740d891 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.keyguard.ui.viewmodel.alternateBouncerWindowViewModel
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.log.logcatLogBuffer
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.statusbar.gesture.TapGestureDetector
 import com.android.systemui.util.mockito.mock
@@ -64,6 +65,7 @@
             },
             messageAreaViewModel = mock<AlternateBouncerMessageAreaViewModel>(),
             powerInteractor = powerInteractor,
+            touchLogBuffer = logcatLogBuffer(),
         )
     }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index 851a378..457bd28 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -36,7 +36,7 @@
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
 import com.android.systemui.globalactions.domain.interactor.globalActionsInteractor
-import com.android.systemui.haptics.msdl.msdlPlayer
+import com.android.systemui.haptics.msdl.fakeMSDLPlayer
 import com.android.systemui.haptics.qs.qsLongPressEffect
 import com.android.systemui.jank.interactionJankMonitor
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -155,5 +155,5 @@
     val scrimController by lazy { kosmos.scrimController }
     val scrimStartable by lazy { kosmos.scrimStartable }
     val sceneContainerOcclusionInteractor by lazy { kosmos.sceneContainerOcclusionInteractor }
-    val msdlPlayer by lazy { kosmos.msdlPlayer }
+    val msdlPlayer by lazy { kosmos.fakeMSDLPlayer }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderKosmos.kt
index a5690a0..cb7750f5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderKosmos.kt
@@ -24,7 +24,6 @@
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.media.controls.util.fakeMediaControllerFactory
 import com.android.systemui.media.controls.util.mediaFlags
-import com.android.systemui.plugins.activityStarter
 
 val Kosmos.mediaDataLoader by
     Kosmos.Fixture {
@@ -32,7 +31,6 @@
             testableContext,
             testDispatcher,
             testScope,
-            activityStarter,
             fakeMediaControllerFactory,
             mediaFlags,
             imageLoader,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorKosmos.kt
index 632436a..174e653 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorKosmos.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.media.controls.data.repository.mediaDataRepository
+import com.android.systemui.media.controls.shared.mediaLogger
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvider
 import com.android.systemui.media.controls.util.fakeMediaControllerFactory
 import com.android.systemui.media.controls.util.mediaFlags
@@ -60,5 +61,6 @@
             keyguardUpdateMonitor = keyguardUpdateMonitor,
             mediaDataRepository = mediaDataRepository,
             mediaDataLoader = { mediaDataLoader },
+            mediaLogger = mediaLogger,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerKosmos.kt
index b7660e0..b33edf9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerKosmos.kt
@@ -28,6 +28,8 @@
     Kosmos.Fixture {
         MediaTimeoutListener(
             mediaControllerFactory = fakeMediaControllerFactory,
+            bgExecutor = fakeExecutor,
+            uiExecutor = fakeExecutor,
             mainExecutor = fakeExecutor,
             logger = MediaTimeoutLogger(logcatLogBuffer("MediaTimeoutLogBuffer")),
             statusBarStateController = statusBarStateController,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/TileLifecycleManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/TileLifecycleManagerKosmos.kt
index a0fc76b..4978558 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/TileLifecycleManagerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/TileLifecycleManagerKosmos.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.qs.tiles.impl.custom.packageManagerAdapterFacade
 import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.time.fakeSystemClock
 
 val Kosmos.tileLifecycleManagerFactory: TileLifecycleManager.Factory by
     Kosmos.Fixture {
@@ -39,6 +40,7 @@
                 activityManager,
                 mock(),
                 fakeExecutor,
+                fakeSystemClock,
             )
         }
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
index 55f3ed7..8744638 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
@@ -12,6 +12,8 @@
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.ui.FakeOverlay
 import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
+import com.android.systemui.scene.ui.viewmodel.splitEdgeDetector
+import com.android.systemui.shade.domain.interactor.shadeInteractor
 import kotlinx.coroutines.flow.MutableStateFlow
 
 var Kosmos.sceneKeys by Fixture {
@@ -70,6 +72,8 @@
             sceneInteractor = sceneInteractor,
             falsingInteractor = falsingInteractor,
             powerInteractor = powerInteractor,
+            shadeInteractor = shadeInteractor,
+            splitEdgeDetector = splitEdgeDetector,
             motionEventHandlerReceiver = {},
             logger = sceneLogger
         )
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
index b612a8b..9a5698c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
@@ -27,6 +27,7 @@
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryHapticsInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
+import com.android.systemui.haptics.msdl.msdlPlayer
 import com.android.systemui.haptics.vibratorHelper
 import com.android.systemui.keyguard.dismissCallbackRegistry
 import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor
@@ -86,5 +87,6 @@
         statusBarStateController = sysuiStatusBarStateController,
         alternateBouncerInteractor = alternateBouncerInteractor,
         vibratorHelper = vibratorHelper,
+        msdlPlayer = msdlPlayer,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorKosmos.kt
new file mode 100644
index 0000000..e0b5292
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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.scene.ui.viewmodel
+
+import androidx.compose.ui.unit.dp
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+
+var Kosmos.splitEdgeDetector: SplitEdgeDetector by
+    Kosmos.Fixture {
+        SplitEdgeDetector(
+            topEdgeSplitFraction = shadeInteractor::getTopEdgeSplitFraction,
+            edgeSize = 40.dp,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/utils/FakeUserScopedService.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/utils/FakeUserScopedService.kt
new file mode 100644
index 0000000..78763f9
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/utils/FakeUserScopedService.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 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.utils
+
+import android.os.UserHandle
+
+class FakeUserScopedService<T>(private val defaultImplementation: T) : UserScopedService<T> {
+
+    private val implementations = mutableMapOf<UserHandle, T>()
+
+    fun addImplementation(user: UserHandle, implementation: T) {
+        implementations[user] = implementation
+    }
+
+    fun removeImplementation(user: UserHandle): T? = implementations.remove(user)
+
+    override fun forUser(user: UserHandle): T =
+        implementations.getOrDefault(user, defaultImplementation)
+}
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 9b0c8e5..eebe5e9f 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -94,6 +94,9 @@
     libs: [
         "ravenwood-runtime-common-ravenwood",
     ],
+    static_libs: [
+        "framework-annotations-lib", // should it be "libs" instead?
+    ],
     visibility: ["//visibility:private"],
 }
 
@@ -127,6 +130,7 @@
     libs: [
         "framework-minus-apex.ravenwood",
         "ravenwood-junit",
+        "ravenwood-helper-libcore-runtime",
     ],
     visibility: ["//visibility:private"],
 }
diff --git a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRedirect.java
similarity index 82%
copy from ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java
copy to ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRedirect.java
index 4b9cf85..b582ccf 100644
--- a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java
+++ b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRedirect.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -15,7 +15,7 @@
  */
 package android.ravenwood.annotation;
 
-import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -29,8 +29,7 @@
  *
  * @hide
  */
-@Target({TYPE})
+@Target({METHOD})
 @Retention(RetentionPolicy.CLASS)
-public @interface RavenwoodNativeSubstitutionClass {
-    String value();
+public @interface RavenwoodRedirect {
 }
diff --git a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRedirectionClass.java
similarity index 94%
rename from ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java
rename to ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRedirectionClass.java
index 4b9cf85..bee9222 100644
--- a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java
+++ b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRedirectionClass.java
@@ -31,6 +31,6 @@
  */
 @Target({TYPE})
 @Retention(RetentionPolicy.CLASS)
-public @interface RavenwoodNativeSubstitutionClass {
+public @interface RavenwoodRedirectionClass {
     String value();
 }
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodAfterClassFailureTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodAfterClassFailureTest.java
new file mode 100644
index 0000000..f9794ad
--- /dev/null
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodAfterClassFailureTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2024 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.ravenwoodtest.bivalenttest.listenertests;
+
+import static android.platform.test.ravenwood.RavenwoodRule.isOnRavenwood;
+
+import org.junit.AfterClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
+/**
+ * Test that throws from @AfterClass.
+ *
+ * Tradefed would ignore it, so instead RavenwoodAwareTestRunner would detect it and kill
+ * the self (test) process.
+ *
+ * Unfortunately, this behavior can't easily be tested from within this class, so for now
+ * it's only used for a manual test, which you can run by removing the @Ignore.
+ *
+ * TODO(b/364948126) Improve the tests and automate it.
+ */
+@Ignore
+@RunWith(ParameterizedAndroidJunit4.class)
+public class RavenwoodAfterClassFailureTest {
+    public RavenwoodAfterClassFailureTest(String param) {
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        if (!isOnRavenwood()) return; // Don't do anything on real device.
+
+        throw new RuntimeException("FAILURE");
+    }
+
+    @Parameters
+    public static List<String> getParams() {
+        var params =  new ArrayList<String>();
+        params.add("foo");
+        params.add("bar");
+        return params;
+    }
+
+    @Test
+    public void test1() {
+    }
+
+    @Test
+    public void test2() {
+    }
+}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodBeforeClassAssumptionFailureTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodBeforeClassAssumptionFailureTest.java
new file mode 100644
index 0000000..61fb068
--- /dev/null
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodBeforeClassAssumptionFailureTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 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.ravenwoodtest.bivalenttest.listenertests;
+
+import static android.platform.test.ravenwood.RavenwoodRule.isOnRavenwood;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
+/**
+ * Test that fails in assumption in @BeforeClass.
+ *
+ * This is only used for manual tests. Make sure `atest` shows 4 test results with
+ * "ASSUMPTION_FAILED".
+ *
+ * TODO(b/364948126) Improve the tests and automate it.
+ */
+@RunWith(ParameterizedAndroidJunit4.class)
+public class RavenwoodBeforeClassAssumptionFailureTest {
+    public RavenwoodBeforeClassAssumptionFailureTest(String param) {
+    }
+
+    @BeforeClass
+    public static void beforeClass() {
+        if (!isOnRavenwood()) return; // Don't do anything on real device.
+
+        Assume.assumeTrue(false);
+    }
+
+    @Parameters
+    public static List<String> getParams() {
+        var params =  new ArrayList<String>();
+        params.add("foo");
+        params.add("bar");
+        return params;
+    }
+
+    @Test
+    public void test1() {
+    }
+
+    @Test
+    public void test2() {
+    }
+}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodBeforeClassFailureTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodBeforeClassFailureTest.java
new file mode 100644
index 0000000..626ce81
--- /dev/null
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodBeforeClassFailureTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2024 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.ravenwoodtest.bivalenttest.listenertests;
+
+import static android.platform.test.ravenwood.RavenwoodRule.isOnRavenwood;
+
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
+/**
+ * Test that fails throws from @BeforeClass.
+ *
+ * This is only used for manual tests. Make sure `atest` shows 4 test results with
+ * a "FAILURE" runtime exception.
+ *
+ * In order to run the test, you'll need to remove the @Ignore.
+ *
+ * TODO(b/364948126) Improve the tests and automate it.
+ */
+@Ignore
+@RunWith(ParameterizedAndroidJunit4.class)
+public class RavenwoodBeforeClassFailureTest {
+    public static final String TAG = "RavenwoodBeforeClassFailureTest";
+
+    public RavenwoodBeforeClassFailureTest(String param) {
+    }
+
+    @BeforeClass
+    public static void beforeClass() {
+        if (!isOnRavenwood()) return; // Don't do anything on real device.
+
+        throw new RuntimeException("FAILURE");
+    }
+
+    @Parameters
+    public static List<String> getParams() {
+        var params =  new ArrayList<String>();
+        params.add("foo");
+        params.add("bar");
+        return params;
+    }
+
+    @Test
+    public void test1() {
+    }
+
+    @Test
+    public void test2() {
+    }
+}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodClassRuleAssumptionFailureTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodClassRuleAssumptionFailureTest.java
new file mode 100644
index 0000000..dc949c4
--- /dev/null
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodClassRuleAssumptionFailureTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 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.ravenwoodtest.bivalenttest.listenertests;
+
+import static android.platform.test.ravenwood.RavenwoodRule.isOnRavenwood;
+
+import static org.junit.Assume.assumeTrue;
+
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.Statement;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
+/**
+ * Test that fails in assumption from a class rule.
+ *
+ * This is only used for manual tests. Make sure `atest` shows 4 test results with
+ * "ASSUMPTION_FAILED".
+ *
+ * TODO(b/364948126) Improve the tests and automate it.
+ */
+@RunWith(ParameterizedAndroidJunit4.class)
+public class RavenwoodClassRuleAssumptionFailureTest {
+    public static final String TAG = "RavenwoodClassRuleFailureTest";
+
+    @ClassRule
+    public static final TestRule sClassRule = new TestRule() {
+        @Override
+        public Statement apply(Statement base, Description description) {
+            if (!isOnRavenwood()) {
+                return base; // Just run the test as-is on a real device.
+            }
+
+            assumeTrue(false);
+            return null; // unreachable
+        }
+    };
+
+    public RavenwoodClassRuleAssumptionFailureTest(String param) {
+    }
+
+    @Parameters
+    public static List<String> getParams() {
+        var params =  new ArrayList<String>();
+        params.add("foo");
+        params.add("bar");
+        return params;
+    }
+
+    @Test
+    public void test1() {
+    }
+
+    @Test
+    public void test2() {
+    }
+}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodClassRuleFailureTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodClassRuleFailureTest.java
new file mode 100644
index 0000000..9996bec
--- /dev/null
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/listenertests/RavenwoodClassRuleFailureTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 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.ravenwoodtest.bivalenttest.listenertests;
+
+import static android.platform.test.ravenwood.RavenwoodRule.isOnRavenwood;
+
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.Statement;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
+/**
+ * Test that fails throws from a class rule.
+ *
+ * This is only used for manual tests. Make sure `atest` shows 4 test results with
+ * a "FAILURE" runtime exception.
+ *
+ * In order to run the test, you'll need to remove the @Ignore.
+ *
+ * TODO(b/364948126) Improve the tests and automate it.
+ */
+@Ignore
+@RunWith(ParameterizedAndroidJunit4.class)
+public class RavenwoodClassRuleFailureTest {
+    public static final String TAG = "RavenwoodClassRuleFailureTest";
+
+    @ClassRule
+    public static final TestRule sClassRule = new TestRule() {
+        @Override
+        public Statement apply(Statement base, Description description) {
+            if (!isOnRavenwood()) {
+                return base; // Just run the test as-is on a real device.
+            }
+
+            throw new RuntimeException("FAILURE");
+        }
+    };
+
+    public RavenwoodClassRuleFailureTest(String param) {
+    }
+
+    @Parameters
+    public static List<String> getParams() {
+        var params =  new ArrayList<String>();
+        params.add("foo");
+        params.add("bar");
+        return params;
+    }
+
+    @Test
+    public void test1() {
+    }
+
+    @Test
+    public void test2() {
+    }
+}
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java
index f237ba9..6d21e440 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java
@@ -27,20 +27,30 @@
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.internal.os.RuntimeInit;
+import com.android.ravenwood.common.RavenwoodCommonUtils;
+
 import org.junit.runner.Description;
 import org.junit.runner.Runner;
 import org.junit.runners.model.TestClass;
 
+import java.util.Stack;
+
 /**
  * Provide hook points created by {@link RavenwoodAwareTestRunner}.
  */
 public class RavenwoodAwareTestRunnerHook {
-    private static final String TAG = "RavenwoodAwareTestRunnerHook";
+    private static final String TAG = RavenwoodAwareTestRunner.TAG;
 
     private RavenwoodAwareTestRunnerHook() {
     }
 
     private static RavenwoodTestStats sStats; // lazy initialization.
+
+    // Keep track of the current class description.
+
+    // Test classes can be nested because of "Suite", so we need a stack to keep track.
+    private static final Stack<Description> sClassDescriptions = new Stack<>();
     private static Description sCurrentClassDescription;
 
     private static RavenwoodTestStats getStats() {
@@ -56,20 +66,36 @@
      * Called when a runner starts, before the inner runner gets a chance to run.
      */
     public static void onRunnerInitializing(Runner runner, TestClass testClass) {
+        // TODO: Move the initialization code to a better place.
+
+        initOnce();
+
         // This log call also ensures the framework JNI is loaded.
         Log.i(TAG, "onRunnerInitializing: testClass=" + testClass.getJavaClass()
                 + " runner=" + runner);
 
-        // TODO: Move the initialization code to a better place.
+        // This is needed to make AndroidJUnit4ClassRunner happy.
+        InstrumentationRegistry.registerInstance(null, Bundle.EMPTY);
+    }
+
+    private static boolean sInitialized = false;
+
+    private static void initOnce() {
+        if (sInitialized) {
+            return;
+        }
+        sInitialized = true;
+
+        // We haven't initialized liblog yet, so directly write to System.out here.
+        RavenwoodCommonUtils.log(TAG, "initOnce()");
+
+        // Redirect stdout/stdin to liblog.
+        RuntimeInit.redirectLogStreams();
 
         // This will let AndroidJUnit4 use the original runner.
         System.setProperty("android.junit.runner",
                 "androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner");
         System.setProperty(RAVENWOOD_VERSION_JAVA_SYSPROP, "1");
-
-
-        // This is needed to make AndroidJUnit4ClassRunner happy.
-        InstrumentationRegistry.registerInstance(null, Bundle.EMPTY);
     }
 
     /**
@@ -87,16 +113,17 @@
      */
     public static boolean onBefore(RavenwoodAwareTestRunner runner, Description description,
             Scope scope, Order order) {
-        Log.i(TAG, "onBefore: description=" + description + ", " + scope + ", " + order);
+        Log.v(TAG, "onBefore: description=" + description + ", " + scope + ", " + order);
 
-        if (scope == Scope.Class && order == Order.First) {
+        if (scope == Scope.Class && order == Order.Outer) {
             // Keep track of the current class.
             sCurrentClassDescription = description;
+            sClassDescriptions.push(description);
         }
 
         // Class-level annotations are checked by the runner already, so we only check
         // method-level annotations here.
-        if (scope == Scope.Instance && order == Order.First) {
+        if (scope == Scope.Instance && order == Order.Outer) {
             if (!RavenwoodEnablementChecker.shouldEnableOnRavenwood(
                     description, true)) {
                 getStats().onTestFinished(sCurrentClassDescription, description, Result.Skipped);
@@ -113,19 +140,22 @@
      */
     public static boolean onAfter(RavenwoodAwareTestRunner runner, Description description,
             Scope scope, Order order, Throwable th) {
-        Log.i(TAG, "onAfter: description=" + description + ", " + scope + ", " + order + ", " + th);
+        Log.v(TAG, "onAfter: description=" + description + ", " + scope + ", " + order + ", " + th);
 
-        if (scope == Scope.Instance && order == Order.First) {
+        if (scope == Scope.Instance && order == Order.Outer) {
             getStats().onTestFinished(sCurrentClassDescription, description,
                     th == null ? Result.Passed : Result.Failed);
 
-        } else if (scope == Scope.Class && order == Order.Last) {
+        } else if (scope == Scope.Class && order == Order.Outer) {
             getStats().onClassFinished(sCurrentClassDescription);
+            sClassDescriptions.pop();
+            sCurrentClassDescription =
+                    sClassDescriptions.size() == 0 ? null : sClassDescriptions.peek();
         }
 
         // If RUN_DISABLED_TESTS is set, and the method did _not_ throw, make it an error.
         if (RavenwoodRule.private$ravenwood().isRunningDisabledTests()
-                && scope == Scope.Instance && order == Order.First) {
+                && scope == Scope.Instance && order == Order.Outer) {
 
             boolean isTestEnabled = RavenwoodEnablementChecker.shouldEnableOnRavenwood(
                     description, false);
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
index a2088fd..0059360 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
@@ -36,7 +36,6 @@
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.internal.os.RuntimeInit;
 import com.android.server.LocalServices;
 
 import org.junit.runner.Description;
@@ -92,8 +91,6 @@
             Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler);
         }
 
-        RuntimeInit.redirectLogStreams();
-
         android.os.Process.init$ravenwood(rule.mUid, rule.mPid);
         android.os.Binder.init$ravenwood();
         setSystemProperties(rule.mSystemProperties);
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodTestStats.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodTestStats.java
index 631f68f..3ffabef 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodTestStats.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodTestStats.java
@@ -127,7 +127,11 @@
         int passed = 0;
         int skipped = 0;
         int failed = 0;
-        for (var e : mStats.get(classDescription).values()) {
+        var stats = mStats.get(classDescription);
+        if (stats == null) {
+            return;
+        }
+        for (var e : stats.values()) {
             switch (e) {
                 case Passed: passed++; break;
                 case Skipped: skipped++; break;
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
index 7d99166..dffb263 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
@@ -15,21 +15,25 @@
  */
 package android.platform.test.ravenwood;
 
+import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING;
 import static com.android.ravenwood.common.RavenwoodCommonUtils.ensureIsPublicVoidMethod;
 import static com.android.ravenwood.common.RavenwoodCommonUtils.isOnRavenwood;
 
 import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.ElementType.TYPE;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.util.Log;
 
-import com.android.ravenwood.common.RavenwoodCommonUtils;
 import com.android.ravenwood.common.SneakyThrow;
 
 import org.junit.Assume;
+import org.junit.AssumptionViolatedException;
 import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
+import org.junit.runner.Result;
 import org.junit.runner.Runner;
 import org.junit.runner.manipulation.Filter;
 import org.junit.runner.manipulation.Filterable;
@@ -40,8 +44,11 @@
 import org.junit.runner.manipulation.Sortable;
 import org.junit.runner.manipulation.Sorter;
 import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
 import org.junit.runner.notification.RunNotifier;
+import org.junit.runner.notification.StoppedByUserException;
 import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.MultipleFailureException;
 import org.junit.runners.model.RunnerBuilder;
 import org.junit.runners.model.Statement;
 import org.junit.runners.model.TestClass;
@@ -52,6 +59,8 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Stack;
 
 /**
  * A test runner used for Ravenwood.
@@ -62,7 +71,7 @@
  *   the inner runner gets a chance to run. This can be used to initialize stuff used by the
  *   inner runner.
  * - Add hook points, which are handed by RavenwoodAwareTestRunnerHook, with help from
- *   the four test rules such as {@link #sImplicitClassMinRule}, which are also injected by
+ *   the four test rules such as {@link #sImplicitClassOuterRule}, which are also injected by
  *   the ravenizer tool.
  *
  * We use this runner to:
@@ -75,7 +84,7 @@
  * (no hooks, etc.)
  */
 public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orderable {
-    private static final String TAG = "RavenwoodAwareTestRunner";
+    public static final String TAG = "Ravenwood";
 
     @Inherited
     @Target({TYPE})
@@ -103,28 +112,50 @@
 
     /** Order of a hook. */
     public enum Order {
-        First,
-        Last,
+        Outer,
+        Inner,
     }
 
     // The following four rule instances will be injected to tests by the Ravenizer tool.
+    private static class RavenwoodClassOuterRule implements TestRule {
+        @Override
+        public Statement apply(Statement base, Description description) {
+            return getCurrentRunner().updateStatement(base, description, Scope.Class, Order.Outer);
+        }
+    }
 
-    public static final TestRule sImplicitClassMinRule = (base, description) ->
-            getCurrentRunner().updateStatement(base, description, Scope.Class, Order.First);
+    private static class RavenwoodClassInnerRule implements TestRule {
+        @Override
+        public Statement apply(Statement base, Description description) {
+            return getCurrentRunner().updateStatement(base, description, Scope.Class, Order.Inner);
+        }
+    }
 
-    public static final TestRule sImplicitClassMaxRule = (base, description) ->
-            getCurrentRunner().updateStatement(base, description, Scope.Class, Order.Last);
+    private static class RavenwoodInstanceOuterRule implements TestRule {
+        @Override
+        public Statement apply(Statement base, Description description) {
+            return getCurrentRunner().updateStatement(
+                    base, description, Scope.Instance, Order.Outer);
+        }
+    }
 
-    public static final TestRule sImplicitInstMinRule = (base, description) ->
-            getCurrentRunner().updateStatement(base, description, Scope.Instance, Order.First);
+    private static class RavenwoodInstanceInnerRule implements TestRule {
+        @Override
+        public Statement apply(Statement base, Description description) {
+            return getCurrentRunner().updateStatement(
+                    base, description, Scope.Instance, Order.Inner);
+        }
+    }
 
-    public static final TestRule sImplicitInstMaxRule = (base, description) ->
-            getCurrentRunner().updateStatement(base, description, Scope.Instance, Order.Last);
+    public static final TestRule sImplicitClassOuterRule = new RavenwoodClassOuterRule();
+    public static final TestRule sImplicitClassInnerRule = new RavenwoodClassInnerRule();
+    public static final TestRule sImplicitInstOuterRule = new RavenwoodInstanceOuterRule();
+    public static final TestRule sImplicitInstInnerRule = new RavenwoodInstanceOuterRule();
 
-    public static final String IMPLICIT_CLASS_MIN_RULE_NAME = "sImplicitClassMinRule";
-    public static final String IMPLICIT_CLASS_MAX_RULE_NAME = "sImplicitClassMaxRule";
-    public static final String IMPLICIT_INST_MIN_RULE_NAME = "sImplicitInstMinRule";
-    public static final String IMPLICIT_INST_MAX_RULE_NAME = "sImplicitInstMaxRule";
+    public static final String IMPLICIT_CLASS_OUTER_RULE_NAME = "sImplicitClassOuterRule";
+    public static final String IMPLICIT_CLASS_INNER_RULE_NAME = "sImplicitClassInnerRule";
+    public static final String IMPLICIT_INST_OUTER_RULE_NAME = "sImplicitInstOuterRule";
+    public static final String IMPLICIT_INST_INNER_RULE_NAME = "sImplicitInstInnerRule";
 
     /** Keeps track of the runner on the current thread. */
     private static final ThreadLocal<RavenwoodAwareTestRunner> sCurrentRunner = new ThreadLocal<>();
@@ -142,16 +173,9 @@
     private Description mDescription = null;
     private Throwable mExceptionInConstructor = null;
 
-    /** Simple logging method. */
-    private void log(String message) {
-        RavenwoodCommonUtils.log(TAG, "[" + getTestClass().getJavaClass() + "  @" + this + "] "
-                + message);
-    }
-
-    private Error logAndFail(String message, Throwable innerException) {
-        log(message);
-        log("    Exception=" + innerException);
-        throw new AssertionError(message, innerException);
+    private Error logAndFail(String message, Throwable exception) {
+        Log.e(TAG, message, exception);
+        throw new AssertionError(message, exception);
     }
 
     public TestClass getTestClass() {
@@ -165,6 +189,10 @@
         try {
             mTestClass = new TestClass(testClass);
 
+            Log.v(TAG, "RavenwoodAwareTestRunner starting for " + testClass.getCanonicalName());
+
+            onRunnerInitializing();
+
             /*
              * If the class has @DisabledOnRavenwood, then we'll delegate to
              * ClassSkippingTestRunner, which simply skips it.
@@ -186,10 +214,8 @@
                 realRunnerClass = BlockJUnit4ClassRunner.class;
             }
 
-            onRunnerInitializing();
-
             try {
-                log("Initializing the inner runner: " + realRunnerClass);
+                Log.i(TAG, "Initializing the inner runner: " + realRunnerClass);
 
                 mRealRunner = instantiateRealRunner(realRunnerClass, testClass);
                 mDescription = mRealRunner.getDescription();
@@ -201,8 +227,7 @@
         } catch (Throwable th) {
             // If we throw in the constructor, Tradefed may not report it and just ignore the class,
             // so record it and throw it when the test actually started.
-            log("Fatal: Exception detected in constructor: " + th.getMessage() + "\n"
-                    + Log.getStackTraceString(th));
+            Log.e(TAG, "Fatal: Exception detected in constructor", th);
             mExceptionInConstructor = new RuntimeException("Exception detected in constructor",
                     th);
             mDescription = Description.createTestDescription(testClass, "Constructor");
@@ -236,8 +261,7 @@
         if (!isOnRavenwood()) {
             return;
         }
-
-        log("onRunnerInitializing");
+        // DO NOT USE android.util.Log before calling onRunnerInitializing().
 
         RavenwoodAwareTestRunnerHook.onRunnerInitializing(this, mTestClass);
 
@@ -250,7 +274,7 @@
         if (!isOnRavenwood()) {
             return;
         }
-        log("runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());
+        Log.v(TAG, "runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());
 
         for (var method : getTestClass().getAnnotatedMethods(annotationClass)) {
             ensureIsPublicVoidMethod(method.getMethod(), /* isStatic=*/ instance == null);
@@ -271,20 +295,27 @@
     }
 
     @Override
-    public void run(RunNotifier notifier) {
+    public void run(RunNotifier realNotifier) {
+        final RunNotifier notifier = new RavenwoodRunNotifier(realNotifier);
+
         if (mRealRunner instanceof ClassSkippingTestRunner) {
             mRealRunner.run(notifier);
             RavenwoodAwareTestRunnerHook.onClassSkipped(getDescription());
             return;
         }
 
+        Log.v(TAG, "Starting " + mTestClass.getJavaClass().getCanonicalName());
+        if (RAVENWOOD_VERBOSE_LOGGING) {
+            dumpDescription(getDescription());
+        }
+
         if (maybeReportExceptionFromConstructor(notifier)) {
             return;
         }
 
         sCurrentRunner.set(this);
         try {
-            runWithHooks(getDescription(), Scope.Runner, Order.First,
+            runWithHooks(getDescription(), Scope.Runner, Order.Outer,
                     () -> mRealRunner.run(notifier));
         } finally {
             sCurrentRunner.remove();
@@ -409,4 +440,217 @@
             }
         }
     }
+
+    private void dumpDescription(Description desc) {
+        dumpDescription(desc, "[TestDescription]=", "  ");
+    }
+
+    private void dumpDescription(Description desc, String header, String indent) {
+        Log.v(TAG, indent + header + desc);
+
+        var children = desc.getChildren();
+        var childrenIndent = "  " + indent;
+        for (int i = 0; i < children.size(); i++) {
+            dumpDescription(children.get(i), "#" + i + ": ", childrenIndent);
+        }
+    }
+
+    /**
+     * A run notifier that wraps another notifier and provides the following features:
+     * - Handle a failure that happened before testStarted and testEnded (typically that means
+     *   it's from @BeforeClass or @AfterClass, or a @ClassRule) and deliver it as if
+     *   individual tests in the class reported it. This is for b/364395552.
+     *
+     * - Logging.
+     */
+    private class RavenwoodRunNotifier extends RunNotifier {
+        private final RunNotifier mRealNotifier;
+
+        private final Stack<Description> mSuiteStack = new Stack<>();
+        private Description mCurrentSuite = null;
+        private final ArrayList<Throwable> mOutOfTestFailures = new ArrayList<>();
+
+        private boolean mBeforeTest = true;
+        private boolean mAfterTest = false;
+
+        private RavenwoodRunNotifier(RunNotifier realNotifier) {
+            mRealNotifier = realNotifier;
+        }
+
+        private boolean isInTest() {
+            return !mBeforeTest && !mAfterTest;
+        }
+
+        @Override
+        public void addListener(RunListener listener) {
+            mRealNotifier.addListener(listener);
+        }
+
+        @Override
+        public void removeListener(RunListener listener) {
+            mRealNotifier.removeListener(listener);
+        }
+
+        @Override
+        public void addFirstListener(RunListener listener) {
+            mRealNotifier.addFirstListener(listener);
+        }
+
+        @Override
+        public void fireTestRunStarted(Description description) {
+            Log.i(TAG, "testRunStarted: " + description);
+            mRealNotifier.fireTestRunStarted(description);
+        }
+
+        @Override
+        public void fireTestRunFinished(Result result) {
+            Log.i(TAG, "testRunFinished: "
+                    + result.getRunCount() + ","
+                    + result.getFailureCount() + ","
+                    + result.getAssumptionFailureCount() + ","
+                    + result.getIgnoreCount());
+            mRealNotifier.fireTestRunFinished(result);
+        }
+
+        @Override
+        public void fireTestSuiteStarted(Description description) {
+            Log.i(TAG, "testSuiteStarted: " + description);
+            mRealNotifier.fireTestSuiteStarted(description);
+
+            mBeforeTest = true;
+            mAfterTest = false;
+
+            // Keep track of the current suite, needed if the outer test is a Suite,
+            // in which case its children are test classes. (not test methods)
+            mCurrentSuite = description;
+            mSuiteStack.push(description);
+
+            mOutOfTestFailures.clear();
+        }
+
+        @Override
+        public void fireTestSuiteFinished(Description description) {
+            Log.i(TAG, "testSuiteFinished: " + description);
+            mRealNotifier.fireTestSuiteFinished(description);
+
+            maybeHandleOutOfTestFailures();
+
+            mBeforeTest = true;
+            mAfterTest = false;
+
+            // Restore the upper suite.
+            mSuiteStack.pop();
+            mCurrentSuite = mSuiteStack.size() == 0 ? null : mSuiteStack.peek();
+        }
+
+        @Override
+        public void fireTestStarted(Description description) throws StoppedByUserException {
+            Log.i(TAG, "testStarted: " + description);
+            mRealNotifier.fireTestStarted(description);
+
+            mAfterTest = false;
+            mBeforeTest = false;
+        }
+
+        @Override
+        public void fireTestFailure(Failure failure) {
+            Log.i(TAG, "testFailure: " + failure);
+
+            if (isInTest()) {
+                mRealNotifier.fireTestFailure(failure);
+            } else {
+                mOutOfTestFailures.add(failure.getException());
+            }
+        }
+
+        @Override
+        public void fireTestAssumptionFailed(Failure failure) {
+            Log.i(TAG, "testAssumptionFailed: " + failure);
+
+            if (isInTest()) {
+                mRealNotifier.fireTestAssumptionFailed(failure);
+            } else {
+                mOutOfTestFailures.add(failure.getException());
+            }
+        }
+
+        @Override
+        public void fireTestIgnored(Description description) {
+            Log.i(TAG, "testIgnored: " + description);
+            mRealNotifier.fireTestIgnored(description);
+        }
+
+        @Override
+        public void fireTestFinished(Description description) {
+            Log.i(TAG, "testFinished: " + description);
+            mRealNotifier.fireTestFinished(description);
+
+            mAfterTest = true;
+        }
+
+        @Override
+        public void pleaseStop() {
+            Log.w(TAG, "pleaseStop:");
+            mRealNotifier.pleaseStop();
+        }
+
+        /**
+         * At the end of each Suite, we handle failures happened out of test methods.
+         * (typically in @BeforeClass or @AfterClasses)
+         *
+         * This is to work around b/364395552.
+         */
+        private boolean maybeHandleOutOfTestFailures() {
+            if (mOutOfTestFailures.size() == 0) {
+                return false;
+            }
+            Throwable th;
+            if (mOutOfTestFailures.size() == 1) {
+                th = mOutOfTestFailures.get(0);
+            } else {
+                th = new MultipleFailureException(mOutOfTestFailures);
+            }
+            if (mBeforeTest) {
+                reportBeforeTestFailure(mCurrentSuite, th);
+                return true;
+            }
+            if (mAfterTest) {
+                // Unfortunately, there's no good way to report it, so kill the own process.
+                onCriticalError(
+                        "Failures detected in @AfterClass, which would be swalloed by tradefed",
+                        th);
+                return true; // unreachable
+            }
+            return false;
+        }
+
+        private void reportBeforeTestFailure(Description suiteDesc, Throwable th) {
+            // If a failure happens befere running any tests, we'll need to pretend
+            // as if each test in the suite reported the failure, to work around b/364395552.
+            for (var child : suiteDesc.getChildren()) {
+                if (child.isSuite()) {
+                    // If the chiil is still a "parent" -- a test class or a test suite
+                    // -- propagate to its children.
+                    mRealNotifier.fireTestSuiteStarted(child);
+                    reportBeforeTestFailure(child, th);
+                    mRealNotifier.fireTestSuiteFinished(child);
+                } else {
+                    mRealNotifier.fireTestStarted(child);
+                    Failure f = new Failure(child, th);
+                    if (th instanceof AssumptionViolatedException) {
+                        mRealNotifier.fireTestAssumptionFailed(f);
+                    } else {
+                        mRealNotifier.fireTestFailure(f);
+                    }
+                    mRealNotifier.fireTestFinished(child);
+                }
+            }
+        }
+    }
+
+    private void onCriticalError(@NonNull String message, @Nullable Throwable th) {
+        Log.e(TAG, "Critical error! Ravenwood cannot continue. Killing self process: "
+                + message, th);
+        System.exit(1);
+    }
 }
diff --git a/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java b/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java
index 7b5bc5a..875ce71 100644
--- a/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java
+++ b/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java
@@ -15,12 +15,17 @@
  */
 package com.android.ravenwood.common;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
 import com.android.ravenwood.common.divergence.RavenwoodDivergence;
 
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
@@ -33,6 +38,14 @@
 
     private static final Object sLock = new Object();
 
+    /**
+     * If set to "1", we enable the verbose logging.
+     *
+     * (See also InitLogging() in http://ac/system/libbase/logging.cpp)
+     */
+    public static final boolean RAVENWOOD_VERBOSE_LOGGING = "1".equals(System.getenv(
+            "RAVENWOOD_VERBOSE"));
+
     /** Name of `libravenwood_runtime` */
     private static final String RAVENWOOD_NATIVE_RUNTIME_NAME = "ravenwood_runtime";
 
@@ -265,4 +278,12 @@
                 method.getDeclaringClass().getName(), method.getName(),
                 (isStatic ? "static " : "")));
     }
+
+    @NonNull
+    public static String getStackTraceString(@Nullable Throwable th) {
+        StringWriter stringWriter = new StringWriter();
+        PrintWriter writer = new PrintWriter(stringWriter);
+        th.printStackTrace(writer);
+        return stringWriter.toString();
+    }
 }
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/CursorWindow_host.java b/ravenwood/runtime-helper-src/framework/android/database/CursorWindow_host.java
similarity index 89%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/CursorWindow_host.java
rename to ravenwood/runtime-helper-src/framework/android/database/CursorWindow_host.java
index f38d565..e21a9cd 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/CursorWindow_host.java
+++ b/ravenwood/runtime-helper-src/framework/android/database/CursorWindow_host.java
@@ -13,9 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.platform.test.ravenwood.nativesubstitution;
+package android.database;
 
-import android.database.Cursor;
 import android.database.sqlite.SQLiteException;
 import android.os.Parcel;
 import android.util.Base64;
@@ -35,8 +34,8 @@
     private String mName;
     private int mColumnNum;
     private static class Row {
-        String[] fields;
-        int[] types;
+        String[] mFields;
+        int[] mTypes;
     }
 
     private final List<Row> mRows = new ArrayList<>();
@@ -69,9 +68,9 @@
     public static boolean nativeAllocRow(long windowPtr) {
         CursorWindow_host instance = sInstances.get(windowPtr);
         Row row = new Row();
-        row.fields = new String[instance.mColumnNum];
-        row.types = new int[instance.mColumnNum];
-        Arrays.fill(row.types, Cursor.FIELD_TYPE_NULL);
+        row.mFields = new String[instance.mColumnNum];
+        row.mTypes = new int[instance.mColumnNum];
+        Arrays.fill(row.mTypes, Cursor.FIELD_TYPE_NULL);
         instance.mRows.add(row);
         return true;
     }
@@ -82,8 +81,8 @@
             return false;
         }
         Row r = instance.mRows.get(row);
-        r.fields[column] = value;
-        r.types[column] = type;
+        r.mFields[column] = value;
+        r.mTypes[column] = type;
         return true;
     }
 
@@ -93,7 +92,7 @@
             return Cursor.FIELD_TYPE_NULL;
         }
 
-        return instance.mRows.get(row).types[column];
+        return instance.mRows.get(row).mTypes[column];
     }
 
     public static boolean nativePutString(long windowPtr, String value,
@@ -107,7 +106,7 @@
             return null;
         }
 
-        return instance.mRows.get(row).fields[column];
+        return instance.mRows.get(row).mFields[column];
     }
 
     public static boolean nativePutLong(long windowPtr, long value, int row, int column) {
@@ -170,8 +169,8 @@
         parcel.writeInt(window.mColumnNum);
         parcel.writeInt(window.mRows.size());
         for (int row = 0; row < window.mRows.size(); row++) {
-            parcel.writeStringArray(window.mRows.get(row).fields);
-            parcel.writeIntArray(window.mRows.get(row).types);
+            parcel.writeStringArray(window.mRows.get(row).mFields);
+            parcel.writeIntArray(window.mRows.get(row).mTypes);
         }
     }
 
@@ -183,8 +182,8 @@
         int rowCount = parcel.readInt();
         for (int row = 0; row < rowCount; row++) {
             Row r = new Row();
-            r.fields = parcel.createStringArray();
-            r.types = parcel.createIntArray();
+            r.mFields = parcel.createStringArray();
+            r.mTypes = parcel.createIntArray();
             window.mRows.add(r);
         }
         return windowPtr;
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/MessageQueue_host.java b/ravenwood/runtime-helper-src/framework/android/os/MessageQueue_host.java
similarity index 97%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/MessageQueue_host.java
rename to ravenwood/runtime-helper-src/framework/android/os/MessageQueue_host.java
index 5e81124..1b63adc 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/MessageQueue_host.java
+++ b/ravenwood/runtime-helper-src/framework/android/os/MessageQueue_host.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.platform.test.ravenwood.nativesubstitution;
+package android.os;
 
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java b/ravenwood/runtime-helper-src/framework/android/os/Parcel_host.java
similarity index 99%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java
rename to ravenwood/runtime-helper-src/framework/android/os/Parcel_host.java
index cb00b3e..720f1d2 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java
+++ b/ravenwood/runtime-helper-src/framework/android/os/Parcel_host.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.platform.test.ravenwood.nativesubstitution;
+package android.os;
 
 import android.system.ErrnoException;
 import android.system.Os;
@@ -527,4 +527,4 @@
         }
         return false;
     }
-}
\ No newline at end of file
+}
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/SystemProperties_host.java b/ravenwood/runtime-helper-src/framework/android/os/SystemProperties_host.java
similarity index 89%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/SystemProperties_host.java
rename to ravenwood/runtime-helper-src/framework/android/os/SystemProperties_host.java
index e7479d3..b09bf31 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/SystemProperties_host.java
+++ b/ravenwood/runtime-helper-src/framework/android/os/SystemProperties_host.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.platform.test.ravenwood.nativesubstitution;
+package android.os;
 
 import android.util.SparseArray;
 
@@ -36,9 +36,6 @@
     /** Predicate tested to determine if a given key can be written. */
     @GuardedBy("sLock")
     private static Predicate<String> sKeyWritablePredicate;
-    /** Callback to trigger when values are changed */
-    @GuardedBy("sLock")
-    private static Runnable sChangeCallback;
 
     /**
      * Reverse mapping that provides a way back to an original key from the
@@ -48,7 +45,7 @@
     private static SparseArray<String> sKeyHandles = new SparseArray<>();
 
     /**
-     * Basically the same as {@link #native_init$ravenwood}, but it'll only run if no values are
+     * Basically the same as {@link #init$ravenwood}, but it'll only run if no values are
      * set yet.
      */
     public static void initializeIfNeeded(Map<String, String> values,
@@ -57,30 +54,32 @@
             if (sValues != null) {
                 return; // Already initialized.
             }
-            native_init$ravenwood(values, keyReadablePredicate, keyWritablePredicate,
-                    () -> {});
+            init$ravenwood(values, keyReadablePredicate, keyWritablePredicate);
         }
     }
 
-    public static void native_init$ravenwood(Map<String, String> values,
-            Predicate<String> keyReadablePredicate, Predicate<String> keyWritablePredicate,
-            Runnable changeCallback) {
+    public static void init$ravenwood(Map<String, String> values,
+            Predicate<String> keyReadablePredicate, Predicate<String> keyWritablePredicate) {
         synchronized (sLock) {
             sValues = Objects.requireNonNull(values);
             sKeyReadablePredicate = Objects.requireNonNull(keyReadablePredicate);
             sKeyWritablePredicate = Objects.requireNonNull(keyWritablePredicate);
-            sChangeCallback = Objects.requireNonNull(changeCallback);
             sKeyHandles.clear();
+            synchronized (SystemProperties.sChangeCallbacks) {
+                SystemProperties.sChangeCallbacks.clear();
+            }
         }
     }
 
-    public static void native_reset$ravenwood() {
+    public static void reset$ravenwood() {
         synchronized (sLock) {
             sValues = null;
             sKeyReadablePredicate = null;
             sKeyWritablePredicate = null;
-            sChangeCallback = null;
             sKeyHandles.clear();
+            synchronized (SystemProperties.sChangeCallbacks) {
+                SystemProperties.sChangeCallbacks.clear();
+            }
         }
     }
 
@@ -101,7 +100,7 @@
             } else {
                 sValues.put(key, val);
             }
-            sChangeCallback.run();
+            SystemProperties.callChangeCallbacks();
         }
     }
 
@@ -183,7 +182,7 @@
         // Report through callback always registered via init above
         synchronized (sLock) {
             Preconditions.requireNonNullViaRavenwoodRule(sValues);
-            sChangeCallback.run();
+            SystemProperties.callChangeCallbacks();
         }
     }
 
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/EventLog_host.java b/ravenwood/runtime-helper-src/framework/android/util/EventLog_host.java
similarity index 83%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/EventLog_host.java
rename to ravenwood/runtime-helper-src/framework/android/util/EventLog_host.java
index 55d4ffb..878a0ff 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/EventLog_host.java
+++ b/ravenwood/runtime-helper-src/framework/android/util/EventLog_host.java
@@ -13,12 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.platform.test.ravenwood.nativesubstitution;
+package android.util;
 
 import com.android.internal.os.RuntimeInit;
 
 import java.io.PrintStream;
-import java.util.Collection;
 
 public class EventLog_host {
     public static int writeEvent(int tag, int value) {
@@ -58,15 +57,6 @@
         return sb.length();
     }
 
-    public static void readEvents(int[] tags, Collection<android.util.EventLog.Event> output) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static void readEventsOnWrapping(int[] tags, long timestamp,
-            Collection<android.util.EventLog.Event> output) {
-        throw new UnsupportedOperationException();
-    }
-
     /**
      * Return the "real" {@code System.out} if it's been swapped by {@code RavenwoodRuleImpl}, so
      * that we don't end up in a recursive loop.
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Log_host.java b/ravenwood/runtime-helper-src/framework/android/util/Log_host.java
similarity index 95%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Log_host.java
rename to ravenwood/runtime-helper-src/framework/android/util/Log_host.java
index f301b9c..d232ef2 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Log_host.java
+++ b/ravenwood/runtime-helper-src/framework/android/util/Log_host.java
@@ -13,9 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.platform.test.ravenwood.nativesubstitution;
+package android.util;
 
-import android.util.Log;
 import android.util.Log.Level;
 
 import com.android.internal.os.RuntimeInit;
@@ -44,7 +43,7 @@
             case Log.LOG_ID_SYSTEM: buffer = "system"; break;
             case Log.LOG_ID_CRASH: buffer = "crash"; break;
             default: buffer = "buf:" + bufID; break;
-        };
+        }
 
         final String prio;
         switch (priority) {
@@ -55,7 +54,7 @@
             case Log.ERROR: prio = "E"; break;
             case Log.ASSERT: prio = "A"; break;
             default: prio = "prio:" + priority; break;
-        };
+        }
 
         for (String s : msg.split("\\n")) {
             getRealOut().println(String.format("logd: [%s] %s %s: %s", buffer, prio, tag, s));
diff --git a/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayContainer_host.java b/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayContainer_host.java
new file mode 100644
index 0000000..c18c307
--- /dev/null
+++ b/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayContainer_host.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.os;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+public class LongArrayContainer_host {
+    private static final HashMap<Long, long[]> sInstances = new HashMap<>();
+    private static long sNextId = 1;
+
+    public static long native_init(int arrayLength) {
+        long[] array = new long[arrayLength];
+        long instanceId = sNextId++;
+        sInstances.put(instanceId, array);
+        return instanceId;
+    }
+
+    static long[] getInstance(long instanceId) {
+        return sInstances.get(instanceId);
+    }
+
+    public static void native_setValues(long instanceId, long[] values) {
+        System.arraycopy(values, 0, getInstance(instanceId), 0, values.length);
+    }
+
+    public static void native_getValues(long instanceId, long[] values) {
+        System.arraycopy(getInstance(instanceId), 0, values, 0, values.length);
+    }
+
+    public static boolean native_combineValues(long instanceId, long[] array, int[] indexMap) {
+        long[] values = getInstance(instanceId);
+
+        boolean nonZero = false;
+        Arrays.fill(array, 0);
+
+        for (int i = 0; i < values.length; i++) {
+            int index = indexMap[i];
+            if (index < 0 || index >= array.length) {
+                throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: [0, "
+                        + (array.length - 1) + "]");
+            }
+            if (values[i] != 0) {
+                array[index] += values[i];
+                nonZero = true;
+            }
+        }
+        return nonZero;
+    }
+}
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongArrayMultiStateCounter_host.java b/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayMultiStateCounter_host.java
similarity index 87%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongArrayMultiStateCounter_host.java
rename to ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayMultiStateCounter_host.java
index 0f65544..9ce8ea8 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongArrayMultiStateCounter_host.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayMultiStateCounter_host.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.platform.test.ravenwood.nativesubstitution;
+package com.android.internal.os;
 
 import android.os.BadParcelableException;
 import android.os.Parcel;
@@ -28,7 +28,7 @@
 public class LongArrayMultiStateCounter_host {
 
     /**
-     * A reimplementation of {@link com.android.internal.os.LongArrayMultiStateCounter}, only in
+     * A reimplementation of {@link LongArrayMultiStateCounter}, only in
      * Java instead of native.  The majority of the code (in C++) can be found in
      * /frameworks/native/libs/battery/MultiStateCounter.h
      */
@@ -257,50 +257,6 @@
         }
     }
 
-    public static class LongArrayContainer_host {
-        private static final HashMap<Long, long[]> sInstances = new HashMap<>();
-        private static long sNextId = 1;
-
-        public static long native_init(int arrayLength) {
-            long[] array = new long[arrayLength];
-            long instanceId = sNextId++;
-            sInstances.put(instanceId, array);
-            return instanceId;
-        }
-
-        static long[] getInstance(long instanceId) {
-            return sInstances.get(instanceId);
-        }
-
-        public static void native_setValues(long instanceId, long[] values) {
-            System.arraycopy(values, 0, getInstance(instanceId), 0, values.length);
-        }
-
-        public static void native_getValues(long instanceId, long[] values) {
-            System.arraycopy(getInstance(instanceId), 0, values, 0, values.length);
-        }
-
-        public static boolean native_combineValues(long instanceId, long[] array, int[] indexMap) {
-            long[] values = getInstance(instanceId);
-
-            boolean nonZero = false;
-            Arrays.fill(array, 0);
-
-            for (int i = 0; i < values.length; i++) {
-                int index = indexMap[i];
-                if (index < 0 || index >= array.length) {
-                    throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: [0, "
-                                                        + (array.length - 1) + "]");
-                }
-                if (values[i] != 0) {
-                    array[index] += values[i];
-                    nonZero = true;
-                }
-            }
-            return nonZero;
-        }
-    }
-
     private static final HashMap<Long, LongArrayMultiStateCounterRavenwood> sInstances =
             new HashMap<>();
     private static long sNextId = 1;
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongMultiStateCounter_host.java b/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongMultiStateCounter_host.java
similarity index 98%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongMultiStateCounter_host.java
rename to ravenwood/runtime-helper-src/framework/com/android/internal/os/LongMultiStateCounter_host.java
index 9486651..1d95aa1 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongMultiStateCounter_host.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongMultiStateCounter_host.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.platform.test.ravenwood.nativesubstitution;
+package com.android.internal.os;
 
 import android.os.BadParcelableException;
 import android.os.Parcel;
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/RavenwoodEnvironment_host.java b/ravenwood/runtime-helper-src/framework/com/android/internal/ravenwood/RavenwoodEnvironment_host.java
similarity index 86%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/RavenwoodEnvironment_host.java
rename to ravenwood/runtime-helper-src/framework/com/android/internal/ravenwood/RavenwoodEnvironment_host.java
index 58f6bbb..3bf116d 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/RavenwoodEnvironment_host.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/internal/ravenwood/RavenwoodEnvironment_host.java
@@ -13,12 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.platform.test.ravenwood.nativesubstitution;
+package com.android.internal.ravenwood;
 
+import android.os.SystemProperties_host;
 import android.platform.test.ravenwood.RavenwoodSystemProperties;
 import android.util.Log;
 
-import com.android.internal.ravenwood.RavenwoodEnvironment;
 import com.android.ravenwood.common.JvmWorkaround;
 import com.android.ravenwood.common.RavenwoodCommonUtils;
 
@@ -36,7 +36,7 @@
     /**
      * Called from {@link RavenwoodEnvironment#ensureRavenwoodInitialized()}.
      */
-    public static void nativeEnsureRavenwoodInitialized() {
+    public static void ensureRavenwoodInitialized() {
 
         // TODO Unify it with the initialization code in RavenwoodAwareTestRunnerHook.
 
@@ -63,14 +63,14 @@
     /**
      * Called from {@link RavenwoodEnvironment#getRavenwoodRuntimePath()}.
      */
-    public static String nativeGetRavenwoodRuntimePath(RavenwoodEnvironment env) {
+    public static String getRavenwoodRuntimePath(RavenwoodEnvironment env) {
         return RavenwoodCommonUtils.getRavenwoodRuntimePath();
     }
 
     /**
      * Called from {@link RavenwoodEnvironment#fromAddress(long)}.
      */
-    public static <T> T nativeFromAddress(RavenwoodEnvironment env, long address) {
+    public static <T> T fromAddress(RavenwoodEnvironment env, long address) {
         return JvmWorkaround.getInstance().fromAddress(address);
     }
 }
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java
index 0f955e7..01e19a7 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java
@@ -15,6 +15,11 @@
  */
 package com.android.platform.test.ravenwood.runtimehelper;
 
+import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING;
+
+import android.system.ErrnoException;
+import android.system.Os;
+
 import com.android.ravenwood.common.RavenwoodCommonUtils;
 
 import java.io.File;
@@ -123,6 +128,15 @@
             return;
         }
 
+        if (RAVENWOOD_VERBOSE_LOGGING) {
+            log("Force enabling verbose logging");
+            try {
+                Os.setenv("ANDROID_LOG_TAGS", "*:v", true);
+            } catch (ErrnoException e) {
+                // Shouldn't happen.
+            }
+        }
+
         // Make sure these properties are not set.
         ensurePropertyNotSet(CORE_NATIVE_CLASSES);
         ensurePropertyNotSet(ICU_DATA_PATH);
diff --git a/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java b/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
index a5c0b54..c94ef31 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
@@ -93,4 +93,8 @@
             throw new ErrnoException("pread", OsConstants.EIO, e);
         }
     }
+
+    public static void setenv(String name, String value, boolean overwrite) throws ErrnoException {
+        RavenwoodRuntimeNative.setenv(name, value, overwrite);
+    }
 }
diff --git a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
index 0d8408c..ad80d92 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
@@ -53,6 +53,9 @@
 
     private static native int nOpen(String path, int flags, int mode) throws ErrnoException;
 
+    public static native void setenv(String name, String value, boolean overwrite)
+            throws ErrnoException;
+
     public static long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException {
         return nLseek(JvmWorkaround.getInstance().getFdInt(fd), offset, whence);
     }
diff --git a/ravenwood/runtime-jni/ravenwood_runtime.cpp b/ravenwood/runtime-jni/ravenwood_runtime.cpp
index f5cb019f..c255be5 100644
--- a/ravenwood/runtime-jni/ravenwood_runtime.cpp
+++ b/ravenwood/runtime-jni/ravenwood_runtime.cpp
@@ -214,6 +214,19 @@
     return throwIfMinusOne(env, "open", TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode)));
 }
 
+static void Linux_setenv(JNIEnv* env, jobject, jstring javaName, jstring javaValue,
+        jboolean overwrite) {
+    ScopedRealUtf8Chars name(env, javaName);
+    if (name.c_str() == NULL) {
+        jniThrowNullPointerException(env);
+    }
+    ScopedRealUtf8Chars value(env, javaValue);
+    if (value.c_str() == NULL) {
+        jniThrowNullPointerException(env);
+    }
+    throwIfMinusOne(env, "setenv", setenv(name.c_str(), value.c_str(), overwrite ? 1 : 0));
+}
+
 // ---- Registration ----
 
 static const JNINativeMethod sMethods[] =
@@ -227,6 +240,7 @@
     { "lstat", "(Ljava/lang/String;)Landroid/system/StructStat;", (void*)Linux_lstat },
     { "stat", "(Ljava/lang/String;)Landroid/system/StructStat;", (void*)Linux_stat },
     { "nOpen", "(Ljava/lang/String;II)I", (void*)Linux_open },
+    { "setenv", "(Ljava/lang/String;Ljava/lang/String;Z)V", (void*)Linux_setenv },
 };
 
 extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
diff --git a/ravenwood/texts/ravenwood-standard-options.txt b/ravenwood/texts/ravenwood-standard-options.txt
index 952ab82..3ec3e3c 100644
--- a/ravenwood/texts/ravenwood-standard-options.txt
+++ b/ravenwood/texts/ravenwood-standard-options.txt
@@ -32,8 +32,11 @@
 --substitute-annotation
     android.ravenwood.annotation.RavenwoodReplace
 
---native-substitute-annotation
-    android.ravenwood.annotation.RavenwoodNativeSubstitutionClass
+--redirect-annotation
+    android.ravenwood.annotation.RavenwoodRedirect
+
+--redirection-class-annotation
+    android.ravenwood.annotation.RavenwoodRedirectionClass
 
 --class-load-hook-annotation
     android.ravenwood.annotation.RavenwoodClassLoadHook
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/adapter/RunnerRewritingAdapter.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/adapter/RunnerRewritingAdapter.kt
index eaef2cf..bd9d96d 100644
--- a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/adapter/RunnerRewritingAdapter.kt
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/adapter/RunnerRewritingAdapter.kt
@@ -302,7 +302,7 @@
         override fun visitCode() {
             visitFieldInsn(Opcodes.GETSTATIC,
                 ravenwoodTestRunnerType.internlName,
-                RavenwoodAwareTestRunner.IMPLICIT_CLASS_MIN_RULE_NAME,
+                RavenwoodAwareTestRunner.IMPLICIT_CLASS_OUTER_RULE_NAME,
                 testRuleType.desc
             )
             visitFieldInsn(Opcodes.PUTSTATIC,
@@ -313,7 +313,7 @@
 
             visitFieldInsn(Opcodes.GETSTATIC,
                 ravenwoodTestRunnerType.internlName,
-                RavenwoodAwareTestRunner.IMPLICIT_CLASS_MAX_RULE_NAME,
+                RavenwoodAwareTestRunner.IMPLICIT_CLASS_INNER_RULE_NAME,
                 testRuleType.desc
             )
             visitFieldInsn(Opcodes.PUTSTATIC,
@@ -361,7 +361,7 @@
             visitVarInsn(ALOAD, 0)
             visitFieldInsn(Opcodes.GETSTATIC,
                 ravenwoodTestRunnerType.internlName,
-                RavenwoodAwareTestRunner.IMPLICIT_INST_MIN_RULE_NAME,
+                RavenwoodAwareTestRunner.IMPLICIT_INST_OUTER_RULE_NAME,
                 testRuleType.desc
             )
             visitFieldInsn(Opcodes.PUTFIELD,
@@ -373,7 +373,7 @@
             visitVarInsn(ALOAD, 0)
             visitFieldInsn(Opcodes.GETSTATIC,
                 ravenwoodTestRunnerType.internlName,
-                RavenwoodAwareTestRunner.IMPLICIT_INST_MAX_RULE_NAME,
+                RavenwoodAwareTestRunner.IMPLICIT_INST_INNER_RULE_NAME,
                 testRuleType.desc
             )
             visitFieldInsn(Opcodes.PUTFIELD,
diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig
index ffa4841..ee3bbca 100644
--- a/services/accessibility/accessibility.aconfig
+++ b/services/accessibility/accessibility.aconfig
@@ -216,6 +216,16 @@
 }
 
 flag {
+    name: "reset_input_dispatcher_before_first_touch_exploration"
+    namespace: "accessibility"
+    description: "Resets InputDispatcher state by sending ACTION_CANCEL before the first TouchExploration hover events"
+    bug: "364408887"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
     name: "scan_packages_without_lock"
     namespace: "accessibility"
     description: "Scans packages for accessibility service/activity info without holding the A11yMS lock"
@@ -228,6 +238,7 @@
     description: "Sends accessibility events in TouchExplorer#onAccessibilityEvent based on internal state to keep it consistent. This reduces test flakiness."
     bug: "295575684"
 }
+
 flag {
     name: "send_hover_events_based_on_event_stream"
     namespace: "accessibility"
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index 04b42e4..0ed239e 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -1613,6 +1613,19 @@
                 dispatchGesture(gestureEvent);
             }
             if (!mEvents.isEmpty() && !mRawEvents.isEmpty()) {
+                if (Flags.resetInputDispatcherBeforeFirstTouchExploration()
+                        && !mState.hasResetInputDispatcherState()) {
+                    // Cancel any possible ongoing touch gesture from before touch exploration
+                    // started. This clears out the InputDispatcher event stream state so that it
+                    // is ready to accept new injected HOVER events.
+                    mDispatcher.sendMotionEvent(
+                            mEvents.get(0),
+                            ACTION_CANCEL,
+                            mRawEvents.get(0),
+                            mPointerIdBits,
+                            mPolicyFlags);
+                    setHasResetInputDispatcherState(true);
+                }
                 // Deliver a down event.
                 mDispatcher.sendMotionEvent(
                         mEvents.get(0),
@@ -1773,4 +1786,9 @@
                 + ", mDraggingPointerId: " + mDraggingPointerId
                 + " }";
     }
+
+    @VisibleForTesting
+    void setHasResetInputDispatcherState(boolean value) {
+        mState.setHasResetInputDispatcherState(value);
+    }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
index e13994e..f15b8ee 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
@@ -86,6 +86,7 @@
     private MotionEvent mLastInjectedHoverEvent;
     // The last injected hover event used for performing clicks.
     private MotionEvent mLastInjectedHoverEventForClick;
+    private boolean mHasResetInputDispatcherState;
     // The time of the last injected down.
     private long mLastInjectedDownEventTime;
     // Keep track of which pointers sent to the system are down.
@@ -361,6 +362,14 @@
         return mLastInjectedDownEventTime;
     }
 
+    boolean hasResetInputDispatcherState() {
+        return mHasResetInputDispatcherState;
+    }
+
+    void setHasResetInputDispatcherState(boolean value) {
+        mHasResetInputDispatcherState = value;
+    }
+
     public int getLastTouchedWindowId() {
         return mLastTouchedWindowId;
     }
diff --git a/services/appfunctions/TEST_MAPPING b/services/appfunctions/TEST_MAPPING
new file mode 100644
index 0000000..c7f5eee
--- /dev/null
+++ b/services/appfunctions/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "postsubmit": [
+    {
+      "name": "FrameworksAppFunctionsTests"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java b/services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java
new file mode 100644
index 0000000..0947238
--- /dev/null
+++ b/services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2024 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.appfunctions;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchBatchResult;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchManager.SearchContext;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.AppSearchSession;
+import android.app.appsearch.BatchResultCallback;
+import android.app.appsearch.GenericDocument;
+import android.app.appsearch.GetByDocumentIdRequest;
+import android.app.appsearch.GetSchemaResponse;
+import android.app.appsearch.PutDocumentsRequest;
+import android.app.appsearch.SearchResult;
+import android.app.appsearch.SearchResults;
+import android.app.appsearch.SearchSpec;
+import android.app.appsearch.SetSchemaRequest;
+import android.app.appsearch.SetSchemaResponse;
+import android.util.Slog;
+
+import com.android.internal.infra.AndroidFuture;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+/** A future API wrapper of {@link AppSearchSession} APIs. */
+public class FutureAppSearchSession implements Closeable {
+    private static final String TAG = FutureAppSearchSession.class.getSimpleName();
+    private final Executor mExecutor;
+    private final AndroidFuture<AppSearchResult<AppSearchSession>> mSettableSessionFuture;
+
+    public FutureAppSearchSession(
+            @NonNull AppSearchManager appSearchManager,
+            @NonNull Executor executor,
+            @NonNull SearchContext appSearchContext) {
+        Objects.requireNonNull(appSearchManager);
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(appSearchContext);
+
+        mExecutor = executor;
+        mSettableSessionFuture = new AndroidFuture<>();
+        appSearchManager.createSearchSession(
+                appSearchContext, mExecutor, mSettableSessionFuture::complete);
+    }
+
+    /** Converts a failed app search result codes into an exception. */
+    @NonNull
+    public static Exception failedResultToException(@NonNull AppSearchResult<?> appSearchResult) {
+        return switch (appSearchResult.getResultCode()) {
+            case AppSearchResult.RESULT_INVALID_ARGUMENT ->
+                    new IllegalArgumentException(appSearchResult.getErrorMessage());
+            case AppSearchResult.RESULT_IO_ERROR ->
+                    new IOException(appSearchResult.getErrorMessage());
+            case AppSearchResult.RESULT_SECURITY_ERROR ->
+                    new SecurityException(appSearchResult.getErrorMessage());
+            default -> new IllegalStateException(appSearchResult.getErrorMessage());
+        };
+    }
+
+    private AndroidFuture<AppSearchSession> getSessionAsync() {
+        return mSettableSessionFuture.thenApply(
+                result -> {
+                    if (result.isSuccess()) {
+                        return result.getResultValue();
+                    } else {
+                        throw new RuntimeException(failedResultToException(result));
+                    }
+                });
+    }
+
+    /** Gets the schema for a given app search session. */
+    public AndroidFuture<GetSchemaResponse> getSchema() {
+        return getSessionAsync()
+                .thenCompose(
+                        session -> {
+                            AndroidFuture<AppSearchResult<GetSchemaResponse>>
+                                    settableSchemaResponse = new AndroidFuture<>();
+                            session.getSchema(mExecutor, settableSchemaResponse::complete);
+                            return settableSchemaResponse.thenApply(
+                                    result -> {
+                                        if (result.isSuccess()) {
+                                            return result.getResultValue();
+                                        } else {
+                                            throw new RuntimeException(
+                                                    failedResultToException(result));
+                                        }
+                                    });
+                        });
+    }
+
+    /** Sets the schema for a given app search session. */
+    public AndroidFuture<SetSchemaResponse> setSchema(@NonNull SetSchemaRequest setSchemaRequest) {
+        return getSessionAsync()
+                .thenCompose(
+                        session -> {
+                            AndroidFuture<AppSearchResult<SetSchemaResponse>>
+                                    settableSchemaResponse = new AndroidFuture<>();
+                            session.setSchema(
+                                    setSchemaRequest,
+                                    mExecutor,
+                                    mExecutor,
+                                    settableSchemaResponse::complete);
+                            return settableSchemaResponse.thenApply(
+                                    result -> {
+                                        if (result.isSuccess()) {
+                                            return result.getResultValue();
+                                        } else {
+                                            throw new RuntimeException(
+                                                    failedResultToException(result));
+                                        }
+                                    });
+                        });
+    }
+
+    /** Indexes documents into the AppSearchSession database. */
+    public AndroidFuture<AppSearchBatchResult<String, Void>> put(
+            @NonNull PutDocumentsRequest putDocumentsRequest) {
+        return getSessionAsync()
+                .thenCompose(
+                        session -> {
+                            AndroidFuture<AppSearchBatchResult<String, Void>> batchResultFuture =
+                                    new AndroidFuture<>();
+
+                            session.put(
+                                    putDocumentsRequest, mExecutor, batchResultFuture::complete);
+                            return batchResultFuture;
+                        });
+    }
+
+    /**
+     * Retrieves documents from the open AppSearchSession that match a given query string and type
+     * of search provided.
+     */
+    public AndroidFuture<FutureSearchResults> search(
+            @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
+        return getSessionAsync()
+                .thenApply(session -> session.search(queryExpression, searchSpec))
+                .thenApply(result -> new FutureSearchResults(result, mExecutor));
+    }
+
+    @Override
+    public void close() throws IOException {
+        try {
+            getSessionAsync().get().close();
+        } catch (Exception ex) {
+            Slog.e(TAG, "Failed to close app search session", ex);
+        }
+    }
+
+    /** A future API wrapper of {@link android.app.appsearch.SearchResults}. */
+    public static class FutureSearchResults {
+        private final SearchResults mSearchResults;
+        private final Executor mExecutor;
+
+        public FutureSearchResults(
+                @NonNull SearchResults searchResults, @NonNull Executor executor) {
+            mSearchResults = Objects.requireNonNull(searchResults);
+            mExecutor = Objects.requireNonNull(executor);
+        }
+
+        public AndroidFuture<List<SearchResult>> getNextPage() {
+            AndroidFuture<AppSearchResult<List<SearchResult>>> nextPageFuture =
+                    new AndroidFuture<>();
+
+            mSearchResults.getNextPage(mExecutor, nextPageFuture::complete);
+            return nextPageFuture.thenApply(
+                    result -> {
+                        if (result.isSuccess()) {
+                            return result.getResultValue();
+                        } else {
+                            throw new RuntimeException(failedResultToException(result));
+                        }
+                    });
+        }
+    }
+
+    /** A future API to retrieve a document by its id from the local AppSearch session. */
+    public AndroidFuture<GenericDocument> getByDocumentId(
+            @NonNull String documentId, @NonNull String namespace) {
+        Objects.requireNonNull(documentId);
+        Objects.requireNonNull(namespace);
+
+        GetByDocumentIdRequest request =
+                new GetByDocumentIdRequest.Builder(namespace)
+                        .addIds(documentId)
+                        .build();
+        return getSessionAsync()
+                .thenCompose(
+                        session -> {
+                            AndroidFuture<AppSearchBatchResult<String, GenericDocument>>
+                                    batchResultFuture = new AndroidFuture<>();
+                            session.getByDocumentId(
+                                    request,
+                                    mExecutor,
+                                    new BatchResultCallbackAdapter<>(batchResultFuture));
+
+                            return batchResultFuture.thenApply(
+                                    batchResult ->
+                                            getGenericDocumentFromBatchResult(
+                                                    batchResult, documentId));
+                        });
+    }
+
+    private static GenericDocument getGenericDocumentFromBatchResult(
+            AppSearchBatchResult<String, GenericDocument> result, String documentId) {
+        if (result.isSuccess()) {
+            return result.getSuccesses().get(documentId);
+        }
+        throw new IllegalArgumentException("No document in the result for id: " + documentId);
+    }
+
+    private static final class BatchResultCallbackAdapter<K, V>
+            implements BatchResultCallback<K, V> {
+        private final AndroidFuture<AppSearchBatchResult<K, V>> mFuture;
+
+        BatchResultCallbackAdapter(AndroidFuture<AppSearchBatchResult<K, V>> future) {
+            mFuture = future;
+        }
+
+        @Override
+        public void onResult(@NonNull AppSearchBatchResult<K, V> result) {
+            mFuture.complete(result);
+        }
+
+        @Override
+        public void onSystemError(Throwable t) {
+            mFuture.completeExceptionally(t);
+        }
+    }
+}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/FutureGlobalSearchSession.java b/services/appfunctions/java/com/android/server/appfunctions/FutureGlobalSearchSession.java
new file mode 100644
index 0000000..0c22624
--- /dev/null
+++ b/services/appfunctions/java/com/android/server/appfunctions/FutureGlobalSearchSession.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 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.appfunctions;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.GlobalSearchSession;
+import android.app.appsearch.exceptions.AppSearchException;
+import android.app.appsearch.observer.ObserverCallback;
+import android.app.appsearch.observer.ObserverSpec;
+import android.util.Slog;
+
+import com.android.internal.infra.AndroidFuture;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.Executor;
+
+/** A wrapper around {@link GlobalSearchSession} that provides a future-based API. */
+public class FutureGlobalSearchSession implements Closeable {
+    private static final String TAG = FutureGlobalSearchSession.class.getSimpleName();
+    private final Executor mExecutor;
+    private final AndroidFuture<AppSearchResult<GlobalSearchSession>> mSettableSessionFuture;
+
+    public FutureGlobalSearchSession(
+            @NonNull AppSearchManager appSearchManager, @NonNull Executor executor) {
+        this.mExecutor = executor;
+        mSettableSessionFuture = new AndroidFuture<>();
+        appSearchManager.createGlobalSearchSession(mExecutor, mSettableSessionFuture::complete);
+    }
+
+    private AndroidFuture<GlobalSearchSession> getSessionAsync() {
+        return mSettableSessionFuture.thenApply(
+                result -> {
+                    if (result.isSuccess()) {
+                        return result.getResultValue();
+                    } else {
+                        throw new RuntimeException(
+                                FutureAppSearchSession.failedResultToException(result));
+                    }
+                });
+    }
+
+    /**
+     * Registers an observer callback for the given target package name.
+     *
+     * @param targetPackageName The package name of the target app.
+     * @param spec The observer spec.
+     * @param executor The executor to run the observer callback on.
+     * @param observer The observer callback to register.
+     * @return A future that completes once the observer is registered.
+     */
+    public AndroidFuture<Void> registerObserverCallbackAsync(
+            String targetPackageName,
+            ObserverSpec spec,
+            Executor executor,
+            ObserverCallback observer) {
+        return getSessionAsync()
+                .thenCompose(
+                        session -> {
+                            try {
+                                session.registerObserverCallback(
+                                        targetPackageName, spec, executor, observer);
+                                return AndroidFuture.completedFuture(null);
+                            } catch (AppSearchException e) {
+                                throw new RuntimeException(e);
+                            }
+                        });
+    }
+
+    @Override
+    public void close() throws IOException {
+        try {
+            getSessionAsync().get().close();
+        } catch (Exception ex) {
+            Slog.e(TAG, "Failed to close global search session", ex);
+        }
+    }
+}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncAdapter.java b/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncAdapter.java
new file mode 100644
index 0000000..be5770b
--- /dev/null
+++ b/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncAdapter.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2024 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.appfunctions;
+
+import android.annotation.NonNull;
+import android.annotation.WorkerThread;
+import android.app.appsearch.SearchResult;
+import android.app.appsearch.SearchSpec;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.appfunctions.FutureAppSearchSession.FutureSearchResults;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+
+/**
+ * This class implements helper methods for synchronously interacting with AppSearch while
+ * synchronizing AppFunction runtime and static metadata.
+ */
+public class MetadataSyncAdapter {
+    private final FutureAppSearchSession mFutureAppSearchSession;
+    private final Executor mSyncExecutor;
+
+    public MetadataSyncAdapter(
+            @NonNull Executor syncExecutor,
+            @NonNull FutureAppSearchSession futureAppSearchSession) {
+        mSyncExecutor = Objects.requireNonNull(syncExecutor);
+        mFutureAppSearchSession = Objects.requireNonNull(futureAppSearchSession);
+    }
+
+    /**
+     * This method returns a map of package names to a set of function ids that are in the static
+     * metadata but not in the runtime metadata.
+     *
+     * @param staticPackageToFunctionMap A map of package names to a set of function ids from the
+     *     static metadata.
+     * @param runtimePackageToFunctionMap A map of package names to a set of function ids from the
+     *     runtime metadata.
+     * @return A map of package names to a set of function ids that are in the static metadata but
+     *     not in the runtime metadata.
+     */
+    @NonNull
+    @VisibleForTesting
+    static ArrayMap<String, ArraySet<String>> getAddedFunctionsDiffMap(
+            ArrayMap<String, ArraySet<String>> staticPackageToFunctionMap,
+            ArrayMap<String, ArraySet<String>> runtimePackageToFunctionMap) {
+        return getFunctionsDiffMap(staticPackageToFunctionMap, runtimePackageToFunctionMap);
+    }
+
+    /**
+     * This method returns a map of package names to a set of function ids that are in the runtime
+     * metadata but not in the static metadata.
+     *
+     * @param staticPackageToFunctionMap A map of package names to a set of function ids from the
+     *     static metadata.
+     * @param runtimePackageToFunctionMap A map of package names to a set of function ids from the
+     *     runtime metadata.
+     * @return A map of package names to a set of function ids that are in the runtime metadata but
+     *     not in the static metadata.
+     */
+    @NonNull
+    @VisibleForTesting
+    static ArrayMap<String, ArraySet<String>> getRemovedFunctionsDiffMap(
+            ArrayMap<String, ArraySet<String>> staticPackageToFunctionMap,
+            ArrayMap<String, ArraySet<String>> runtimePackageToFunctionMap) {
+        return getFunctionsDiffMap(runtimePackageToFunctionMap, staticPackageToFunctionMap);
+    }
+
+    @NonNull
+    private static ArrayMap<String, ArraySet<String>> getFunctionsDiffMap(
+            ArrayMap<String, ArraySet<String>> packageToFunctionMapA,
+            ArrayMap<String, ArraySet<String>> packageToFunctionMapB) {
+        ArrayMap<String, ArraySet<String>> diffMap = new ArrayMap<>();
+        for (String packageName : packageToFunctionMapA.keySet()) {
+            if (!packageToFunctionMapB.containsKey(packageName)) {
+                diffMap.put(packageName, packageToFunctionMapA.get(packageName));
+                continue;
+            }
+            ArraySet<String> diffFunctions = new ArraySet<>();
+            for (String functionId :
+                    Objects.requireNonNull(packageToFunctionMapA.get(packageName))) {
+                if (!Objects.requireNonNull(packageToFunctionMapB.get(packageName))
+                        .contains(functionId)) {
+                    diffFunctions.add(functionId);
+                }
+            }
+            if (!diffFunctions.isEmpty()) {
+                diffMap.put(packageName, diffFunctions);
+            }
+        }
+        return diffMap;
+    }
+
+    /**
+     * This method returns a map of package names to a set of function ids.
+     *
+     * @param queryExpression The query expression to use when searching for AppFunction metadata.
+     * @param metadataSearchSpec The search spec to use when searching for AppFunction metadata.
+     * @return A map of package names to a set of function ids.
+     * @throws ExecutionException If the future search results fail to execute.
+     * @throws InterruptedException If the future search results are interrupted.
+     */
+    @NonNull
+    @VisibleForTesting
+    @WorkerThread
+    ArrayMap<String, ArraySet<String>> getPackageToFunctionIdMap(
+            @NonNull String queryExpression,
+            @NonNull SearchSpec metadataSearchSpec,
+            @NonNull String propertyFunctionId,
+            @NonNull String propertyPackageName)
+            throws ExecutionException, InterruptedException {
+        ArrayMap<String, ArraySet<String>> packageToFunctionIds = new ArrayMap<>();
+        FutureSearchResults futureSearchResults =
+                mFutureAppSearchSession.search(queryExpression, metadataSearchSpec).get();
+        List<SearchResult> searchResultsList = futureSearchResults.getNextPage().get();
+        // TODO(b/357551503): This could be expensive if we have more functions
+        while (!searchResultsList.isEmpty()) {
+            for (SearchResult searchResult : searchResultsList) {
+                String packageName =
+                        searchResult.getGenericDocument().getPropertyString(propertyPackageName);
+                String functionId =
+                        searchResult.getGenericDocument().getPropertyString(propertyFunctionId);
+                packageToFunctionIds
+                        .computeIfAbsent(packageName, k -> new ArraySet<>())
+                        .add(functionId);
+            }
+            searchResultsList = futureSearchResults.getNextPage().get();
+        }
+        return packageToFunctionIds;
+    }
+}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCaller.java b/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCaller.java
index 98903ae..58597c3 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCaller.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCaller.java
@@ -25,7 +25,6 @@
  * services are properly unbound after the operation completes or a timeout occurs.
  *
  * @param <T> Class of wrapped service.
- * @hide
  */
 public interface RemoteServiceCaller<T> {
 
diff --git a/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCallerImpl.java b/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCallerImpl.java
index 0e18705..eea17ee 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCallerImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCallerImpl.java
@@ -34,7 +34,6 @@
  * Context#bindService}.
  *
  * @param <T> Class of wrapped service.
- * @hide
  */
 public class RemoteServiceCallerImpl<T> implements RemoteServiceCaller<T> {
     private static final String TAG = "AppFunctionsServiceCall";
diff --git a/services/appfunctions/java/com/android/server/appfunctions/SyncAppSearchCallHelper.java b/services/appfunctions/java/com/android/server/appfunctions/SyncAppSearchCallHelper.java
deleted file mode 100644
index e56f81f0..0000000
--- a/services/appfunctions/java/com/android/server/appfunctions/SyncAppSearchCallHelper.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2024 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.appfunctions;
-
-import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-import android.app.appsearch.AppSearchManager;
-import android.app.appsearch.AppSearchManager.SearchContext;
-import android.app.appsearch.AppSearchResult;
-import android.app.appsearch.AppSearchSession;
-import android.app.appsearch.GetSchemaResponse;
-import android.app.appsearch.SetSchemaRequest;
-import android.app.appsearch.SetSchemaResponse;
-import android.util.Slog;
-
-import com.android.internal.infra.AndroidFuture;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-
-/**
- * Helper class for interacting with a system server local appsearch session asynchronously.
- *
- * <p>Converts the AppSearch Callback API to {@link AndroidFuture}.
- */
-@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
-public class SyncAppSearchCallHelper implements Closeable {
-    private static final String TAG = SyncAppSearchCallHelper.class.getSimpleName();
-    private final Executor mExecutor;
-    private final AppSearchManager mAppSearchManager;
-    private final AndroidFuture<AppSearchResult<AppSearchSession>> mSettableSessionFuture;
-
-    public SyncAppSearchCallHelper(
-            @NonNull AppSearchManager appSearchManager,
-            @NonNull Executor executor,
-            @NonNull SearchContext appSearchContext) {
-        Objects.requireNonNull(appSearchManager);
-        Objects.requireNonNull(executor);
-        Objects.requireNonNull(appSearchContext);
-
-        mExecutor = executor;
-        mAppSearchManager = appSearchManager;
-        mSettableSessionFuture = new AndroidFuture<>();
-        mAppSearchManager.createSearchSession(
-                appSearchContext, mExecutor, mSettableSessionFuture::complete);
-    }
-
-    /** Converts a failed app search result codes into an exception. */
-    @NonNull
-    private static Exception failedResultToException(@NonNull AppSearchResult appSearchResult) {
-        return switch (appSearchResult.getResultCode()) {
-            case AppSearchResult.RESULT_INVALID_ARGUMENT ->
-                    new IllegalArgumentException(appSearchResult.getErrorMessage());
-            case AppSearchResult.RESULT_IO_ERROR ->
-                    new IOException(appSearchResult.getErrorMessage());
-            case AppSearchResult.RESULT_SECURITY_ERROR ->
-                    new SecurityException(appSearchResult.getErrorMessage());
-            default -> new IllegalStateException(appSearchResult.getErrorMessage());
-        };
-    }
-
-    private AndroidFuture<AppSearchSession> getSessionAsync() {
-        return mSettableSessionFuture.thenApply(
-                result -> {
-                    if (result.isSuccess()) {
-                        return result.getResultValue();
-                    } else {
-                        throw new RuntimeException(failedResultToException(result));
-                    }
-                });
-    }
-
-    /** Gets the schema for a given app search session. */
-    public AndroidFuture<GetSchemaResponse> getSchema() {
-        return getSessionAsync()
-                .thenComposeAsync(
-                        session -> {
-                            AndroidFuture<AppSearchResult<GetSchemaResponse>>
-                                    settableSchemaResponse = new AndroidFuture<>();
-                            session.getSchema(mExecutor, settableSchemaResponse::complete);
-                            return settableSchemaResponse.thenApply(
-                                    result -> {
-                                        if (result.isSuccess()) {
-                                            return result.getResultValue();
-                                        } else {
-                                            throw new RuntimeException(
-                                                    failedResultToException(result));
-                                        }
-                                    });
-                        },
-                        mExecutor);
-    }
-
-    /** Sets the schema for a given app search session. */
-    public AndroidFuture<SetSchemaResponse> setSchema(@NonNull SetSchemaRequest setSchemaRequest) {
-        return getSessionAsync()
-                .thenComposeAsync(
-                        session -> {
-                            AndroidFuture<AppSearchResult<SetSchemaResponse>>
-                                    settableSchemaResponse = new AndroidFuture<>();
-                            session.setSchema(
-                                    setSchemaRequest,
-                                    mExecutor,
-                                    mExecutor,
-                                    settableSchemaResponse::complete);
-                            return settableSchemaResponse.thenApply(
-                                    result -> {
-                                        if (result.isSuccess()) {
-                                            return result.getResultValue();
-                                        } else {
-                                            throw new RuntimeException(
-                                                    failedResultToException(result));
-                                        }
-                                    });
-                        },
-                        mExecutor);
-    }
-
-    @Override
-    public void close() throws IOException {
-        try {
-            getSessionAsync().get().close();
-        } catch (Exception ex) {
-            Slog.e(TAG, "Failed to close app search session", ex);
-        }
-    }
-}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 3068398..b53bf98 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -220,6 +220,15 @@
     // See {@link Provider#pendingDeletedWidgetIds}.
     private static final String PENDING_DELETED_IDS_ATTR = "pending_deleted_ids";
 
+    // Hard limit of number of hosts an app can create, note that the app that hosts the widgets
+    // can have multiple instances of {@link AppWidgetHost}, typically in respect to different
+    // surfaces in the host app.
+    // @see AppWidgetHost
+    // @see AppWidgetHost#mHostId
+    private static final int MAX_NUMBER_OF_HOSTS_PER_PACKAGE = 20;
+    // Hard limit of number of widgets can be pinned by a host.
+    private static final int MAX_NUMBER_OF_WIDGETS_PER_HOST = 200;
+
     // Handles user and package related broadcasts.
     // See {@link #registerBroadcastReceiver}
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -2284,7 +2293,7 @@
         if (host != null) {
             return host;
         }
-
+        ensureHostCountBeforeAddLocked(id);
         host = new Host();
         host.id = id;
         mHosts.add(host);
@@ -2292,6 +2301,24 @@
         return host;
     }
 
+    /**
+     * Ensures that the number of hosts for a package is less than the maximum number of hosts per
+     * package. If the number of hosts is greater than the maximum number of hosts per package, then
+     * removes the oldest host.
+     */
+    private void ensureHostCountBeforeAddLocked(@NonNull final HostId hostId) {
+        final List<Host> hosts = new ArrayList<>();
+        for (Host host : mHosts) {
+            if (host.id.uid == hostId.uid
+                    && host.id.packageName.equals(hostId.packageName)) {
+                hosts.add(host);
+            }
+        }
+        while (hosts.size() >= MAX_NUMBER_OF_HOSTS_PER_PACKAGE) {
+            deleteHostLocked(hosts.remove(0));
+        }
+    }
+
     private void deleteHostLocked(Host host) {
         if (DEBUG) {
             Slog.i(TAG, "deleteHostLocked() " + host);
@@ -2377,6 +2404,11 @@
             }
 
             @Override
+            public void onNullBinding(ComponentName name) {
+                mContext.unbindService(this);
+            }
+
+            @Override
             public void onServiceDisconnected(ComponentName name) {
                 // Do nothing
             }
@@ -2524,6 +2556,11 @@
                             }
 
                             @Override
+                            public void onNullBinding(ComponentName name) {
+                                mContext.unbindService(this);
+                            }
+
+                            @Override
                             public void onServiceDisconnected(android.content.ComponentName name) {
                                 // Do nothing
                             }
@@ -3582,12 +3619,33 @@
         if (DEBUG) {
             Slog.i(TAG, "addWidgetLocked() " + widget);
         }
+        ensureWidgetCountBeforeAddLocked(widget);
         mWidgets.add(widget);
 
         onWidgetProviderAddedOrChangedLocked(widget);
     }
 
     /**
+     * Ensures that the widget count for the widget's host is not greater than the maximum
+     * number of widgets per host. If the count is greater than the maximum, removes oldest widgets
+     * from the host until the count is less than or equal to the maximum.
+     */
+    private void ensureWidgetCountBeforeAddLocked(@NonNull final Widget widget) {
+        if (widget.host == null || widget.host.id == null) {
+            return;
+        }
+        final List<Widget> widgetsInSameHost = new ArrayList<>();
+        for (Widget w : mWidgets) {
+            if (w.host != null && widget.host.id.equals(w.host.id)) {
+                widgetsInSameHost.add(w);
+            }
+        }
+        while (widgetsInSameHost.size() >= MAX_NUMBER_OF_WIDGETS_PER_HOST) {
+            removeWidgetLocked(widgetsInSameHost.remove(0));
+        }
+    }
+
+    /**
      * Checks if the provider is assigned and updates the mWidgetPackages to track packages
      * that have bound widgets.
      */
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index d4f729c..3666524 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1516,9 +1516,8 @@
                 serviceName, FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__START);
         mAm.mBatteryStatsService.noteServiceStartRunning(uid, packageName, serviceName);
         final ProcessRecord hostApp = r.app;
-        final boolean wasStopped = hostApp == null ? wasStopped(r) : false;
-        final boolean firstLaunch =
-                hostApp == null ? !mAm.wasPackageEverLaunched(r.packageName, r.userId) : false;
+        final boolean wasStopped = hostApp == null ? r.appInfo.isStopped() : false;
+        final boolean firstLaunch = hostApp == null ? r.appInfo.isNotLaunched() : false;
 
         String error = bringUpServiceLocked(r, service.getFlags(), callerFg,
                 false /* whileRestarting */,
@@ -4308,9 +4307,8 @@
                         true, UNKNOWN_ADJ);
             }
 
-            final boolean wasStopped = hostApp == null ? wasStopped(s) : false;
-            final boolean firstLaunch =
-                    hostApp == null ? !mAm.wasPackageEverLaunched(s.packageName, s.userId) : false;
+            final boolean wasStopped = hostApp == null ? s.appInfo.isStopped() : false;
+            final boolean firstLaunch = hostApp == null ? s.appInfo.isNotLaunched() : false;
 
             boolean needOomAdj = false;
             if (c.hasFlag(Context.BIND_AUTO_CREATE)) {
@@ -9350,8 +9348,4 @@
         return mCachedDeviceProvisioningPackage != null
                 && mCachedDeviceProvisioningPackage.equals(packageName);
     }
-
-    private boolean wasStopped(ServiceRecord serviceRecord) {
-        return (serviceRecord.appInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0;
-    }
 }
diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java
index 1b00cec..6aadcdc 100644
--- a/services/core/java/com/android/server/am/AppStartInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java
@@ -33,6 +33,7 @@
 import android.content.pm.PackageManager;
 import android.icu.text.SimpleDateFormat;
 import android.os.Binder;
+import android.os.Debug;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBinder.DeathRecipient;
@@ -495,6 +496,10 @@
 
     private void addBaseFieldsFromProcessRecord(ApplicationStartInfo start, ProcessRecord app) {
         if (app == null) {
+            if (DEBUG) {
+                Slog.w(TAG,
+                        "app is null in addBaseFieldsFromProcessRecord: " + Debug.getCallers(4));
+            }
             return;
         }
         final int definingUid = app.getHostingRecord() != null
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 8fe33d1..9e4666c 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -1005,13 +1005,10 @@
         final ApplicationInfo info = ((ResolveInfo) receiver).activityInfo.applicationInfo;
         final ComponentName component = ((ResolveInfo) receiver).activityInfo.getComponentName();
 
-        if ((info.flags & ApplicationInfo.FLAG_STOPPED) != 0) {
-            queue.setActiveWasStopped(true);
-        }
-        final int intentFlags = r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND;
-        final boolean firstLaunch = !mService.wasPackageEverLaunched(info.packageName, r.userId);
-        queue.setActiveFirstLaunch(firstLaunch);
+        queue.setActiveWasStopped(info.isStopped());
+        queue.setActiveFirstLaunch(info.isNotLaunched());
 
+        final int intentFlags = r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND;
         final HostingRecord hostingRecord = new HostingRecord(HostingRecord.HOSTING_TYPE_BROADCAST,
                 component, r.intent.getAction(), r.getHostingRecordTriggerType());
         final boolean isActivityCapable = (r.options != null
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 8f52f67..416c110 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -86,7 +86,6 @@
 
 import dalvik.annotation.optimization.NeverCompile;
 
-import java.io.FileReader;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -2318,6 +2317,7 @@
                         Slog.d(TAG_AM, "Skipping freeze because process is marked "
                                 + "should not be frozen");
                     }
+                    reportProcessFreezableChangedLocked(proc);
                     return;
                 }
 
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 1314521..da40826 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -554,13 +554,11 @@
                                     callingProcessState, proc.mState.getCurProcState(),
                                     false, 0L);
                         } else {
-                            final boolean stopped =
-                                    (cpr.appInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0;
+                            final boolean stopped = cpr.appInfo.isStopped();
                             final int packageState = stopped
                                     ? PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_STOPPED
                                     : PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL;
-                            final boolean firstLaunch = !mService.wasPackageEverLaunched(
-                                    cpi.packageName, userId);
+                            final boolean firstLaunch = cpr.appInfo.isNotLaunched();
                             checkTime(startTime, "getContentProviderImpl: before start process");
                             proc = mService.startProcessLocked(
                                     cpi.processName, cpr.appInfo, false, 0,
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index bb0c24b..5b4e573 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -3394,24 +3394,33 @@
                 hostingRecord.getDefiningUid(), hostingRecord.getDefiningProcessName());
         final ProcessStateRecord state = r.mState;
 
-        final boolean wasStopped = (info.flags & ApplicationInfo.FLAG_STOPPED) != 0;
+        final boolean wasStopped = info.isStopped();
         // Check if we should mark the processrecord for first launch after force-stopping
         if (wasStopped) {
+            boolean wasEverLaunched;
+            if (android.app.Flags.useAppInfoNotLaunched()) {
+                wasEverLaunched = !info.isNotLaunched();
+            } else {
+                wasEverLaunched = mService.getPackageManagerInternal()
+                        .wasPackageEverLaunched(r.getApplicationInfo().packageName, r.userId);
+            }
             // Check if the hosting record is for an activity or not. Since the stopped
             // state tracking is handled differently to avoid WM calling back into AM,
             // store the state in the correct record
             if (hostingRecord.isTypeActivity()) {
-                final boolean wasPackageEverLaunched = mService
-                        .wasPackageEverLaunched(r.getApplicationInfo().packageName, r.userId);
                 // If the package was launched in the past but is currently stopped, only then
                 // should it be considered as force-stopped.
-                @WindowProcessController.StoppedState int stoppedState = wasPackageEverLaunched
+                @WindowProcessController.StoppedState int stoppedState = wasEverLaunched
                         ? STOPPED_STATE_FORCE_STOPPED
                         : STOPPED_STATE_FIRST_LAUNCH;
                 r.getWindowProcessController().setStoppedState(stoppedState);
             } else {
-                r.setWasForceStopped(true);
-                // first launch is computed just before logging, for non-activity types
+                if (android.app.Flags.useAppInfoNotLaunched()) {
+                    // If it was launched before, then it must be a force-stop
+                    r.setWasForceStopped(wasEverLaunched);
+                } else {
+                    r.setWasForceStopped(true);
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 2937307..99c3eca 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -139,6 +139,7 @@
     static final String[] sDeviceConfigAconfigScopes = new String[] {
         "accessibility",
         "android_core_networking",
+        "android_health_services",
         "android_sdk",
         "android_stylus",
         "aoc",
@@ -235,7 +236,6 @@
         "wear_connectivity",
         "wear_esim_carriers",
         "wear_frameworks",
-        "wear_health_services",
         "wear_media",
         "wear_offload",
         "wear_security",
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4e24cf3..6daf0d0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -285,7 +285,6 @@
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.concurrent.CancellationException;
-import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
@@ -411,6 +410,9 @@
     /** The controller for the volume UI. */
     private final VolumeController mVolumeController = new VolumeController();
 
+    /** Used only for testing to enable/disable the long press timeout volume actions. */
+    private final AtomicBoolean mVolumeControllerLongPressEnabled = new AtomicBoolean(true);
+
     // sendMsg() flags
     /** If the msg is already queued, replace it with this one. */
     private static final int SENDMSG_REPLACE = 0;
@@ -12554,6 +12556,15 @@
         if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
     }
 
+    /** @see AudioManager#setVolumeControllerLongPressTimeoutEnabled(boolean) */
+    @Override
+    @android.annotation.EnforcePermission(MODIFY_AUDIO_SETTINGS_PRIVILEGED)
+    public void setVolumeControllerLongPressTimeoutEnabled(boolean enable) {
+        super.setVolumeControllerLongPressTimeoutEnabled_enforcePermission();
+        mVolumeControllerLongPressEnabled.set(enable);
+        Log.i(TAG, "Volume controller long press timeout enabled: " + enable);
+    }
+
     @Override
     public void setVolumePolicy(VolumePolicy policy) {
         enforceVolumeController("set volume policy");
@@ -12632,7 +12643,9 @@
                 if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
                     // UI is not visible yet, adjustment is ignored
                     if (mNextLongPress < now) {
-                        mNextLongPress = now + mLongPressTimeout;
+                        mNextLongPress =
+                                now + (mVolumeControllerLongPressEnabled.get() ? mLongPressTimeout
+                                        : 0);
                     }
                     suppress = true;
                 } else if (mNextLongPress > 0) {  // in a long-press
@@ -12699,11 +12712,6 @@
             if (mController == null)
                 return;
             try {
-                // TODO: remove this when deprecating STREAM_BLUETOOTH_SCO
-                if (isStreamBluetoothSco(streamType)) {
-                    // TODO: notify both sco and voice_call about volume changes
-                    streamType = AudioSystem.STREAM_BLUETOOTH_SCO;
-                }
                 mController.volumeChanged(streamType, flags);
             } catch (RemoteException e) {
                 Log.w(TAG, "Error calling volumeChanged", e);
@@ -14714,6 +14722,7 @@
     @Override
     /** @see AudioManager#permissionUpdateBarrier() */
     public void permissionUpdateBarrier() {
+        if (!audioserverPermissions()) return;
         mAudioSystem.triggerSystemPropertyUpdate(mSysPropListenerNativeHandle);
         List<Future> snapshot;
         synchronized (mScheduledPermissionTasks) {
diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
index ac3c028..b2c616a 100644
--- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java
+++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
@@ -316,6 +316,7 @@
         Pair<BiometricSensor, Integer> sensorNotEnrolled = null;
         Pair<BiometricSensor, Integer> sensorLockout = null;
         Pair<BiometricSensor, Integer> hardwareNotDetected = null;
+        Pair<BiometricSensor, Integer> biometricAppNotAllowed = null;
         for (Pair<BiometricSensor, Integer> pair : ineligibleSensors) {
             final int status = pair.second;
             if (status == BIOMETRIC_LOCKOUT_TIMED || status == BIOMETRIC_LOCKOUT_PERMANENT) {
@@ -327,6 +328,9 @@
             if (status == BIOMETRIC_HARDWARE_NOT_DETECTED) {
                 hardwareNotDetected = pair;
             }
+            if (status == BIOMETRIC_NOT_ENABLED_FOR_APPS) {
+                biometricAppNotAllowed = pair;
+            }
         }
 
         // If there is a sensor locked out, prioritize lockout over other sensor's error.
@@ -339,6 +343,10 @@
             return hardwareNotDetected;
         }
 
+        if (Flags.mandatoryBiometrics() && biometricAppNotAllowed != null) {
+            return biometricAppNotAllowed;
+        }
+
         // If the caller requested STRONG, and the device contains both STRONG and non-STRONG
         // sensors, prioritize BIOMETRIC_NOT_ENROLLED over the weak sensor's
         // BIOMETRIC_INSUFFICIENT_STRENGTH error.
diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java
index 8711214..407ef1e 100644
--- a/services/core/java/com/android/server/biometrics/Utils.java
+++ b/services/core/java/com/android/server/biometrics/Utils.java
@@ -321,6 +321,9 @@
             case BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE:
                 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE;
                 break;
+            case BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS:
+                biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS;
+                break;
             default:
                 Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode);
                 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
@@ -384,9 +387,12 @@
                 return BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED;
             case MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR:
                 return BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE;
+            case BIOMETRIC_NOT_ENABLED_FOR_APPS:
+                if (Flags.mandatoryBiometrics()) {
+                    return BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS;
+                }
             case BIOMETRIC_DISABLED_BY_DEVICE_POLICY:
             case BIOMETRIC_HARDWARE_NOT_DETECTED:
-            case BIOMETRIC_NOT_ENABLED_FOR_APPS:
             default:
                 return BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
         }
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 907e7c6..86015ac 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -938,7 +938,7 @@
             setAmbientLux(mFastAmbientLux);
             if (mLoggingEnabled) {
                 Slog.d(TAG, "updateAmbientLux: "
-                        + ((mFastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": "
+                        + ((mFastAmbientLux > mPreThresholdLux) ? "Brightened" : "Darkened") + ": "
                         + "mAmbientBrighteningThreshold=" + mAmbientBrighteningThreshold + ", "
                         + "mAmbientDarkeningThreshold=" + mAmbientDarkeningThreshold + ", "
                         + "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", "
diff --git a/services/core/java/com/android/server/display/DisplayBrightnessState.java b/services/core/java/com/android/server/display/DisplayBrightnessState.java
index 334dda0..01bbd2f 100644
--- a/services/core/java/com/android/server/display/DisplayBrightnessState.java
+++ b/services/core/java/com/android/server/display/DisplayBrightnessState.java
@@ -17,6 +17,7 @@
 package com.android.server.display;
 
 import android.hardware.display.BrightnessInfo;
+import android.os.PowerManager;
 import android.text.TextUtils;
 
 import com.android.server.display.brightness.BrightnessEvent;
@@ -255,7 +256,7 @@
         private String mDisplayBrightnessStrategyName;
         private boolean mShouldUseAutoBrightness;
         private boolean mIsSlowChange;
-        private float mMaxBrightness;
+        private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX;
         private float mMinBrightness;
         private float mCustomAnimationRate = CUSTOM_ANIMATION_RATE_NOT_SET;
         private boolean mShouldUpdateScreenBrightnessSetting;
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 2b732ea..ed16b14 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -134,6 +134,7 @@
 import android.util.EventLog;
 import android.util.IndentingPrintWriter;
 import android.util.IntArray;
+import android.util.MathUtils;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -1275,6 +1276,9 @@
                         || isUidPresentOnDisplayInternal(callingUid, displayId)) {
                     return info;
                 }
+            } else if (displayId == Display.DEFAULT_DISPLAY) {
+                Slog.e(TAG, "Default display is null for info request from uid "
+                        + callingUid);
             }
             return null;
         }
@@ -2223,10 +2227,11 @@
             if (display.isValidLocked()) {
                 applyDisplayChangedLocked(display);
             }
-            return;
+        } else {
+            releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
         }
 
-        releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
+        Slog.i(TAG, "Logical display removed: " + display.getDisplayIdLocked());
     }
 
     private void releaseDisplayAndEmitEvent(LogicalDisplay display, int event) {
@@ -3098,6 +3103,7 @@
 
     /**
      * Get internal or external viewport. Create it if does not currently exist.
+     *
      * @param viewportType - either INTERNAL or EXTERNAL
      * @return the viewport with the requested type
      */
@@ -4413,7 +4419,6 @@
         }
 
 
-
         @Override // Binder call
         public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) {
             final String uniqueId;
@@ -4492,10 +4497,12 @@
         @Override // Binder call
         public void setBrightness(int displayId, float brightness) {
             setBrightness_enforcePermission();
-            if (!isValidBrightness(brightness)) {
-                Slog.w(TAG, "Attempted to set invalid brightness" + brightness);
+            if (Float.isNaN(brightness)) {
+                Slog.w(TAG, "Attempted to set invalid brightness: " + brightness);
                 return;
             }
+            MathUtils.constrain(brightness, PowerManager.BRIGHTNESS_MIN,
+                    PowerManager.BRIGHTNESS_MAX);
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
@@ -4791,12 +4798,6 @@
         }
     }
 
-    private static boolean isValidBrightness(float brightness) {
-        return !Float.isNaN(brightness)
-                && (brightness >= PowerManager.BRIGHTNESS_MIN)
-                && (brightness <= PowerManager.BRIGHTNESS_MAX);
-    }
-
     @VisibleForTesting
     void overrideSensorManager(SensorManager sensorManager) {
         synchronized (mSyncRoot) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index bb2bed7..7c591e3 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -2222,6 +2222,7 @@
                 unblockScreenOn();
             }
             mWindowManagerPolicy.screenTurningOn(mDisplayId, mPendingScreenOnUnblocker);
+            Slog.i(TAG, "Window Manager Policy screenTurningOn complete");
         }
 
         // Return true if the screen isn't blocked.
diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java
index 40e9198..cf44ac0 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java
@@ -73,7 +73,6 @@
     abstract void stop();
 
     protected enum Type {
-        THERMAL,
         POWER,
         WEAR_BEDTIME_MODE,
     }
diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
index d3be33f..9404034 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
@@ -72,6 +72,8 @@
     private final List<DisplayDeviceDataListener> mDisplayDeviceDataListeners = new ArrayList<>();
     private final List<StatefulModifier> mStatefulModifiers = new ArrayList<>();
     private final List<UserSwitchListener> mUserSwitchListeners = new ArrayList<>();
+    private final List<DeviceConfigListener> mDeviceConfigListeners = new ArrayList<>();
+
     private ModifiersAggregatedState mModifiersAggregatedState = new ModifiersAggregatedState();
 
     private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener;
@@ -144,9 +146,14 @@
             if (m instanceof UserSwitchListener l) {
                 mUserSwitchListeners.add(l);
             }
+            if (m instanceof DeviceConfigListener l) {
+                mDeviceConfigListeners.add(l);
+            }
         });
-        mOnPropertiesChangedListener =
-                properties -> mClampers.forEach(BrightnessClamper::onDeviceConfigChanged);
+        mOnPropertiesChangedListener = properties -> {
+            mClampers.forEach(BrightnessClamper::onDeviceConfigChanged);
+            mDeviceConfigListeners.forEach(DeviceConfigListener::onDeviceConfigChanged);
+        };
         mLightSensorController.configure(data.getAmbientLightSensor(), data.getDisplayId());
         start();
     }
@@ -209,8 +216,6 @@
     private int getBrightnessMaxReason() {
         if (mClamperType == null) {
             return BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
-        } else if (mClamperType == Type.THERMAL) {
-            return BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL;
         } else if (mClamperType == Type.POWER) {
             return BrightnessInfo.BRIGHTNESS_MAX_REASON_POWER_IC;
         } else if (mClamperType == Type.WEAR_BEDTIME_MODE) {
@@ -225,7 +230,7 @@
      * Called when the user switches.
      */
     public void onUserSwitch() {
-        mUserSwitchListeners.forEach(listener -> listener.onSwitchUser());
+        mUserSwitchListeners.forEach(UserSwitchListener::onSwitchUser);
     }
 
     /**
@@ -294,11 +299,14 @@
                 state2.mMaxDesiredHdrRatio)
                 || !BrightnessSynchronizer.floatEquals(state1.mMaxHdrBrightness,
                 state2.mMaxHdrBrightness)
-                || state1.mSdrHdrRatioSpline != state2.mSdrHdrRatioSpline;
+                || state1.mSdrHdrRatioSpline != state2.mSdrHdrRatioSpline
+                || state1.mMaxBrightnessReason != state2.mMaxBrightnessReason
+                || !BrightnessSynchronizer.floatEquals(state1.mMaxBrightness,
+                state2.mMaxBrightness);
     }
 
     private void start() {
-        if (!mClampers.isEmpty()) {
+        if (!mClampers.isEmpty() || !mDeviceConfigListeners.isEmpty()) {
             mDeviceConfigParameterProvider.addOnPropertiesChangedListener(
                     mExecutor, mOnPropertiesChangedListener);
         }
@@ -333,8 +341,7 @@
                 ClamperChangeListener clamperChangeListener, DisplayDeviceData data,
                 DisplayManagerFlags flags, Context context, float currentBrightness) {
             List<BrightnessClamper<? super DisplayDeviceData>> clampers = new ArrayList<>();
-            clampers.add(
-                    new BrightnessThermalClamper(handler, clamperChangeListener, data));
+
             if (flags.isPowerThrottlingClamperEnabled()) {
                 // Check if power-throttling config is present.
                 PowerThrottlingConfigData configData = data.getPowerThrottlingConfigData();
@@ -354,6 +361,8 @@
                 Handler handler, ClamperChangeListener listener,
                 DisplayDeviceData data) {
             List<BrightnessStateModifier> modifiers = new ArrayList<>();
+            modifiers.add(new BrightnessThermalModifier(handler, listener, data));
+
             modifiers.add(new DisplayDimModifier(context));
             modifiers.add(new BrightnessLowPowerModeModifier());
             if (flags.isEvenDimmerEnabled() && data.mDisplayDeviceConfig.isEvenDimmerAvailable()) {
@@ -384,7 +393,7 @@
     /**
      * Config Data for clampers/modifiers
      */
-    public static class DisplayDeviceData implements BrightnessThermalClamper.ThermalData,
+    public static class DisplayDeviceData implements BrightnessThermalModifier.ThermalData,
             BrightnessPowerClamper.PowerData,
             BrightnessWearBedtimeModeClamper.WearBedtimeModeData {
         @NonNull
@@ -498,13 +507,23 @@
     }
 
     /**
+     * Modifier should implement this interface in order to receive device config updates
+     */
+    interface DeviceConfigListener {
+        void onDeviceConfigChanged();
+    }
+
+    /**
      * StatefulModifiers contribute to AggregatedState, that is used to decide if brightness
-     * adjustement is needed
+     * adjustment is needed
      */
     public static class ModifiersAggregatedState {
         float mMaxDesiredHdrRatio = HdrBrightnessModifier.DEFAULT_MAX_HDR_SDR_RATIO;
         float mMaxHdrBrightness = PowerManager.BRIGHTNESS_MAX;
         @Nullable
         Spline mSdrHdrRatioSpline = null;
+        @BrightnessInfo.BrightnessMaxReason
+        int mMaxBrightnessReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
+        float mMaxBrightness = PowerManager.BRIGHTNESS_MAX;
     }
 }
diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalClamper.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalModifier.java
similarity index 77%
rename from services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalClamper.java
rename to services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalModifier.java
index 4498258..21ef309 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalClamper.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalModifier.java
@@ -22,6 +22,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.hardware.display.BrightnessInfo;
+import android.hardware.display.DisplayManagerInternal;
 import android.os.Handler;
 import android.os.IThermalEventListener;
 import android.os.IThermalService;
@@ -33,8 +35,10 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData;
 import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel;
+import com.android.server.display.brightness.BrightnessReason;
 import com.android.server.display.config.SensorData;
 import com.android.server.display.feature.DeviceConfigParameterProvider;
 import com.android.server.display.utils.DeviceConfigParsingUtils;
@@ -43,12 +47,15 @@
 import java.io.PrintWriter;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.function.BiFunction;
 import java.util.function.Function;
 
 
-class BrightnessThermalClamper extends
-        BrightnessClamper<BrightnessThermalClamper.ThermalData> {
+class BrightnessThermalModifier implements BrightnessStateModifier,
+        BrightnessClamperController.DisplayDeviceDataListener,
+        BrightnessClamperController.StatefulModifier,
+        BrightnessClamperController.DeviceConfigListener {
 
     private static final String TAG = "BrightnessThermalClamper";
     @NonNull
@@ -58,6 +65,11 @@
     // data from DeviceConfig, for all displays, for all dataSets
     // mapOf(uniqueDisplayId to mapOf(dataSetId to ThermalBrightnessThrottlingData))
     @NonNull
+    protected final Handler mHandler;
+    @NonNull
+    protected final BrightnessClamperController.ClamperChangeListener mChangeListener;
+
+    @NonNull
     private Map<String, Map<String, ThermalBrightnessThrottlingData>>
             mThermalThrottlingDataOverride = Map.of();
     // data from DisplayDeviceConfig, for particular display+dataSet
@@ -73,6 +85,8 @@
     private String mDataId = null;
     @Temperature.ThrottlingStatus
     private int mThrottlingStatus = Temperature.THROTTLING_NONE;
+    private float mBrightnessCap = PowerManager.BRIGHTNESS_MAX;
+    private boolean mApplied = false;
 
     private final BiFunction<String, String, ThrottlingLevel> mDataPointMapper = (key, value) -> {
         try {
@@ -88,53 +102,51 @@
             mDataSetMapper = ThermalBrightnessThrottlingData::create;
 
 
-    BrightnessThermalClamper(Handler handler, ClamperChangeListener listener,
-            ThermalData thermalData) {
-        this(new Injector(), handler, listener, thermalData);
+    BrightnessThermalModifier(Handler handler, ClamperChangeListener listener,
+            BrightnessClamperController.DisplayDeviceData data) {
+        this(new Injector(), handler, listener, data);
     }
 
     @VisibleForTesting
-    BrightnessThermalClamper(Injector injector, Handler handler,
-            ClamperChangeListener listener, ThermalData thermalData) {
-        super(handler, listener);
+    BrightnessThermalModifier(Injector injector, @NonNull Handler handler,
+            @NonNull ClamperChangeListener listener,
+            @NonNull BrightnessClamperController.DisplayDeviceData data) {
+        mHandler = handler;
+        mChangeListener = listener;
         mConfigParameterProvider = injector.getDeviceConfigParameterProvider();
         mThermalStatusObserver = new ThermalStatusObserver(injector, handler);
         mHandler.post(() -> {
-            setDisplayData(thermalData);
-            loadOverrideData();
-        });
-
-    }
-
-    @Override
-    @NonNull
-    Type getType() {
-        return Type.THERMAL;
-    }
-
-    @Override
-    void onDeviceConfigChanged() {
-        mHandler.post(() -> {
-            loadOverrideData();
-            recalculateActiveData();
-        });
-    }
-
-    @Override
-    void onDisplayChanged(ThermalData data) {
-        mHandler.post(() -> {
             setDisplayData(data);
-            recalculateActiveData();
+            loadOverrideData();
         });
     }
+    //region BrightnessStateModifier
+    @Override
+    public void apply(DisplayManagerInternal.DisplayPowerRequest request,
+            DisplayBrightnessState.Builder stateBuilder) {
+        if (stateBuilder.getMaxBrightness() > mBrightnessCap) {
+            stateBuilder.setMaxBrightness(mBrightnessCap);
+            stateBuilder.setBrightness(Math.min(stateBuilder.getBrightness(), mBrightnessCap));
+            stateBuilder.setBrightnessMaxReason(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL);
+            stateBuilder.getBrightnessReason().addModifier(BrightnessReason.MODIFIER_THROTTLED);
+            // set fast change only when modifier is activated.
+            // this will allow auto brightness to apply slow change even when modifier is active
+            if (!mApplied) {
+                stateBuilder.setIsSlowChange(false);
+            }
+            mApplied = true;
+        } else {
+            mApplied = false;
+        }
+    }
 
     @Override
-    void stop() {
+    public void stop() {
         mThermalStatusObserver.stopObserving();
     }
 
     @Override
-    void dump(PrintWriter writer) {
+    public void dump(PrintWriter writer) {
         writer.println("BrightnessThermalClamper:");
         writer.println("  mThrottlingStatus: " + mThrottlingStatus);
         writer.println("  mUniqueDisplayId: " + mUniqueDisplayId);
@@ -142,10 +154,53 @@
         writer.println("  mDataOverride: " + mThermalThrottlingDataOverride);
         writer.println("  mDataFromDeviceConfig: " + mThermalThrottlingDataFromDeviceConfig);
         writer.println("  mDataActive: " + mThermalThrottlingDataActive);
+        writer.println("  mBrightnessCap:" + mBrightnessCap);
+        writer.println("  mApplied:" + mApplied);
         mThermalStatusObserver.dump(writer);
-        super.dump(writer);
     }
 
+    @Override
+    public boolean shouldListenToLightSensor() {
+        return false;
+    }
+
+    @Override
+    public void setAmbientLux(float lux) {
+        // noop
+    }
+    //endregion
+
+    //region DisplayDeviceDataListener
+    @Override
+    public void onDisplayChanged(BrightnessClamperController.DisplayDeviceData data) {
+        mHandler.post(() -> {
+            setDisplayData(data);
+            recalculateActiveData();
+        });
+    }
+    //endregion
+
+    //region StatefulModifier
+    @Override
+    public void applyStateChange(
+            BrightnessClamperController.ModifiersAggregatedState aggregatedState) {
+        if (aggregatedState.mMaxBrightness > mBrightnessCap) {
+            aggregatedState.mMaxBrightness = mBrightnessCap;
+            aggregatedState.mMaxBrightnessReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL;
+        }
+    }
+    //endregion
+
+    //region DeviceConfigListener
+    @Override
+    public void onDeviceConfigChanged() {
+        mHandler.post(() -> {
+            loadOverrideData();
+            recalculateActiveData();
+        });
+    }
+    //endregion
+
     private void recalculateActiveData() {
         if (mUniqueDisplayId == null || mDataId == null) {
             return;
@@ -176,14 +231,11 @@
 
     private void recalculateBrightnessCap() {
         float brightnessCap = PowerManager.BRIGHTNESS_MAX;
-        boolean isActive = false;
-
         if (mThermalThrottlingDataActive != null) {
             // Throttling levels are sorted by increasing severity
             for (ThrottlingLevel level : mThermalThrottlingDataActive.throttlingLevels) {
                 if (level.thermalStatus <= mThrottlingStatus) {
                     brightnessCap = level.brightness;
-                    isActive = true;
                 } else {
                     // Throttling levels that are greater than the current status are irrelevant
                     break;
@@ -191,9 +243,8 @@
             }
         }
 
-        if (brightnessCap  != mBrightnessCap || mIsActive != isActive) {
+        if (brightnessCap  != mBrightnessCap) {
             mBrightnessCap = brightnessCap;
-            mIsActive = isActive;
             mChangeListener.onChanged();
         }
     }
@@ -205,7 +256,6 @@
         }
     }
 
-
     private final class ThermalStatusObserver extends IThermalEventListener.Stub {
         private final Injector mInjector;
         private final Handler mHandler;
@@ -228,7 +278,7 @@
 
             String curType = mObserverTempSensor.type;
             mObserverTempSensor = tempSensor;
-            if (curType.equals(tempSensor.type)) {
+            if (Objects.equals(curType, tempSensor.type)) {
                 Slog.d(TAG, "Thermal status observer already started");
                 return;
             }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
index 234d6d3..236333e 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
@@ -53,6 +53,10 @@
     // Default state used in common by all the feature actions.
     protected static final int STATE_NONE = 0;
 
+    // Delay to query avr's audio status, some avrs could report the old volume first. It could
+    // show inverse mute state on TV.
+    protected static final long DELAY_GIVE_AUDIO_STATUS = 500;
+
     // Internal state indicating the progress of action.
     protected int mState = STATE_NONE;
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 4b85217..101596d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1150,6 +1150,13 @@
             return Constants.ABORT_REFUSED;
         }
 
+        if (mArcEstablished) {
+            HdmiLogger.debug("ARC is already established.");
+            HdmiCecMessage command = HdmiCecMessageBuilder.buildReportArcInitiated(
+                getDeviceInfo().getLogicalAddress(), message.getSource());
+            mService.sendCecCommand(command);
+            return Constants.HANDLED;
+        }
         // In case where <Initiate Arc> is started by <Request ARC Initiation>, this message is
         // handled in RequestArcInitiationAction as well.
         SetArcTransmissionStateAction action = new SetArcTransmissionStateAction(this,
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 3c7b9d3..271836a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1638,6 +1638,10 @@
         mHandler.post(new WorkSourceUidPreservingRunnable(runnable));
     }
 
+    void runOnServiceThreadDelayed(Runnable runnable, long delay) {
+        mHandler.postDelayed(new WorkSourceUidPreservingRunnable(runnable), delay);
+    }
+
     private void assertRunOnServiceThread() {
         if (Looper.myLooper() != mHandler.getLooper()) {
             throw new IllegalStateException("Should run on service thread.");
diff --git a/services/core/java/com/android/server/hdmi/RequestSadAction.java b/services/core/java/com/android/server/hdmi/RequestSadAction.java
index 0188e96..2566300 100644
--- a/services/core/java/com/android/server/hdmi/RequestSadAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestSadAction.java
@@ -19,6 +19,8 @@
 import android.hardware.hdmi.HdmiControlManager;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -36,7 +38,8 @@
     // State in which the action is waiting for <Report Short Audio Descriptor>.
     private static final int STATE_WAITING_FOR_REPORT_SAD = 1;
     private static final int MAX_SAD_PER_REQUEST = 4;
-    private static final int RETRY_COUNTER_MAX = 1;
+    @VisibleForTesting
+    public static final int RETRY_COUNTER_MAX = 3;
     private final int mTargetAddress;
     private final RequestSadCallback mCallback;
     private final List<Integer> mCecCodecsToQuery = new ArrayList<>();
diff --git a/services/core/java/com/android/server/hdmi/SendKeyAction.java b/services/core/java/com/android/server/hdmi/SendKeyAction.java
index 7e18d84..11682f6 100644
--- a/services/core/java/com/android/server/hdmi/SendKeyAction.java
+++ b/services/core/java/com/android/server/hdmi/SendKeyAction.java
@@ -180,15 +180,22 @@
                 && localDevice().getService().isAbsoluteVolumeBehaviorEnabled()) {
             sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(getSourceAddress(),
                     mTargetAddress),
-                    __ -> sendCommand(HdmiCecMessageBuilder.buildGiveAudioStatus(
-                            getSourceAddress(),
-                            localDevice().findAudioReceiverAddress())));
+                    __ -> queryAvrAudioStatus());
         } else {
             sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(getSourceAddress(),
                     mTargetAddress));
         }
     }
 
+    private void queryAvrAudioStatus() {
+        localDevice().mService.runOnServiceThreadDelayed(
+                () -> sendCommand(HdmiCecMessageBuilder.buildGiveAudioStatus(
+                        getSourceAddress(),
+                        localDevice().findAudioReceiverAddress())),
+                DELAY_GIVE_AUDIO_STATUS);
+
+    }
+
     @Override
     public boolean processCommand(HdmiCecMessage cmd) {
         // Send key action doesn't need any incoming CEC command, hence does not consume it.
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index 5ab22e1..e6abcb9 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -60,6 +60,12 @@
     boolean start() {
         // Seq #37.
         if (mEnabled) {
+            // Avoid triggering duplicate RequestSadAction events.
+            // This could lead to unexpected responses from the AVR and cause the TV to receive data
+            // out of order. The SAD report does not provide information about the order of events.
+            if ((tv().hasAction(RequestSadAction.class))) {
+                return true;
+            }
             // Request SADs before enabling ARC
             RequestSadAction action = new RequestSadAction(
                     localDevice(), Constants.ADDR_AUDIO_SYSTEM,
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 84cee7e..1285a61 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -2269,13 +2269,15 @@
     // Native callback.
     @SuppressWarnings("unused")
     private void notifyTouchpadHardwareState(TouchpadHardwareState hardwareStates, int deviceId) {
-        // TODO(b/286551975): sent the touchpad hardware state data here to TouchpadDebugActivity
         Slog.d(TAG, "notifyTouchpadHardwareState: Time: "
                 + hardwareStates.getTimestamp() + ", No. Buttons: "
                 + hardwareStates.getButtonsDown() + ", No. Fingers: "
                 + hardwareStates.getFingerCount() + ", No. Touch: "
                 + hardwareStates.getTouchCount() + ", Id: "
                 + deviceId);
+        if (mTouchpadDebugViewController != null) {
+            mTouchpadDebugViewController.updateTouchpadHardwareState(hardwareStates);
+        }
     }
 
     // Native callback.
diff --git a/services/core/java/com/android/server/input/debug/TouchpadDebugView.java b/services/core/java/com/android/server/input/debug/TouchpadDebugView.java
index 7785ffb..ba56ad0 100644
--- a/services/core/java/com/android/server/input/debug/TouchpadDebugView.java
+++ b/services/core/java/com/android/server/input/debug/TouchpadDebugView.java
@@ -30,6 +30,9 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.server.input.TouchpadFingerState;
+import com.android.server.input.TouchpadHardwareState;
+
 import java.util.Objects;
 
 public class TouchpadDebugView extends LinearLayout {
@@ -52,6 +55,10 @@
     private int mScreenHeight;
     private int mWindowLocationBeforeDragX;
     private int mWindowLocationBeforeDragY;
+    @NonNull
+    private TouchpadHardwareState mLastTouchpadState =
+            new TouchpadHardwareState(0, 0 /* buttonsDown */, 0, 0,
+                    new TouchpadFingerState[0]);
 
     public TouchpadDebugView(Context context, int touchpadId) {
         super(context);
@@ -83,14 +90,14 @@
 
     private void init(Context context) {
         setOrientation(VERTICAL);
-        setLayoutParams(new LinearLayout.LayoutParams(
-                LinearLayout.LayoutParams.WRAP_CONTENT,
-                LinearLayout.LayoutParams.WRAP_CONTENT));
-        setBackgroundColor(Color.TRANSPARENT);
+        setLayoutParams(new LayoutParams(
+                LayoutParams.WRAP_CONTENT,
+                LayoutParams.WRAP_CONTENT));
+        setBackgroundColor(Color.RED);
 
         // TODO(b/286551975): Replace this content with the touchpad debug view.
         TextView textView1 = new TextView(context);
-        textView1.setBackgroundColor(Color.parseColor("#FFFF0000"));
+        textView1.setBackgroundColor(Color.TRANSPARENT);
         textView1.setTextSize(20);
         textView1.setText("Touchpad Debug View 1");
         textView1.setGravity(Gravity.CENTER);
@@ -98,7 +105,7 @@
         textView1.setLayoutParams(new LayoutParams(1000, 200));
 
         TextView textView2 = new TextView(context);
-        textView2.setBackgroundColor(Color.BLUE);
+        textView2.setBackgroundColor(Color.TRANSPARENT);
         textView2.setTextSize(20);
         textView2.setText("Touchpad Debug View 2");
         textView2.setGravity(Gravity.CENTER);
@@ -126,9 +133,7 @@
             case MotionEvent.ACTION_MOVE:
                 deltaX = event.getRawX() - mWindowLayoutParams.x - mTouchDownX;
                 deltaY = event.getRawY() - mWindowLayoutParams.y - mTouchDownY;
-                Slog.d("TouchpadDebugView", "Slop = " + mTouchSlop);
                 if (isSlopExceeded(deltaX, deltaY)) {
-                    Slog.d("TouchpadDebugView", "Slop exceeded");
                     mWindowLayoutParams.x =
                             Math.max(0, Math.min((int) (event.getRawX() - mTouchDownX),
                                     mScreenWidth - this.getWidth()));
@@ -136,9 +141,6 @@
                             Math.max(0, Math.min((int) (event.getRawY() - mTouchDownY),
                                     mScreenHeight - this.getHeight()));
 
-                    Slog.d("TouchpadDebugView", "New position X: "
-                            + mWindowLayoutParams.x + ", Y: " + mWindowLayoutParams.y);
-
                     mWindowManager.updateViewLayout(this, mWindowLayoutParams);
                 }
                 return true;
@@ -166,7 +168,7 @@
     @Override
     public boolean performClick() {
         super.performClick();
-        Slog.d("TouchpadDebugView", "You clicked me!");
+        Slog.d("TouchpadDebugView", "You tapped the window!");
         return true;
     }
 
@@ -201,4 +203,34 @@
     public WindowManager.LayoutParams getWindowLayoutParams() {
         return mWindowLayoutParams;
     }
+
+    public void updateHardwareState(TouchpadHardwareState touchpadHardwareState) {
+        if (mLastTouchpadState.getButtonsDown() == 0) {
+            if (touchpadHardwareState.getButtonsDown() > 0) {
+                onTouchpadButtonPress();
+            }
+        } else {
+            if (touchpadHardwareState.getButtonsDown() == 0) {
+                onTouchpadButtonRelease();
+            }
+        }
+        mLastTouchpadState = touchpadHardwareState;
+    }
+
+    private void onTouchpadButtonPress() {
+        Slog.d("TouchpadDebugView", "You clicked me!");
+
+        // Iterate through all child views
+        // Temporary demonstration for testing
+        for (int i = 0; i < getChildCount(); i++) {
+            getChildAt(i).setBackgroundColor(Color.BLUE);
+        }
+    }
+
+    private void onTouchpadButtonRelease() {
+        Slog.d("TouchpadDebugView", "You released the click");
+        for (int i = 0; i < getChildCount(); i++) {
+            getChildAt(i).setBackgroundColor(Color.RED);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java b/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java
index c28e74a..bc53c49 100644
--- a/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java
+++ b/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java
@@ -27,6 +27,7 @@
 
 import com.android.server.input.InputManagerService;
 import com.android.server.input.TouchpadHardwareProperties;
+import com.android.server.input.TouchpadHardwareState;
 
 import java.util.Objects;
 
@@ -132,4 +133,10 @@
         mTouchpadDebugView = null;
         Slog.d(TAG, "Touchpad debug view removed.");
     }
+
+    public void updateTouchpadHardwareState(TouchpadHardwareState touchpadHardwareState) {
+        if (mTouchpadDebugView != null) {
+            mTouchpadDebugView.updateHardwareState(touchpadHardwareState);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index af0ccf9..f747879 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -4678,6 +4678,7 @@
         }
     }
 
+    // TODO(b/356239178): Make dump proto multi-user aware.
     private void dumpDebug(ProtoOutputStream proto, long fieldId) {
         synchronized (ImfLock.class) {
             final int userId = mCurrentImeUserId;
@@ -6103,17 +6104,40 @@
     @BinderThread
     private void dumpAsStringNoCheck(FileDescriptor fd, PrintWriter pw, String[] args,
             boolean isCritical) {
+        final int argUserId = parseUserIdFromDumpArgs(args);
+        final Printer p = new PrintWriterPrinter(pw);
+        p.println("Current Input Method Manager state:");
+        p.println("  concurrentMultiUserModeEnabled=" + mConcurrentMultiUserModeEnabled);
+        if (mConcurrentMultiUserModeEnabled && argUserId == UserHandle.USER_NULL) {
+            mUserDataRepository.forAllUserData(
+                    u -> dumpAsStringNoCheckForUser(u, fd, pw, args, isCritical));
+        } else {
+            final int userId = argUserId != UserHandle.USER_NULL ? argUserId : mCurrentImeUserId;
+            final var userData = getUserData(userId);
+            dumpAsStringNoCheckForUser(userData, fd, pw, args, isCritical);
+        }
+    }
+
+    @UserIdInt
+    private static int parseUserIdFromDumpArgs(String[] args) {
+        final int userIdx = Arrays.binarySearch(args, "--user");
+        if (userIdx == -1 || userIdx == args.length - 1) {
+            return UserHandle.USER_NULL;
+        }
+        return Integer.parseInt(args[userIdx + 1]);
+    }
+
+    // TODO(b/356239178): Update dump format output to better group per-user info.
+    @BinderThread
+    private void dumpAsStringNoCheckForUser(UserData userData, FileDescriptor fd, PrintWriter pw,
+            String[] args, boolean isCritical) {
+        final Printer p = new PrintWriterPrinter(pw);
         IInputMethodInvoker method;
         ClientState client;
-
-        final Printer p = new PrintWriterPrinter(pw);
-
+        p.println("  UserId=" + userData.mUserId);
         synchronized (ImfLock.class) {
-            final int userId = mCurrentImeUserId;
-            final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
-            final var userData = getUserData(userId);
-            p.println("Current Input Method Manager state:");
-            p.println("  concurrentMultiUserModeEnabled" + mConcurrentMultiUserModeEnabled);
+            final InputMethodSettings settings = InputMethodSettingsRepository.get(
+                    userData.mUserId);
             final List<InputMethodInfo> methodList = settings.getMethodList();
             int numImes = methodList.size();
             p.println("  Input Methods:");
@@ -6133,7 +6157,7 @@
                 p.println("    sessionRequested="
                         + c.mSessionRequested);
                 p.println("    sessionRequestedForAccessibility="
-                                + c.mSessionRequestedForAccessibility);
+                        + c.mSessionRequestedForAccessibility);
                 p.println("    curSession=" + c.mCurSession);
                 p.println("    selfReportedDisplayId=" + c.mSelfReportedDisplayId);
                 p.println("    uid=" + c.mUid);
@@ -6141,7 +6165,6 @@
             };
             mClientController.forAllClients(clientControllerDump);
             final var bindingController = userData.mBindingController;
-            p.println("  mCurrentImeUserId=" + userData.mUserId);
             p.println("  mCurMethodId=" + bindingController.getSelectedMethodId());
             client = userData.mCurClient;
             p.println("  mCurClient=" + client + " mCurSeq="
@@ -6234,8 +6257,6 @@
             p.println("No input method client.");
         }
         synchronized (ImfLock.class) {
-            final int userId = mCurrentImeUserId;
-            final var userData = getUserData(userId);
             if (userData.mImeBindingState.mFocusedWindowClient != null
                     && client != userData.mImeBindingState.mFocusedWindowClient) {
                 p.println(" ");
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 4fcf27d..7d44ba1 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -889,8 +889,14 @@
                 // Hide notification first, as tie profile lock takes time
                 hideEncryptionNotification(new UserHandle(userId));
 
-                if (isCredentialSharableWithParent(userId)) {
-                    tieProfileLockIfNecessary(userId, LockscreenCredential.createNone());
+                if (android.app.admin.flags.Flags.fixRaceConditionInTieProfileLock()) {
+                    synchronized (mSpManager) {
+                        tieProfileLockIfNecessary(userId, LockscreenCredential.createNone());
+                    }
+                } else {
+                    if (isCredentialSharableWithParent(userId)) {
+                        tieProfileLockIfNecessary(userId, LockscreenCredential.createNone());
+                    }
                 }
             }
         });
@@ -1287,7 +1293,13 @@
                 mStorage.removeChildProfileLock(userId);
                 removeKeystoreProfileKey(userId);
             } else {
-                tieProfileLockIfNecessary(userId, profileUserPassword);
+                if (android.app.admin.flags.Flags.fixRaceConditionInTieProfileLock()) {
+                    synchronized (mSpManager) {
+                        tieProfileLockIfNecessary(userId, profileUserPassword);
+                    }
+                } else {
+                    tieProfileLockIfNecessary(userId, profileUserPassword);
+                }
             }
         } catch (IllegalStateException e) {
             setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, old, userId);
@@ -3403,8 +3415,13 @@
             // It's OK to dump the credential type since anyone with physical access can just
             // observe it from the keyguard directly.
             pw.println("Quality: " + getKeyguardStoredQuality(userId));
-            pw.println("CredentialType: " + LockPatternUtils.credentialTypeToString(
-                    getCredentialTypeInternal(userId)));
+            final int credentialType = getCredentialTypeInternal(userId);
+            pw.println("CredentialType: "
+                    + LockPatternUtils.credentialTypeToString(credentialType));
+            if (credentialType == CREDENTIAL_TYPE_NONE) {
+                pw.println("IsLockScreenDisabled: "
+                        + getBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, userId));
+            }
             pw.println("SeparateChallenge: " + getSeparateProfileChallengeEnabledInternal(userId));
             pw.println(TextUtils.formatSimple("Metrics: %s",
                     getUserPasswordMetrics(userId) != null ? "known" : "unknown"));
diff --git a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
index bad959a..925ba17 100644
--- a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
+++ b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
@@ -22,6 +22,7 @@
 import static com.android.server.notification.ZenLog.traceApplyDeviceEffect;
 import static com.android.server.notification.ZenLog.traceScheduleApplyDeviceEffect;
 
+import android.app.KeyguardManager;
 import android.app.UiModeManager;
 import android.app.WallpaperManager;
 import android.content.BroadcastReceiver;
@@ -53,6 +54,7 @@
 
     private final Context mContext;
     private final ColorDisplayManager mColorDisplayManager;
+    private final KeyguardManager mKeyguardManager;
     private final PowerManager mPowerManager;
     private final UiModeManager mUiModeManager;
     private final WallpaperManager mWallpaperManager;
@@ -67,6 +69,7 @@
     DefaultDeviceEffectsApplier(Context context) {
         mContext = context;
         mColorDisplayManager = context.getSystemService(ColorDisplayManager.class);
+        mKeyguardManager = context.getSystemService(KeyguardManager.class);
         mPowerManager = context.getSystemService(PowerManager.class);
         mUiModeManager = context.getSystemService(UiModeManager.class);
         WallpaperManager wallpaperManager = context.getSystemService(WallpaperManager.class);
@@ -133,12 +136,14 @@
 
         // Changing the theme can be disruptive for the user (Activities are likely recreated, may
         // lose some state). Therefore we only apply the change immediately if the rule was
-        // activated manually, or we are initializing, or the screen is currently off/dreaming.
+        // activated manually, or we are initializing, or the screen is currently off/dreaming,
+        // or if the device is locked.
         if (origin == ZenModeConfig.ORIGIN_INIT
                 || origin == ZenModeConfig.ORIGIN_INIT_USER
                 || origin == ZenModeConfig.ORIGIN_USER_IN_SYSTEMUI
                 || origin == ZenModeConfig.ORIGIN_USER_IN_APP
-                || !mPowerManager.isInteractive()) {
+                || !mPowerManager.isInteractive()
+                || (android.app.Flags.modesUi() && mKeyguardManager.isKeyguardLocked())) {
             unregisterScreenOffReceiver();
             updateNightModeImmediately(useNightMode);
         } else {
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 0cc50e6..03fc60c 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -103,7 +103,7 @@
  *  - A remote interface definition (aidl) provided by the service used for communication.
  */
 abstract public class ManagedServices {
-    protected final String TAG = getClass().getSimpleName();
+    protected final String TAG = getClass().getSimpleName().replace('$', '.');
     protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000;
@@ -1094,7 +1094,7 @@
             return info;
         }
         throw new SecurityException("Disallowed call from unknown " + getCaption() + ": "
-                + service + " " + service.getClass());
+                + service.asBinder() + " " + service.getClass());
     }
 
     public boolean isSameUser(IInterface service, int userId) {
@@ -1585,6 +1585,9 @@
         // after the rebind delay
         if (isPackageOrComponentAllowedWithPermission(cn, userId)) {
             registerService(cn, userId);
+        } else {
+            if (DEBUG) Slog.v(TAG, "skipped reregisterService cn=" + cn + " u=" + userId
+                    + " because of isPackageOrComponentAllowedWithPermission check");
         }
     }
 
@@ -1918,6 +1921,7 @@
                     .append(",targetSdkVersion=").append(targetSdkVersion)
                     .append(",connection=").append(connection == null ? null : "<connection>")
                     .append(",service=").append(service)
+                    .append(",serviceAsBinder=").append(service != null ? service.asBinder() : null)
                     .append(']').toString();
         }
 
@@ -1956,7 +1960,7 @@
 
         @Override
         public void binderDied() {
-            if (DEBUG) Slog.d(TAG, "binderDied");
+            if (DEBUG) Slog.d(TAG, "binderDied " + this);
             // Remove the service, but don't unbind from the service. The system will bring the
             // service back up, and the onServiceConnected handler will read the service with the
             // new binding. If this isn't a bound service, and is just a registered
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 43a285c..2856eb4 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -1019,7 +1019,9 @@
                     && scanInstallPackages(requests, createdAppId, versionInfos)) {
                 List<ReconciledPackage> reconciledPackages =
                         reconcileInstallPackages(requests, versionInfos);
-                if (reconciledPackages != null && commitInstallPackages(reconciledPackages)) {
+                if (reconciledPackages != null
+                        && renameAndUpdatePaths(requests)
+                        && commitInstallPackages(reconciledPackages)) {
                     success = true;
                 }
             }
@@ -1029,24 +1031,49 @@
         }
     }
 
-    private boolean prepareInstallPackages(List<InstallRequest> requests) {
-        // TODO: will remove the locking after doRename is moved out of prepare
+    private boolean renameAndUpdatePaths(List<InstallRequest> requests) {
         try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
             for (InstallRequest request : requests) {
-                try {
-                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
-                    request.onPrepareStarted();
-                    preparePackageLI(request);
-                } catch (PrepareFailure prepareFailure) {
-                    request.setError(prepareFailure.error,
-                            prepareFailure.getMessage());
-                    request.setOriginPackage(prepareFailure.mConflictingPackage);
-                    request.setOriginPermission(prepareFailure.mConflictingPermission);
-                    return false;
-                } finally {
-                    request.onPrepareFinished();
-                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+                ParsedPackage parsedPackage = request.getParsedPackage();
+                final boolean isApex = (request.getScanFlags() & SCAN_AS_APEX) != 0;
+                if (isApex) {
+                    continue;
                 }
+                try {
+                    doRenameLI(request, parsedPackage);
+                    setUpFsVerity(parsedPackage);
+                } catch (Installer.InstallerException | IOException | DigestException
+                         | NoSuchAlgorithmException | PrepareFailure e) {
+                    request.setError(PackageManagerException.INTERNAL_ERROR_VERITY_SETUP,
+                            "Failed to set up verity: " + e);
+                    return false;
+                }
+
+                // update paths that are set before renaming
+                PackageSetting scannedPackageSetting = request.getScannedPackageSetting();
+                scannedPackageSetting.setPath(new File(parsedPackage.getPath()));
+                scannedPackageSetting.setLegacyNativeLibraryPath(
+                        parsedPackage.getNativeLibraryRootDir());
+            }
+            return true;
+        }
+    }
+
+    private boolean prepareInstallPackages(List<InstallRequest> requests) {
+        for (InstallRequest request : requests) {
+            try {
+                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
+                request.onPrepareStarted();
+                preparePackage(request);
+            } catch (PrepareFailure prepareFailure) {
+                request.setError(prepareFailure.error,
+                        prepareFailure.getMessage());
+                request.setOriginPackage(prepareFailure.mConflictingPackage);
+                request.setOriginPermission(prepareFailure.mConflictingPermission);
+                return false;
+            } finally {
+                request.onPrepareFinished();
+                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
             }
         }
         return true;
@@ -1231,8 +1258,7 @@
         return newProp != null && newProp.getBoolean();
     }
 
-    @GuardedBy("mPm.mInstallLock")
-    private void preparePackageLI(InstallRequest request) throws PrepareFailure {
+    private void preparePackage(InstallRequest request) throws PrepareFailure {
         final int[] allUsers =  mPm.mUserManager.getUserIds();
         final int installFlags = request.getInstallFlags();
         final boolean onExternal = request.getVolumeUuid() != null;
@@ -1739,18 +1765,7 @@
             }
         }
 
-        if (!isApex) {
-            doRenameLI(request, parsedPackage);
-
-            try {
-                setUpFsVerity(parsedPackage);
-            } catch (Installer.InstallerException | IOException | DigestException
-                    | NoSuchAlgorithmException e) {
-                throw PrepareFailure.ofInternalError(
-                        "Failed to set up verity: " + e,
-                        PackageManagerException.INTERNAL_ERROR_VERITY_SETUP);
-            }
-        } else {
+        if (isApex) {
             // Use the path returned by apexd
             parsedPackage.setPath(request.getApexInfo().modulePath);
             parsedPackage.setBaseApkPath(request.getApexInfo().modulePath);
@@ -1882,10 +1897,16 @@
                     }
 
                     if (!oldSharedUid.equals(newSharedUid)) {
-                        throw new PrepareFailure(INSTALL_FAILED_UID_CHANGED,
-                                "Package " + parsedPackage.getPackageName()
-                                        + " shared user changed from "
-                                        + oldSharedUid + " to " + newSharedUid);
+                        if (!(oldSharedUid.equals("<nothing>") && ps.getPkg() == null
+                                && ps.isArchivedOnAnyUser(allUsers))) {
+                            // Only allow changing sharedUserId if unarchiving
+                            // TODO(b/361558423): remove this check after pre-archiving installs
+                            // accept a sharedUserId param in the API
+                            throw new PrepareFailure(INSTALL_FAILED_UID_CHANGED,
+                                    "Package " + parsedPackage.getPackageName()
+                                            + " shared user changed from "
+                                            + oldSharedUid + " to " + newSharedUid);
+                        }
                     }
 
                     // APK should not re-join shared UID
@@ -2086,7 +2107,21 @@
 
         // Reflect the rename in scanned details
         try {
-            parsedPackage.setPath(afterCodeFile.getCanonicalPath());
+            String afterCanonicalPath = afterCodeFile.getCanonicalPath();
+            String beforeCanonicalPath = beforeCodeFile.getCanonicalPath();
+            parsedPackage.setPath(afterCanonicalPath);
+
+            parsedPackage.setNativeLibraryDir(
+                    parsedPackage.getNativeLibraryDir()
+                            .replace(beforeCanonicalPath, afterCanonicalPath));
+            parsedPackage.setNativeLibraryRootDir(
+                    parsedPackage.getNativeLibraryRootDir()
+                            .replace(beforeCanonicalPath, afterCanonicalPath));
+            String secondaryNativeLibraryDir = parsedPackage.getSecondaryNativeLibraryDir();
+            if (secondaryNativeLibraryDir != null) {
+                parsedPackage.setSecondaryNativeLibraryDir(
+                        secondaryNativeLibraryDir.replace(beforeCanonicalPath, afterCanonicalPath));
+            }
         } catch (IOException e) {
             Slog.e(TAG, "Failed to get path: " + afterCodeFile, e);
             throw new PrepareFailure(PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE,
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index 5e45b4c..f532342 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -936,13 +936,9 @@
      * <p> In the rare case the app had multiple launcher activities, only one of the icons is
      * returned arbitrarily.
      *
-     * <p> By default, the icon will be overlay'd with a cloud icon on top. A launcher app can
+     * <p> By default, the icon will be overlay'd with a cloud icon on top. An app can
      * disable the cloud overlay via the
      * {@link LauncherApps.ArchiveCompatibilityParams#setEnableIconOverlay(boolean)} API.
-     * The default launcher's cloud overlay mode determines the cloud overlay status returned by
-     * any other callers. That is, if the current launcher has the cloud overlay disabled, any other
-     * app that fetches the app icon will also get an icon that has the cloud overlay disabled.
-     * This is to prevent style mismatch caused by icons that are fetched by different callers.
      */
     @Nullable
     public Bitmap getArchivedAppIcon(@NonNull String packageName, @NonNull UserHandle user,
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 9fb9e71..9428de7 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -925,6 +925,18 @@
         return PackageArchiver.isArchived(readUserState(userId));
     }
 
+    /**
+     * @return if the package is archived in any of the users
+     */
+    boolean isArchivedOnAnyUser(int[] userIds) {
+        for (int user : userIds) {
+            if (isArchived(user)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     int getInstallReason(int userId) {
         return readUserState(userId).getInstallReason();
     }
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 74594cc..94bdfbd 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -56,8 +56,8 @@
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.PackageStateUtils;
+import com.android.server.rollback.ApexdRevertLogger;
 import com.android.server.rollback.RollbackManagerInternal;
-import com.android.server.rollback.WatchdogRollbackLogger;
 
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
@@ -764,7 +764,7 @@
     private void logFailedApexSessionsIfNecessary() {
         synchronized (mFailedPackageNames) {
             if (!mFailedPackageNames.isEmpty()) {
-                WatchdogRollbackLogger.logApexdRevert(mContext,
+                ApexdRevertLogger.logApexdRevert(mContext,
                         mFailedPackageNames, mNativeFailureReason);
             }
         }
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 1c70af0..5ca5fda 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -397,6 +397,8 @@
         ai.privateFlags |= flag(state.isInstantApp(), ApplicationInfo.PRIVATE_FLAG_INSTANT)
                 | flag(state.isVirtualPreload(), ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD)
                 | flag(state.isHidden(), ApplicationInfo.PRIVATE_FLAG_HIDDEN);
+        ai.privateFlagsExt |=
+                flag(state.isNotLaunched(), ApplicationInfo.PRIVATE_FLAG_EXT_NOT_LAUNCHED);
         if (state.getEnabledState() == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
             ai.enabled = true;
         } else if (state.getEnabledState()
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 749025b..ed9dcfa 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -535,7 +535,7 @@
     volatile boolean mRequestedOrSleepingDefaultDisplay;
 
     /**
-     * This is used to check whether to invoke {@link #updateScreenOffSleepToken} when screen is
+     * This is used to check whether to acquire screen-off sleep token when screen is
      * turned off. E.g. if it is false when screen is turned off and the display is swapping, it
      * is expected that the screen will be on in a short time. Then it is unnecessary to acquire
      * screen-off-sleep-token, so it can avoid intermediate visibility or lifecycle changes.
@@ -610,7 +610,6 @@
     private boolean mPendingKeyguardOccluded;
     private boolean mKeyguardOccludedChanged;
 
-    private ActivityTaskManagerInternal.SleepTokenAcquirer mScreenOffSleepTokenAcquirer;
     Intent mHomeIntent;
     Intent mCarDockIntent;
     Intent mDeskDockIntent;
@@ -810,7 +809,7 @@
                     event.recycle();
                     break;
                 case MSG_HANDLE_ALL_APPS:
-                    launchAllAppsAction();
+                    launchAllAppsAction((KeyEvent) msg.obj);
                     break;
                 case MSG_RINGER_TOGGLE_CHORD:
                     handleRingerChordGesture();
@@ -1879,26 +1878,31 @@
         }
     }
 
-    private void launchAllAppsAction() {
-        Intent intent = new Intent(Intent.ACTION_ALL_APPS);
-        if (mHasFeatureLeanback) {
-            Intent intentLauncher = new Intent(Intent.ACTION_MAIN);
-            intentLauncher.addCategory(Intent.CATEGORY_HOME);
-            ResolveInfo resolveInfo = mPackageManager.resolveActivityAsUser(intentLauncher,
-                    PackageManager.MATCH_SYSTEM_ONLY,
-                    mCurrentUserId);
-            if (resolveInfo != null) {
-                intent.setPackage(resolveInfo.activityInfo.packageName);
+    private void launchAllAppsAction(KeyEvent event) {
+        if (mHasFeatureLeanback || mHasFeatureWatch) {
+            // TV and watch support the all apps intent
+            notifyKeyGestureCompleted(event,
+                                KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS);
+            Intent intent = new Intent(Intent.ACTION_ALL_APPS);
+            if (mHasFeatureLeanback) {
+                Intent intentLauncher = new Intent(Intent.ACTION_MAIN);
+                intentLauncher.addCategory(Intent.CATEGORY_HOME);
+                ResolveInfo resolveInfo = mPackageManager.resolveActivityAsUser(intentLauncher,
+                        PackageManager.MATCH_SYSTEM_ONLY,
+                        mCurrentUserId);
+                if (resolveInfo != null) {
+                    intent.setPackage(resolveInfo.activityInfo.packageName);
+                }
             }
-        }
-        startActivityAsUser(intent, UserHandle.CURRENT);
-    }
-
-    private void launchAllAppsViaA11y() {
-        AccessibilityManagerInternal accessibilityManager = getAccessibilityManagerInternal();
-        if (accessibilityManager != null) {
-            accessibilityManager.performSystemAction(
-                    AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
+            startActivityAsUser(intent, UserHandle.CURRENT);
+        } else {
+            notifyKeyGestureCompleted(event,
+                                KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS);
+            AccessibilityManagerInternal accessibilityManager = getAccessibilityManagerInternal();
+            if (accessibilityManager != null) {
+                accessibilityManager.performSystemAction(
+                        AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
+            }
         }
         dismissKeyboardShortcutsMenu();
     }
@@ -2076,15 +2080,7 @@
             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, "Home - Long Press");
             switch (mLongPressOnHomeBehavior) {
                 case LONG_PRESS_HOME_ALL_APPS:
-                    if (mHasFeatureLeanback) {
-                        launchAllAppsAction();
-                        notifyKeyGestureCompleted(event,
-                                KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS);
-                    } else {
-                        launchAllAppsViaA11y();
-                        notifyKeyGestureCompleted(event,
-                                KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS);
-                    }
+                    launchAllAppsAction(event);
                     break;
                 case LONG_PRESS_HOME_ASSIST:
                     notifyKeyGestureCompleted(event,
@@ -2223,9 +2219,6 @@
         mLockPatternUtils = new LockPatternUtils(mContext);
         mLogger = new MetricsLogger();
 
-        mScreenOffSleepTokenAcquirer = mActivityTaskManagerInternal
-                .createSleepTokenAcquirer("ScreenOff");
-
         Resources res = mContext.getResources();
         mWakeOnDpadKeyPress =
                 res.getBoolean(com.android.internal.R.bool.config_wakeOnDpadKeyPress);
@@ -3695,18 +3688,11 @@
                 break;
             case KeyEvent.KEYCODE_ALL_APPS:
                 if (firstDown) {
-                    if (mHasFeatureLeanback) {
-                        mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
-                        Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS);
-                        msg.setAsynchronous(true);
-                        msg.sendToTarget();
-                        notifyKeyGestureCompleted(event,
-                                KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS);
-                    } else {
-                        launchAllAppsViaA11y();
-                        notifyKeyGestureCompleted(event,
-                                KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS);
-                    }
+                    mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
+
+                    Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS, new KeyEvent(event));
+                    msg.setAsynchronous(true);
+                    msg.sendToTarget();
                 }
                 return true;
             case KeyEvent.KEYCODE_NOTIFICATION:
@@ -3759,9 +3745,7 @@
                                 KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK);
                     } else if (mPendingMetaAction) {
                         if (!canceled) {
-                            launchAllAppsViaA11y();
-                            notifyKeyGestureCompleted(event,
-                                    KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS);
+                            launchAllAppsAction(event);
                         }
                         mPendingMetaAction = false;
                     }
@@ -5533,13 +5517,6 @@
         mRequestedOrSleepingDefaultDisplay = true;
         mIsGoingToSleepDefaultDisplay = true;
 
-        // In case startedGoingToSleep is called after screenTurnedOff (the source caller is in
-        // order but the methods run on different threads) and updateScreenOffSleepToken was
-        // skipped. Then acquire sleep token if screen was off.
-        if (!mDefaultDisplayPolicy.isScreenOnFully() && !mDefaultDisplayPolicy.isScreenOnEarly()) {
-            updateScreenOffSleepToken(true /* acquire */);
-        }
-
         if (mKeyguardDelegate != null) {
             mKeyguardDelegate.onStartedGoingToSleep(pmSleepReason);
         }
@@ -5700,11 +5677,9 @@
         if (DEBUG_WAKEUP) Slog.i(TAG, "Display" + displayId + " turned off...");
 
         if (displayId == DEFAULT_DISPLAY) {
-            if (!isSwappingDisplay || mIsGoingToSleepDefaultDisplay) {
-                updateScreenOffSleepToken(true /* acquire */);
-            }
+            final boolean acquireSleepToken = !isSwappingDisplay || mIsGoingToSleepDefaultDisplay;
             mRequestedOrSleepingDefaultDisplay = false;
-            mDefaultDisplayPolicy.screenTurnedOff();
+            mDefaultDisplayPolicy.screenTurnedOff(acquireSleepToken);
             synchronized (mLock) {
                 if (mKeyguardDelegate != null) {
                     mKeyguardDelegate.onScreenTurnedOff();
@@ -5760,7 +5735,6 @@
         if (displayId == DEFAULT_DISPLAY) {
             Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurningOn",
                     0 /* cookie */);
-            updateScreenOffSleepToken(false /* acquire */);
             mDefaultDisplayPolicy.screenTurningOn(screenOnListener);
             mBootAnimationDismissable = false;
 
@@ -6267,15 +6241,6 @@
         }
     }
 
-    // TODO (multidisplay): Support multiple displays in WindowManagerPolicy.
-    private void updateScreenOffSleepToken(boolean acquire) {
-        if (acquire) {
-            mScreenOffSleepTokenAcquirer.acquire(DEFAULT_DISPLAY);
-        } else {
-            mScreenOffSleepTokenAcquirer.release(DEFAULT_DISPLAY);
-        }
-    }
-
     /** {@inheritDoc} */
     @Override
     public void enableScreenAfterBoot() {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 12e7fd0..71cb882 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -3668,7 +3668,7 @@
                         mBrightWhenDozingConfig);
                 int wakefulness = powerGroup.getWakefulnessLocked();
                 if (DEBUG_SPEW) {
-                    Slog.d(TAG, "updateDisplayPowerStateLocked: displayReady=" + ready
+                    Slog.d(TAG, "updatePowerGroupsLocked: displayReady=" + ready
                             + ", groupId=" + groupId
                             + ", policy=" + policyToString(powerGroup.getPolicyLocked())
                             + ", mWakefulness="
diff --git a/services/core/java/com/android/server/rollback/ApexdRevertLogger.java b/services/core/java/com/android/server/rollback/ApexdRevertLogger.java
new file mode 100644
index 0000000..9950cc7
--- /dev/null
+++ b/services/core/java/com/android/server/rollback/ApexdRevertLogger.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2024 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.rollback;
+
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH_DURING_BOOT;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.VersionedPackage;
+import android.os.SystemProperties;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.crashrecovery.proto.CrashRecoveryStatsLog;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class handles the logic for logging Apexd-triggered rollback events.
+ * TODO: b/354112511 Refactor to have a separate metric for ApexdReverts
+ */
+public final class ApexdRevertLogger {
+    private static final String TAG = "WatchdogRollbackLogger";
+
+    private static final String LOGGING_PARENT_KEY = "android.content.pm.LOGGING_PARENT";
+
+    /**
+     * Logs that one or more apexd reverts have occurred, along with the crashing native process
+     * that caused apexd to revert during boot.
+     *
+     * @param context the context to use when determining the log packages
+     * @param failedPackageNames a list of names of packages which were reverted
+     * @param failingNativeProcess the crashing native process which caused a revert
+     */
+    public static void logApexdRevert(Context context, @NonNull List<String> failedPackageNames,
+            @NonNull String failingNativeProcess) {
+        Set<VersionedPackage> logPackages = getLogPackages(context, failedPackageNames);
+        for (VersionedPackage logPackage: logPackages) {
+            logEvent(logPackage,
+                    failingNativeProcess);
+        }
+    }
+
+    /**
+     * Gets the set of parent packages for a given set of failed package names. In the case that
+     * multiple sessions have failed, we want to log failure for each of the parent packages.
+     * Even if multiple failed packages have the same parent, we only log the parent package once.
+     */
+    private static Set<VersionedPackage> getLogPackages(Context context,
+            @NonNull List<String> failedPackageNames) {
+        Set<VersionedPackage> parentPackages = new ArraySet<>();
+        for (String failedPackageName: failedPackageNames) {
+            parentPackages.add(getLogPackage(context, new VersionedPackage(failedPackageName, 0)));
+        }
+        return parentPackages;
+    }
+
+    /**
+     * Returns the logging parent of a given package if it exists, {@code null} otherwise.
+     *
+     * The logging parent is defined by the {@code android.content.pm.LOGGING_PARENT} field in the
+     * metadata of a package's AndroidManifest.xml.
+     */
+    @VisibleForTesting
+    @Nullable
+    private static VersionedPackage getLogPackage(Context context,
+            @NonNull VersionedPackage failingPackage) {
+        String logPackageName;
+        VersionedPackage loggingParent;
+        logPackageName = getLoggingParentName(context, failingPackage.getPackageName());
+        if (logPackageName == null) {
+            return null;
+        }
+        try {
+            loggingParent = new VersionedPackage(logPackageName, context.getPackageManager()
+                    .getPackageInfo(logPackageName, 0 /* flags */).getLongVersionCode());
+        } catch (PackageManager.NameNotFoundException e) {
+            return null;
+        }
+        return loggingParent;
+    }
+
+    @Nullable
+    private static String getLoggingParentName(Context context, @NonNull String packageName) {
+        PackageManager packageManager = context.getPackageManager();
+        try {
+            int flags = PackageManager.MATCH_APEX | PackageManager.GET_META_DATA;
+            ApplicationInfo ai = packageManager.getPackageInfo(packageName, flags).applicationInfo;
+            if (ai == null || ai.metaData == null) {
+                return null;
+            }
+            return ai.metaData.getString(LOGGING_PARENT_KEY);
+        } catch (Exception e) {
+            Slog.w(TAG, "Unable to discover logging parent package: " + packageName, e);
+            return null;
+        }
+    }
+
+    /**
+     * Log a Apexd rollback event to statsd.
+     *
+     * @param logPackage         the package to associate the rollback with.
+     * @param failingPackageName the failing package or process which triggered the rollback.
+     */
+    private static void logEvent(@Nullable VersionedPackage logPackage,
+            @NonNull String failingPackageName) {
+        Slog.i(TAG, "Watchdog event occurred with type: ROLLBACK_SUCCESS"
+                + " logPackage: " + logPackage
+                + " rollbackReason: REASON_NATIVE_CRASH_DURING_BOOT"
+                + " failedPackageName: " + failingPackageName);
+        CrashRecoveryStatsLog.write(
+                WATCHDOG_ROLLBACK_OCCURRED,
+                WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
+                (logPackage != null) ? logPackage.getPackageName() : "",
+                (logPackage != null) ? logPackage.getVersionCode() : 0,
+                WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH_DURING_BOOT,
+                failingPackageName,
+                new byte[]{});
+
+        logTestProperties(logPackage, failingPackageName);
+    }
+
+    /**
+     * Writes properties which will be used by rollback tests to check if rollback has occurred
+     * have occurred.
+     *
+     * persist.sys.rollbacktest.enabled: true if rollback tests are running
+     * persist.sys.rollbacktest.ROLLBACK_SUCCESS.logPackage: the package to associate the rollback
+     * persist.sys.rollbacktest.ROLLBACK_SUCCESS.rollbackReason: the reason Apexd triggered it
+     * persist.sys.rollbacktest.ROLLBACK_SUCCESS.failedPackageName: the failing package or process
+     * which triggered the rollback
+     */
+    private static void logTestProperties(@Nullable VersionedPackage logPackage,
+            @NonNull String failingPackageName) {
+        // This property should be on only during the tests
+        final String prefix = "persist.sys.rollbacktest.";
+        if (!SystemProperties.getBoolean(prefix + "enabled", false)) {
+            return;
+        }
+        String key = prefix +  "ROLLBACK_SUCCESS";
+        SystemProperties.set(key, String.valueOf(true));
+        SystemProperties.set(key + ".logPackage", logPackage != null ? logPackage.toString() : "");
+        SystemProperties.set(key + ".rollbackReason", "REASON_NATIVE_CRASH_DURING_BOOT");
+        SystemProperties.set(key + ".failedPackageName", failingPackageName);
+    }
+}
diff --git a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
index 7fc0292..d763199 100644
--- a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
+++ b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
@@ -165,25 +165,6 @@
     }
 
     /**
-     * Logs that one or more apexd reverts have occurred, along with the crashing native process
-     * that caused apexd to revert during boot.
-     *
-     * @param context the context to use when determining the log packages
-     * @param failedPackageNames a list of names of packages which were reverted
-     * @param failingNativeProcess the crashing native process which caused a revert
-     */
-    public static void logApexdRevert(Context context, @NonNull List<String> failedPackageNames,
-            @NonNull String failingNativeProcess) {
-        Set<VersionedPackage> logPackages = getLogPackages(context, failedPackageNames);
-        for (VersionedPackage logPackage: logPackages) {
-            logEvent(logPackage,
-                    WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
-                    WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH_DURING_BOOT,
-                    failingNativeProcess);
-        }
-    }
-
-    /**
      * Log a Watchdog rollback event to statsd.
      *
      * @param logPackage the package to associate the rollback with.
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 60b5e65..91a17a9 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -599,13 +599,6 @@
             ComponentName component = it.next();
             ServiceState serviceState = userState.serviceStateMap.get(component);
             if (serviceState != null && serviceState.sessionTokens.isEmpty()) {
-                if (serviceState.callback != null) {
-                    try {
-                        serviceState.service.unregisterCallback(serviceState.callback);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in unregisterCallback", e);
-                    }
-                }
                 unbindService(serviceState);
                 it.remove();
             }
@@ -667,13 +660,6 @@
             // Unregister all callbacks and unbind all services.
             for (ServiceState serviceState : userState.serviceStateMap.values()) {
                 if (serviceState.service != null) {
-                    if (serviceState.callback != null) {
-                        try {
-                            serviceState.service.unregisterCallback(serviceState.callback);
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "error in unregisterCallback", e);
-                        }
-                    }
                     unbindService(serviceState);
                 }
             }
@@ -3571,12 +3557,19 @@
 
     @GuardedBy("mLock")
     private void unbindService(ServiceState serviceState) {
-        if (!serviceState.bound) {
+        if (serviceState == null || !serviceState.bound) {
             return;
         }
         if (DEBUG) {
             Slog.d(TAG, "unbindService(service=" + serviceState.component + ")");
         }
+        if (serviceState.callback != null) {
+            try {
+                serviceState.service.unregisterCallback(serviceState.callback);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "error in unregisterCallback", e);
+            }
+        }
         mContext.unbindService(serviceState.connection);
         serviceState.bound = false;
         serviceState.service = null;
@@ -3794,9 +3787,9 @@
                     if (serviceState.hardwareInputMap.containsKey(inputInfo.getId())) {
                         return;
                     }
-                    Slog.d("ServiceCallback",
-                            "addHardwareInput: device id " + deviceId + ", "
-                                    + inputInfo.toString());
+                    Slog.d(TAG, "ServiceCallback: addHardwareInput, deviceId: " + deviceId +
+                                ", inputInfo: " + inputInfo.toString() + " by " + mComponent +
+                                ", userId: " + mUserId);
                     mTvInputHardwareManager.addHardwareInput(deviceId, inputInfo);
                     addHardwareInputLocked(inputInfo, mComponent, mUserId);
                 }
@@ -3815,6 +3808,9 @@
                     if (serviceState.hardwareInputMap.containsKey(inputInfo.getId())) {
                         return;
                     }
+                    Slog.d(TAG, "ServiceCallback: addHdmiInput, id: " + id +
+                                ", inputInfo: "+ inputInfo.toString() + " by " + mComponent +
+                                ", userId: " + mUserId);
                     mTvInputHardwareManager.addHdmiInput(id, inputInfo);
                     addHardwareInputLocked(inputInfo, mComponent, mUserId);
                     if (mOnScreenInputId != null && mOnScreenSessionState != null) {
@@ -3845,8 +3841,8 @@
             final long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
-                    Slog.d("ServiceCallback",
-                            "removeHardwareInput " + inputId + " by " + mComponent);
+                    Slog.d(TAG, "ServiceCallback: removeHardwareInput, inputId: " + inputId +
+                                " by " + mComponent + ", userId: " + mUserId);
                     removeHardwareInputLocked(inputId, mUserId);
                 }
             } finally {
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index ecd140e..96a25da 100644
--- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -44,7 +44,6 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.annotations.VisibleForTesting.Visibility;
-import com.android.internal.telephony.flags.Flags;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
 
@@ -324,11 +323,8 @@
         if (SubscriptionManager.isValidSubscriptionId(subId)) {
             // Get only configs as needed to save memory.
             final PersistableBundle carrierConfig =
-                    Flags.fixCrashOnGettingConfigWhenPhoneIsGone()
-                            ? CarrierConfigManager.getCarrierConfigSubset(mContext, subId,
-                                    VcnManager.VCN_RELATED_CARRIER_CONFIG_KEYS)
-                            : mCarrierConfigManager.getConfigForSubId(subId,
-                                    VcnManager.VCN_RELATED_CARRIER_CONFIG_KEYS);
+                    CarrierConfigManager.getCarrierConfigSubset(mContext, subId,
+                            VcnManager.VCN_RELATED_CARRIER_CONFIG_KEYS);
             if (mDeps.isConfigForIdentifiedCarrier(carrierConfig)) {
                 mReadySubIdsBySlotId.put(slotId, subId);
 
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index f53dda6..4dcc6e1 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -3169,7 +3169,8 @@
                 final WallpaperDestinationChangeHandler
                         liveSync = new WallpaperDestinationChangeHandler(
                         newWallpaper);
-                boolean same = changingToSame(name, newWallpaper);
+                boolean same = changingToSame(name, newWallpaper.connection,
+                        newWallpaper.wallpaperComponent);
 
                 /*
                  * If we have a shared system+lock wallpaper, and we reapply the same wallpaper
@@ -3257,14 +3258,15 @@
         return name == null || name.equals(mDefaultWallpaperComponent);
     }
 
-    private boolean changingToSame(ComponentName componentName, WallpaperData wallpaper) {
-        if (wallpaper.connection != null) {
-            final ComponentName wallpaperName = wallpaper.wallpaperComponent;
-            if (isDefaultComponent(componentName) && isDefaultComponent(wallpaperName)) {
+    private boolean changingToSame(ComponentName newComponentName,
+            WallpaperConnection currentConnection, ComponentName currentComponentName) {
+        if (currentConnection != null) {
+            if (isDefaultComponent(newComponentName) && isDefaultComponent(currentComponentName)) {
                 if (DEBUG) Slog.v(TAG, "changingToSame: still using default");
                 // Still using default wallpaper.
                 return true;
-            } else if (wallpaperName != null && wallpaperName.equals(componentName)) {
+            } else if (currentComponentName != null && currentComponentName.equals(
+                    newComponentName)) {
                 // Changing to same wallpaper.
                 if (DEBUG) Slog.v(TAG, "same wallpaper");
                 return true;
@@ -3279,7 +3281,8 @@
             Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
         }
         // Has the component changed?
-        if (!force && changingToSame(componentName, wallpaper)) {
+        if (!force && changingToSame(componentName, wallpaper.connection,
+                wallpaper.wallpaperComponent)) {
             try {
                 if (DEBUG_LIVE) {
                     Slog.v(TAG, "Changing to the same component, ignoring");
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 99747e0..0be6471 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -8149,7 +8149,8 @@
      */
     @Override
     protected int getOverrideOrientation() {
-        if (mWmService.mConstants.mIgnoreActivityOrientationRequest) {
+        if (mWmService.mConstants.mIgnoreActivityOrientationRequest
+                && info.applicationInfo.category != ApplicationInfo.CATEGORY_GAME) {
             return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
         }
         return mAppCompatController.getOrientationPolicy()
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index b8ce02ed..3d6b64b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -130,35 +130,6 @@
     }
 
     /**
-     * Sleep tokens cause the activity manager to put the top activity to sleep.
-     * They are used by components such as dreams that may hide and block interaction
-     * with underlying activities.
-     * The Acquirer provides an interface that encapsulates the underlying work, so the user does
-     * not need to handle the token by him/herself.
-     */
-    public interface SleepTokenAcquirer {
-
-        /**
-         * Acquires a sleep token.
-         * @param displayId The display to apply to.
-         */
-        void acquire(int displayId);
-
-        /**
-         * Releases the sleep token.
-         * @param displayId The display to apply to.
-         */
-        void release(int displayId);
-    }
-
-    /**
-     * Creates a sleep token acquirer for the specified display with the specified tag.
-     *
-     * @param tag A string identifying the purpose (eg. "Dream").
-     */
-    public abstract SleepTokenAcquirer createSleepTokenAcquirer(@NonNull String tag);
-
-    /**
      * Returns home activity for the specified user.
      *
      * @param userId ID of the user or {@link android.os.UserHandle#USER_ALL}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index e25d940d..49ca698 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4356,6 +4356,7 @@
             mTaskOrganizerController.dump(pw, "  ");
             mVisibleActivityProcessTracker.dump(pw, "  ");
             mActiveUids.dump(pw, "  ");
+            pw.println("  SleepTokens=" + mRootWindowContainer.mSleepTokens);
             if (mDemoteTopAppReasons != 0) {
                 pw.println("  mDemoteTopAppReasons=" + mDemoteTopAppReasons);
             }
@@ -5071,17 +5072,16 @@
         EventLogTags.writeWmSetResumedActivity(r.mUserId, r.shortComponentName, reason);
     }
 
-    final class SleepTokenAcquirerImpl implements ActivityTaskManagerInternal.SleepTokenAcquirer {
+    final class SleepTokenAcquirer {
         private final String mTag;
         private final SparseArray<RootWindowContainer.SleepToken> mSleepTokens =
                 new SparseArray<>();
 
-        SleepTokenAcquirerImpl(@NonNull String tag) {
+        SleepTokenAcquirer(@NonNull String tag) {
             mTag = tag;
         }
 
-        @Override
-        public void acquire(int displayId) {
+        void acquire(int displayId) {
             synchronized (mGlobalLock) {
                 if (!mSleepTokens.contains(displayId)) {
                     mSleepTokens.append(displayId,
@@ -5091,8 +5091,7 @@
             }
         }
 
-        @Override
-        public void release(int displayId) {
+        void release(int displayId) {
             synchronized (mGlobalLock) {
                 final RootWindowContainer.SleepToken token = mSleepTokens.get(displayId);
                 if (token != null) {
@@ -5955,11 +5954,6 @@
     }
 
     final class LocalService extends ActivityTaskManagerInternal {
-        @Override
-        public SleepTokenAcquirer createSleepTokenAcquirer(@NonNull String tag) {
-            Objects.requireNonNull(tag);
-            return new SleepTokenAcquirerImpl(tag);
-        }
 
         @Override
         public ComponentName getHomeActivityForUser(int userId) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e8a3951..10e0641 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -735,8 +735,6 @@
 
     /** All tokens used to put activities on this root task to sleep (including mOffToken) */
     final ArrayList<RootWindowContainer.SleepToken> mAllSleepTokens = new ArrayList<>();
-    /** The token acquirer to put root tasks on the display to sleep */
-    private final ActivityTaskManagerInternal.SleepTokenAcquirer mOffTokenAcquirer;
 
     private boolean mSleeping;
 
@@ -1131,7 +1129,6 @@
         mDisplay = display;
         mDisplayId = display.getDisplayId();
         mCurrentUniqueDisplayId = display.getUniqueId();
-        mOffTokenAcquirer = mRootWindowContainer.mDisplayOffTokenAcquirer;
         mWallpaperController = new WallpaperController(mWmService, this);
         mWallpaperController.resetLargestDisplay(display);
         display.getDisplayInfo(mDisplayInfo);
@@ -6157,9 +6154,9 @@
         final int displayState = mDisplayInfo.state;
         if (displayId != DEFAULT_DISPLAY) {
             if (displayState == Display.STATE_OFF) {
-                mOffTokenAcquirer.acquire(mDisplayId);
+                mRootWindowContainer.mDisplayOffTokenAcquirer.acquire(mDisplayId);
             } else if (displayState == Display.STATE_ON) {
-                mOffTokenAcquirer.release(mDisplayId);
+                mRootWindowContainer.mDisplayOffTokenAcquirer.release(mDisplayId);
             }
             ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
                     "Content Recording: Display %d state was (%d), is now (%d), so update "
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 5c62120..107d31e 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -804,6 +804,14 @@
                     mAwake /* waiting */);
             if (!awake) {
                 onDisplaySwitchFinished();
+                // In case PhoneWindowManager's startedGoingToSleep is called after screenTurnedOff
+                // (the source caller is in order but the methods run on different threads) and
+                // updateScreenOffSleepToken was skipped by mIsGoingToSleepDefaultDisplay. Then
+                // acquire sleep token if screen is off.
+                if (!mScreenOnEarly && !mScreenOnFully && !mDisplayContent.isSleeping()) {
+                    Slog.w(TAG, "Late acquire sleep token for " + mDisplayContent);
+                    mService.mRoot.mDisplayOffTokenAcquirer.acquire(mDisplayContent.mDisplayId);
+                }
             }
         }
     }
@@ -851,6 +859,7 @@
     public void screenTurningOn(ScreenOnListener screenOnListener) {
         WindowProcessController visibleDozeUiProcess = null;
         synchronized (mLock) {
+            mService.mRoot.mDisplayOffTokenAcquirer.release(mDisplayContent.mDisplayId);
             mScreenOnEarly = true;
             mScreenOnFully = false;
             mKeyguardDrawComplete = false;
@@ -875,8 +884,12 @@
         onDisplaySwitchFinished();
     }
 
-    public void screenTurnedOff() {
+    /** It is called after {@link #screenTurningOn}. This runs on PowerManager's thread. */
+    public void screenTurnedOff(boolean acquireSleepToken) {
         synchronized (mLock) {
+            if (acquireSleepToken) {
+                mService.mRoot.mDisplayOffTokenAcquirer.acquire(mDisplayContent.mDisplayId);
+            }
             mScreenOnEarly = false;
             mScreenOnFully = false;
             mKeyguardDrawComplete = false;
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 5d8a96c..0c489d6 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -87,7 +87,7 @@
     private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
     private final ActivityTaskManagerService mService;
     private RootWindowContainer mRootWindowContainer;
-    private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer;
+    private final ActivityTaskManagerService.SleepTokenAcquirer mSleepTokenAcquirer;
     private boolean mWaitingForWakeTransition;
     private Transition.ReadyCondition mWaitAodHide = null;
 
@@ -95,7 +95,7 @@
             ActivityTaskSupervisor taskSupervisor) {
         mService = service;
         mTaskSupervisor = taskSupervisor;
-        mSleepTokenAcquirer = mService.new SleepTokenAcquirerImpl(KEYGUARD_SLEEP_TOKEN_TAG);
+        mSleepTokenAcquirer = mService.new SleepTokenAcquirer(KEYGUARD_SLEEP_TOKEN_TAG);
     }
 
     void setWindowManager(WindowManagerService windowManager) {
@@ -658,10 +658,10 @@
 
         private boolean mRequestDismissKeyguard;
         private final ActivityTaskManagerService mService;
-        private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer;
+        private final ActivityTaskManagerService.SleepTokenAcquirer mSleepTokenAcquirer;
 
         KeyguardDisplayState(ActivityTaskManagerService service, int displayId,
-                ActivityTaskManagerInternal.SleepTokenAcquirer acquirer) {
+                ActivityTaskManagerService.SleepTokenAcquirer acquirer) {
             mService = service;
             mDisplayId = displayId;
             mSleepTokenAcquirer = acquirer;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 866dcd5..8f5612c 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -215,7 +215,7 @@
     private static final String DISPLAY_OFF_SLEEP_TOKEN_TAG = "Display-off";
 
     /** The token acquirer to put root tasks on the displays to sleep */
-    final ActivityTaskManagerInternal.SleepTokenAcquirer mDisplayOffTokenAcquirer;
+    final ActivityTaskManagerService.SleepTokenAcquirer mDisplayOffTokenAcquirer;
 
     /**
      * The modes which affect which tasks are returned when calling
@@ -450,7 +450,7 @@
         mService = service.mAtmService;
         mTaskSupervisor = mService.mTaskSupervisor;
         mTaskSupervisor.mRootWindowContainer = this;
-        mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirerImpl(DISPLAY_OFF_SLEEP_TOKEN_TAG);
+        mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirer(DISPLAY_OFF_SLEEP_TOKEN_TAG);
         mDeviceStateController = new DeviceStateController(service.mContext, service.mGlobalLock);
         mDisplayRotationCoordinator = new DisplayRotationCoordinator();
     }
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index 5aa34d2..92953e5 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -17,6 +17,8 @@
 package com.android.server.wm;
 
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.window.TaskFragmentOrganizer.KEY_RESTORE_TASK_FRAGMENTS_INFO;
+import static android.window.TaskFragmentOrganizer.KEY_RESTORE_TASK_FRAGMENT_PARENT_INFO;
 import static android.window.TaskFragmentOrganizer.putErrorInfoInBundle;
 import static android.window.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENTED_TO_TASK;
 import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
@@ -206,7 +208,13 @@
             mOrganizerPid = pid;
             mAppThread = getAppThread(pid, mOrganizerUid);
             for (int i = mOrganizedTaskFragments.size() - 1; i >= 0; i--) {
-                mOrganizedTaskFragments.get(i).onTaskFragmentOrganizerRestarted(organizer);
+                final TaskFragment taskFragment = mOrganizedTaskFragments.get(i);
+                if (taskFragment.isAttached()
+                        && taskFragment.getTopNonFinishingActivity() != null) {
+                    taskFragment.onTaskFragmentOrganizerRestarted(organizer);
+                } else {
+                    mOrganizedTaskFragments.remove(taskFragment);
+                }
             }
             try {
                 mOrganizer.asBinder().linkToDeath(this, 0 /*flags*/);
@@ -575,8 +583,29 @@
         }
 
         mCachedTaskFragmentOrganizerStates.remove(cachedState);
-        outSavedState.putAll(cachedState.mSavedState);
         cachedState.restore(organizer, pid);
+        outSavedState.putAll(cachedState.mSavedState);
+
+        // Collect the organized TfInfo and TfParentInfo in the system.
+        final ArrayList<TaskFragmentInfo> infos = new ArrayList<>();
+        final ArrayMap<Integer, Task> tasks = new ArrayMap<>();
+        final int fragmentCount = cachedState.mOrganizedTaskFragments.size();
+        for (int j = 0; j < fragmentCount; j++) {
+            final TaskFragment tf = cachedState.mOrganizedTaskFragments.get(j);
+            infos.add(tf.getTaskFragmentInfo());
+            if (!tasks.containsKey(tf.getTask().mTaskId)) {
+                tasks.put(tf.getTask().mTaskId, tf.getTask());
+            }
+        }
+        outSavedState.putParcelableArrayList(KEY_RESTORE_TASK_FRAGMENTS_INFO, infos);
+
+        final ArrayList<TaskFragmentParentInfo> parentInfos = new ArrayList<>();
+        for (int j = tasks.size() - 1; j >= 0; j--) {
+            parentInfos.add(tasks.valueAt(j).getTaskFragmentParentInfo());
+        }
+        outSavedState.putParcelableArrayList(KEY_RESTORE_TASK_FRAGMENT_PARENT_INFO,
+                parentInfos);
+
         mTaskFragmentOrganizerState.put(organizer.asBinder(), cachedState);
         mPendingTaskFragmentEvents.put(organizer.asBinder(), new ArrayList<>());
         return true;
diff --git a/services/core/java/com/android/server/wm/WindowManagerConstants.java b/services/core/java/com/android/server/wm/WindowManagerConstants.java
index 47c42f4..e0f24d8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerConstants.java
+++ b/services/core/java/com/android/server/wm/WindowManagerConstants.java
@@ -34,7 +34,7 @@
  */
 final class WindowManagerConstants {
 
-    /** The orientation of activity will be always "unspecified". */
+    /** The orientation of activity will be always "unspecified" except for game apps. */
     private static final String KEY_IGNORE_ACTIVITY_ORIENTATION_REQUEST =
             "ignore_activity_orientation_request";
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 85e24c1..b6e45fc8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -14799,7 +14799,8 @@
     }
 
     @Override
-    public void setSecondaryLockscreenEnabled(ComponentName who, boolean enabled) {
+    public void setSecondaryLockscreenEnabled(ComponentName who, boolean enabled,
+            PersistableBundle options) {
         Objects.requireNonNull(who, "ComponentName is null");
 
         // Check can set secondary lockscreen enabled
@@ -18644,11 +18645,9 @@
 
         toggleBackupServiceActive(caller.getUserId(), enabled);
 
-        if (Flags.backupServiceSecurityLogEventEnabled()) {
-            if (SecurityLog.isLoggingEnabled()) {
-                SecurityLog.writeEvent(SecurityLog.TAG_BACKUP_SERVICE_TOGGLED,
-                        caller.getPackageName(), caller.getUserId(), enabled ? 1 : 0);
-            }
+        if (SecurityLog.isLoggingEnabled()) {
+            SecurityLog.writeEvent(SecurityLog.TAG_BACKUP_SERVICE_TOGGLED,
+                    caller.getPackageName(), caller.getUserId(), enabled ? 1 : 0);
         }
     }
 
diff --git a/services/tests/appfunctions/Android.bp b/services/tests/appfunctions/Android.bp
new file mode 100644
index 0000000..b5cf986
--- /dev/null
+++ b/services/tests/appfunctions/Android.bp
@@ -0,0 +1,59 @@
+// Copyright (C) 2024 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: "FrameworksAppFunctionsTests",
+    team: "trendy_team_machine_learning",
+    defaults: [
+        "modules-utils-testable-device-config-defaults",
+    ],
+
+    srcs: [
+        "src/**/*.kt",
+    ],
+
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.runner",
+        "androidx.test.ext.truth",
+        "platform-test-annotations",
+        "services.appfunctions",
+        "servicestests-core-utils",
+        "truth",
+        "frameworks-base-testutils",
+        "androidx.test.rules",
+    ],
+
+    libs: [
+        "android.test.base",
+        "android.test.runner",
+    ],
+
+    certificate: "platform",
+    platform_apis: true,
+    test_suites: ["device-tests"],
+
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/services/tests/appfunctions/AndroidManifest.xml b/services/tests/appfunctions/AndroidManifest.xml
new file mode 100644
index 0000000..1d42b17
--- /dev/null
+++ b/services/tests/appfunctions/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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="com.android.frameworks.appfunctionstests">
+
+    <application android:testOnly="true"
+                 android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.frameworks.appfunctionstests"
+        android:label="Frameworks AppFunctions Services Tests" />
+
+</manifest>
\ No newline at end of file
diff --git a/services/tests/appfunctions/AndroidTest.xml b/services/tests/appfunctions/AndroidTest.xml
new file mode 100644
index 0000000..0650120
--- /dev/null
+++ b/services/tests/appfunctions/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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 Frameworks AppFunctions Services Tests.">
+    <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="FrameworksAppFunctionsTests.apk" />
+    </target_preparer>
+
+    <option name="test-tag" value="FrameworksAppFunctionsTests" />
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.frameworks.appfunctionstests" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/services/tests/appfunctions/src/android/app/appfunctions/AppFunctionStaticMetadataHelperTest.kt b/services/tests/appfunctions/src/android/app/appfunctions/AppFunctionStaticMetadataHelperTest.kt
new file mode 100644
index 0000000..d8ce393
--- /dev/null
+++ b/services/tests/appfunctions/src/android/app/appfunctions/AppFunctionStaticMetadataHelperTest.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 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.appfunctions
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class AppFunctionStaticMetadataHelperTest {
+
+    @Test
+    fun getStaticSchemaNameForPackage() {
+        val actualSchemaName =
+            AppFunctionStaticMetadataHelper.getStaticSchemaNameForPackage("com.example.app")
+
+        assertThat(actualSchemaName).isEqualTo("AppFunctionStaticMetadata-com.example.app")
+    }
+
+    @Test
+    fun getDocumentIdForAppFunction() {
+        val packageName = "com.example.app"
+        val functionId = "someFunction"
+
+        val actualDocumentId =
+            AppFunctionStaticMetadataHelper.getDocumentIdForAppFunction(packageName, functionId)
+
+        assertThat(actualDocumentId).isEqualTo("com.example.app/someFunction")
+    }
+
+    @Test
+    fun getStaticMetadataQualifiedId() {
+        val packageName = "com.example.app"
+        val functionId = "someFunction"
+
+        val actualQualifiedId =
+            AppFunctionStaticMetadataHelper.getStaticMetadataQualifiedId(packageName, functionId)
+
+        assertThat(actualQualifiedId)
+            .isEqualTo("android\$apps-db/app_functions#com.example.app/someFunction")
+    }
+}
diff --git a/services/tests/appfunctions/src/com/android/server/appfunctions/FutureAppSearchSessionTest.kt b/services/tests/appfunctions/src/com/android/server/appfunctions/FutureAppSearchSessionTest.kt
new file mode 100644
index 0000000..a0f1a55
--- /dev/null
+++ b/services/tests/appfunctions/src/com/android/server/appfunctions/FutureAppSearchSessionTest.kt
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2023 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.appfunctions
+
+import android.app.appfunctions.AppFunctionRuntimeMetadata
+import android.app.appfunctions.AppFunctionRuntimeMetadata.APP_FUNCTION_RUNTIME_NAMESPACE
+import android.app.appfunctions.AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema
+import android.app.appfunctions.AppFunctionRuntimeMetadata.createParentAppFunctionRuntimeSchema
+import android.app.appsearch.AppSearchManager
+import android.app.appsearch.PutDocumentsRequest
+import android.app.appsearch.SearchSpec
+import android.app.appsearch.SetSchemaRequest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class FutureAppSearchSessionTest {
+    private val context = InstrumentationRegistry.getInstrumentation().targetContext
+    private val appSearchManager = context.getSystemService(AppSearchManager::class.java)
+    private val testExecutor = MoreExecutors.directExecutor()
+
+    @Before
+    @After
+    fun clearData() {
+        val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use {
+            val setSchemaRequest = SetSchemaRequest.Builder().setForceOverride(true).build()
+            it.setSchema(setSchemaRequest)
+        }
+    }
+
+    @Test
+    fun setSchema() {
+        val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+            val setSchemaRequest =
+                SetSchemaRequest.Builder()
+                    .addSchemas(
+                        createParentAppFunctionRuntimeSchema(),
+                        createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
+                    )
+                    .build()
+
+            val schema = session.setSchema(setSchemaRequest)
+
+            assertThat(schema.get()).isNotNull()
+        }
+    }
+
+    @Test
+    fun put() {
+        val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+            val setSchemaRequest =
+                SetSchemaRequest.Builder()
+                    .addSchemas(
+                        createParentAppFunctionRuntimeSchema(),
+                        createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
+                    )
+                    .build()
+            val schema = session.setSchema(setSchemaRequest)
+            assertThat(schema.get()).isNotNull()
+            val appFunctionRuntimeMetadata =
+                AppFunctionRuntimeMetadata.Builder(TEST_PACKAGE_NAME, TEST_FUNCTION_ID, "").build()
+            val putDocumentsRequest: PutDocumentsRequest =
+                PutDocumentsRequest.Builder()
+                    .addGenericDocuments(appFunctionRuntimeMetadata)
+                    .build()
+
+            val putResult = session.put(putDocumentsRequest)
+
+            assertThat(putResult.get().isSuccess).isTrue()
+        }
+    }
+
+    @Test
+    fun search() {
+        val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+            val setSchemaRequest =
+                SetSchemaRequest.Builder()
+                    .addSchemas(
+                        createParentAppFunctionRuntimeSchema(),
+                        createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
+                    )
+                    .build()
+            val schema = session.setSchema(setSchemaRequest)
+            assertThat(schema.get()).isNotNull()
+            val appFunctionRuntimeMetadata =
+                AppFunctionRuntimeMetadata.Builder(TEST_PACKAGE_NAME, TEST_FUNCTION_ID, "").build()
+            val putDocumentsRequest: PutDocumentsRequest =
+                PutDocumentsRequest.Builder()
+                    .addGenericDocuments(appFunctionRuntimeMetadata)
+                    .build()
+            val putResult = session.put(putDocumentsRequest)
+            assertThat(putResult.get().isSuccess).isTrue()
+
+            val searchResult = session.search("", SearchSpec.Builder().build())
+
+            val genericDocs =
+                searchResult.get().nextPage.get().stream().map { it.genericDocument }.toList()
+            assertThat(genericDocs).hasSize(1)
+            val foundAppFunctionRuntimeMetadata = AppFunctionRuntimeMetadata(genericDocs[0])
+            assertThat(foundAppFunctionRuntimeMetadata.functionId).isEqualTo(TEST_FUNCTION_ID)
+        }
+    }
+
+    @Test
+    fun getByDocumentId() {
+        val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+            val setSchemaRequest =
+                SetSchemaRequest.Builder()
+                    .addSchemas(
+                        createParentAppFunctionRuntimeSchema(),
+                        createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
+                    )
+                    .build()
+            val schema = session.setSchema(setSchemaRequest)
+            val appFunctionRuntimeMetadata =
+                AppFunctionRuntimeMetadata.Builder(TEST_PACKAGE_NAME, TEST_FUNCTION_ID, "").build()
+            val putDocumentsRequest: PutDocumentsRequest =
+                PutDocumentsRequest.Builder()
+                    .addGenericDocuments(appFunctionRuntimeMetadata)
+                    .build()
+            val putResult = session.put(putDocumentsRequest)
+
+            val genricDocument = session
+                .getByDocumentId(
+                    /* documentId= */ "${TEST_PACKAGE_NAME}/${TEST_FUNCTION_ID}",
+                    APP_FUNCTION_RUNTIME_NAMESPACE
+                )
+                .get()
+
+            val foundAppFunctionRuntimeMetadata = AppFunctionRuntimeMetadata(genricDocument)
+            assertThat(foundAppFunctionRuntimeMetadata.functionId).isEqualTo(TEST_FUNCTION_ID)
+        }
+    }
+
+    private companion object {
+        const val TEST_DB: String = "test_db"
+        const val TEST_PACKAGE_NAME: String = "test_pkg"
+        const val TEST_FUNCTION_ID: String = "print"
+    }
+}
diff --git a/services/tests/appfunctions/src/com/android/server/appfunctions/FutureGlobalSearchSessionTest.kt b/services/tests/appfunctions/src/com/android/server/appfunctions/FutureGlobalSearchSessionTest.kt
new file mode 100644
index 0000000..1fa55c7
--- /dev/null
+++ b/services/tests/appfunctions/src/com/android/server/appfunctions/FutureGlobalSearchSessionTest.kt
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2023 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.appfunctions
+
+import android.app.appfunctions.AppFunctionRuntimeMetadata
+import android.app.appfunctions.AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema
+import android.app.appfunctions.AppFunctionRuntimeMetadata.createParentAppFunctionRuntimeSchema
+import android.app.appsearch.AppSearchManager
+import android.app.appsearch.AppSearchManager.SearchContext
+import android.app.appsearch.PutDocumentsRequest
+import android.app.appsearch.SetSchemaRequest
+import android.app.appsearch.observer.DocumentChangeInfo
+import android.app.appsearch.observer.ObserverCallback
+import android.app.appsearch.observer.ObserverSpec
+import android.app.appsearch.observer.SchemaChangeInfo
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.internal.infra.AndroidFuture
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class FutureGlobalSearchSessionTest {
+    private val context = InstrumentationRegistry.getInstrumentation().targetContext
+    private val appSearchManager = context.getSystemService(AppSearchManager::class.java)
+    private val testExecutor = MoreExecutors.directExecutor()
+
+    @Before
+    @After
+    fun clearData() {
+        val searchContext = SearchContext.Builder(TEST_DB).build()
+        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use {
+            val setSchemaRequest = SetSchemaRequest.Builder().setForceOverride(true).build()
+            it.setSchema(setSchemaRequest)
+        }
+    }
+
+    @Test
+    fun registerDocumentChangeObserverCallback() {
+        val packageObserverSpec: ObserverSpec =
+            ObserverSpec.Builder()
+                .addFilterSchemas(
+                    AppFunctionRuntimeMetadata.getRuntimeSchemaNameForPackage(TEST_TARGET_PKG_NAME)
+                )
+                .build()
+        val settableDocumentChangeInfo: AndroidFuture<DocumentChangeInfo> = AndroidFuture()
+        val observer: ObserverCallback =
+            object : ObserverCallback {
+                override fun onSchemaChanged(changeInfo: SchemaChangeInfo) {}
+
+                override fun onDocumentChanged(changeInfo: DocumentChangeInfo) {
+                    settableDocumentChangeInfo.complete(changeInfo)
+                }
+            }
+        val futureGlobalSearchSession = FutureGlobalSearchSession(appSearchManager, testExecutor)
+
+        val registerPackageObserver: Void? =
+            futureGlobalSearchSession
+                .registerObserverCallbackAsync(
+                    TEST_TARGET_PKG_NAME,
+                    packageObserverSpec,
+                    testExecutor,
+                    observer,
+                )
+                .get()
+        assertThat(registerPackageObserver).isNull()
+        // Trigger document change
+        val searchContext = SearchContext.Builder(TEST_DB).build()
+        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+            val setSchemaRequest =
+                SetSchemaRequest.Builder()
+                    .addSchemas(
+                        createParentAppFunctionRuntimeSchema(),
+                        createAppFunctionRuntimeSchema(TEST_TARGET_PKG_NAME),
+                    )
+                    .build()
+            val schema = session.setSchema(setSchemaRequest)
+            assertThat(schema.get()).isNotNull()
+            val appFunctionRuntimeMetadata =
+                AppFunctionRuntimeMetadata.Builder(TEST_TARGET_PKG_NAME, TEST_FUNCTION_ID, "")
+                    .build()
+            val putDocumentsRequest: PutDocumentsRequest =
+                PutDocumentsRequest.Builder()
+                    .addGenericDocuments(appFunctionRuntimeMetadata)
+                    .build()
+            val putResult = session.put(putDocumentsRequest).get()
+            assertThat(putResult.isSuccess).isTrue()
+        }
+        assertThat(
+                settableDocumentChangeInfo
+                    .get()
+                    .changedDocumentIds
+                    .contains(
+                        AppFunctionRuntimeMetadata.getDocumentIdForAppFunction(
+                            TEST_TARGET_PKG_NAME,
+                            TEST_FUNCTION_ID,
+                        )
+                    )
+            )
+            .isTrue()
+    }
+
+    private companion object {
+        const val TEST_DB: String = "test_db"
+        const val TEST_TARGET_PKG_NAME = "com.android.frameworks.appfunctionstests"
+        const val TEST_FUNCTION_ID: String = "print"
+    }
+}
diff --git a/services/tests/appfunctions/src/com/android/server/appfunctions/MetadataSyncAdapterTest.kt b/services/tests/appfunctions/src/com/android/server/appfunctions/MetadataSyncAdapterTest.kt
new file mode 100644
index 0000000..1061da2
--- /dev/null
+++ b/services/tests/appfunctions/src/com/android/server/appfunctions/MetadataSyncAdapterTest.kt
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2023 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.appfunctions
+
+import android.app.appfunctions.AppFunctionRuntimeMetadata
+import android.app.appfunctions.AppFunctionRuntimeMetadata.PROPERTY_FUNCTION_ID
+import android.app.appfunctions.AppFunctionRuntimeMetadata.PROPERTY_PACKAGE_NAME
+import android.app.appsearch.AppSearchManager
+import android.app.appsearch.AppSearchManager.SearchContext
+import android.app.appsearch.PutDocumentsRequest
+import android.app.appsearch.SearchSpec
+import android.app.appsearch.SetSchemaRequest
+import android.util.ArrayMap
+import android.util.ArraySet
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class MetadataSyncAdapterTest {
+    private val context = InstrumentationRegistry.getInstrumentation().targetContext
+    private val appSearchManager = context.getSystemService(AppSearchManager::class.java)
+    private val testExecutor = MoreExecutors.directExecutor()
+
+    @Before
+    @After
+    fun clearData() {
+        val searchContext = SearchContext.Builder(TEST_DB).build()
+        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use {
+            val setSchemaRequest = SetSchemaRequest.Builder().setForceOverride(true).build()
+            it.setSchema(setSchemaRequest)
+        }
+    }
+
+    @Test
+    fun getPackageToFunctionIdMap() {
+        val searchContext: SearchContext = SearchContext.Builder(TEST_DB).build()
+        val functionRuntimeMetadata =
+            AppFunctionRuntimeMetadata.Builder(TEST_TARGET_PKG_NAME, "testFunctionId", "").build()
+        val setSchemaRequest =
+            SetSchemaRequest.Builder()
+                .addSchemas(AppFunctionRuntimeMetadata.createParentAppFunctionRuntimeSchema())
+                .addSchemas(
+                    AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema(TEST_TARGET_PKG_NAME)
+                )
+                .build()
+        val putDocumentsRequest: PutDocumentsRequest =
+            PutDocumentsRequest.Builder().addGenericDocuments(functionRuntimeMetadata).build()
+        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use {
+            val setSchemaResponse = it.setSchema(setSchemaRequest).get()
+            assertThat(setSchemaResponse).isNotNull()
+            val appSearchBatchResult = it.put(putDocumentsRequest).get()
+            assertThat(appSearchBatchResult.isSuccess).isTrue()
+        }
+
+        val metadataSyncAdapter =
+            MetadataSyncAdapter(
+                testExecutor,
+                FutureAppSearchSession(appSearchManager, testExecutor, searchContext),
+            )
+        val searchSpec: SearchSpec =
+            SearchSpec.Builder()
+                .addFilterSchemas(
+                    AppFunctionRuntimeMetadata.RUNTIME_SCHEMA_TYPE,
+                    AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema(TEST_TARGET_PKG_NAME)
+                        .schemaType,
+                )
+                .build()
+        val packageToFunctionIdMap =
+            metadataSyncAdapter.getPackageToFunctionIdMap(
+                "",
+                searchSpec,
+                PROPERTY_FUNCTION_ID,
+                PROPERTY_PACKAGE_NAME,
+            )
+
+        assertThat(packageToFunctionIdMap).isNotNull()
+        assertThat(packageToFunctionIdMap[TEST_TARGET_PKG_NAME]).containsExactly("testFunctionId")
+    }
+
+    @Test
+    fun getPackageToFunctionIdMap_multipleDocuments() {
+        val searchContext: SearchContext = SearchContext.Builder(TEST_DB).build()
+        val functionRuntimeMetadata =
+            AppFunctionRuntimeMetadata.Builder(TEST_TARGET_PKG_NAME, "testFunctionId", "").build()
+        val functionRuntimeMetadata1 =
+            AppFunctionRuntimeMetadata.Builder(TEST_TARGET_PKG_NAME, "testFunctionId1", "").build()
+        val functionRuntimeMetadata2 =
+            AppFunctionRuntimeMetadata.Builder(TEST_TARGET_PKG_NAME, "testFunctionId2", "").build()
+        val functionRuntimeMetadata3 =
+            AppFunctionRuntimeMetadata.Builder(TEST_TARGET_PKG_NAME, "testFunctionId3", "").build()
+        val setSchemaRequest =
+            SetSchemaRequest.Builder()
+                .addSchemas(AppFunctionRuntimeMetadata.createParentAppFunctionRuntimeSchema())
+                .addSchemas(
+                    AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema(TEST_TARGET_PKG_NAME)
+                )
+                .build()
+        val putDocumentsRequest: PutDocumentsRequest =
+            PutDocumentsRequest.Builder()
+                .addGenericDocuments(
+                    functionRuntimeMetadata,
+                    functionRuntimeMetadata1,
+                    functionRuntimeMetadata2,
+                    functionRuntimeMetadata3,
+                )
+                .build()
+        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use {
+            val setSchemaResponse = it.setSchema(setSchemaRequest).get()
+            assertThat(setSchemaResponse).isNotNull()
+            val appSearchBatchResult = it.put(putDocumentsRequest).get()
+            assertThat(appSearchBatchResult.isSuccess).isTrue()
+        }
+
+        val metadataSyncAdapter =
+            MetadataSyncAdapter(
+                testExecutor,
+                FutureAppSearchSession(appSearchManager, testExecutor, searchContext),
+            )
+        val searchSpec: SearchSpec =
+            SearchSpec.Builder()
+                .setResultCountPerPage(1)
+                .addFilterSchemas(
+                    AppFunctionRuntimeMetadata.RUNTIME_SCHEMA_TYPE,
+                    AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema(TEST_TARGET_PKG_NAME)
+                        .schemaType,
+                )
+                .build()
+        val packageToFunctionIdMap =
+            metadataSyncAdapter.getPackageToFunctionIdMap(
+                "",
+                searchSpec,
+                PROPERTY_FUNCTION_ID,
+                PROPERTY_PACKAGE_NAME,
+            )
+
+        assertThat(packageToFunctionIdMap).isNotNull()
+        assertThat(packageToFunctionIdMap[TEST_TARGET_PKG_NAME])
+            .containsExactly(
+                "testFunctionId",
+                "testFunctionId1",
+                "testFunctionId2",
+                "testFunctionId3",
+            )
+    }
+
+    @Test
+    fun getAddedFunctionsDiffMap_noDiff() {
+        val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+        staticPackageToFunctionMap.putAll(
+            mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+        )
+        val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> =
+            ArrayMap(staticPackageToFunctionMap)
+
+        val addedFunctionsDiffMap =
+            MetadataSyncAdapter.getAddedFunctionsDiffMap(
+                staticPackageToFunctionMap,
+                runtimePackageToFunctionMap,
+            )
+
+        assertThat(addedFunctionsDiffMap.isEmpty()).isEqualTo(true)
+    }
+
+    @Test
+    fun getAddedFunctionsDiffMap_addedFunction() {
+        val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+        staticPackageToFunctionMap.putAll(
+            mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1", "testFunction2")))
+        )
+        val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+        runtimePackageToFunctionMap.putAll(
+            mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+        )
+
+        val addedFunctionsDiffMap =
+            MetadataSyncAdapter.getAddedFunctionsDiffMap(
+                staticPackageToFunctionMap,
+                runtimePackageToFunctionMap,
+            )
+
+        assertThat(addedFunctionsDiffMap.size).isEqualTo(1)
+        assertThat(addedFunctionsDiffMap[TEST_TARGET_PKG_NAME]).containsExactly("testFunction2")
+    }
+
+    @Test
+    fun getAddedFunctionsDiffMap_addedFunctionNewPackage() {
+        val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+        staticPackageToFunctionMap.putAll(
+            mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+        )
+        val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+
+        val addedFunctionsDiffMap =
+            MetadataSyncAdapter.getAddedFunctionsDiffMap(
+                staticPackageToFunctionMap,
+                runtimePackageToFunctionMap,
+            )
+
+        assertThat(addedFunctionsDiffMap.size).isEqualTo(1)
+        assertThat(addedFunctionsDiffMap[TEST_TARGET_PKG_NAME]).containsExactly("testFunction1")
+    }
+
+    @Test
+    fun getAddedFunctionsDiffMap_removedFunction() {
+        val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+        val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+        runtimePackageToFunctionMap.putAll(
+            mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+        )
+
+        val addedFunctionsDiffMap =
+            MetadataSyncAdapter.getAddedFunctionsDiffMap(
+                staticPackageToFunctionMap,
+                runtimePackageToFunctionMap,
+            )
+
+        assertThat(addedFunctionsDiffMap.isEmpty()).isEqualTo(true)
+    }
+
+    @Test
+    fun getRemovedFunctionsDiffMap_noDiff() {
+        val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+        staticPackageToFunctionMap.putAll(
+            mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+        )
+        val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> =
+            ArrayMap(staticPackageToFunctionMap)
+
+        val removedFunctionsDiffMap =
+            MetadataSyncAdapter.getRemovedFunctionsDiffMap(
+                staticPackageToFunctionMap,
+                runtimePackageToFunctionMap,
+            )
+
+        assertThat(removedFunctionsDiffMap.isEmpty()).isEqualTo(true)
+    }
+
+    @Test
+    fun getRemovedFunctionsDiffMap_removedFunction() {
+        val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+        val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+        runtimePackageToFunctionMap.putAll(
+            mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+        )
+
+        val removedFunctionsDiffMap =
+            MetadataSyncAdapter.getRemovedFunctionsDiffMap(
+                staticPackageToFunctionMap,
+                runtimePackageToFunctionMap,
+            )
+
+        assertThat(removedFunctionsDiffMap.size).isEqualTo(1)
+        assertThat(removedFunctionsDiffMap[TEST_TARGET_PKG_NAME]).containsExactly("testFunction1")
+    }
+
+    @Test
+    fun getRemovedFunctionsDiffMap_addedFunction() {
+        val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+        staticPackageToFunctionMap.putAll(
+            mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+        )
+        val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+
+        val removedFunctionsDiffMap =
+            MetadataSyncAdapter.getRemovedFunctionsDiffMap(
+                staticPackageToFunctionMap,
+                runtimePackageToFunctionMap,
+            )
+
+        assertThat(removedFunctionsDiffMap.isEmpty()).isEqualTo(true)
+    }
+
+    private companion object {
+        const val TEST_DB: String = "test_db"
+        const val TEST_TARGET_PKG_NAME = "com.android.frameworks.appfunctionstests"
+    }
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 5bb8ded..52f1cbd 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -107,6 +107,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.MessageQueue;
+import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemProperties;
@@ -3053,6 +3054,74 @@
     }
 
     @Test
+    public void testBrightnessUpdates() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mShortMockedInjector);
+        DisplayManagerInternal localService = displayManager.new LocalService();
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        registerDefaultDisplays(displayManager);
+        initDisplayPowerController(localService);
+
+        final float invalidBrightness = -0.3f;
+        final float brightnessOff = -1.0f;
+        final float minimumBrightness = 0.0f;
+        final float validBrightness = 0.5f;
+
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS_MODE,
+                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+
+        // set and check valid brightness
+        waitForIdleHandler(mPowerHandler);
+        displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, validBrightness);
+        waitForIdleHandler(mPowerHandler);
+        assertEquals(validBrightness,
+                displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
+                FLOAT_TOLERANCE);
+
+        // set and check invalid brightness
+        waitForIdleHandler(mPowerHandler);
+        displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, invalidBrightness);
+        waitForIdleHandler(mPowerHandler);
+        assertEquals(PowerManager.BRIGHTNESS_MIN,
+                displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
+                FLOAT_TOLERANCE);
+
+        // reset and check valid brightness
+        waitForIdleHandler(mPowerHandler);
+        displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, validBrightness);
+        waitForIdleHandler(mPowerHandler);
+        assertEquals(validBrightness,
+                displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
+                FLOAT_TOLERANCE);
+
+        // set and check brightness off
+        waitForIdleHandler(mPowerHandler);
+        displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, brightnessOff);
+        waitForIdleHandler(mPowerHandler);
+        assertEquals(PowerManager.BRIGHTNESS_MIN,
+                displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
+                FLOAT_TOLERANCE);
+
+        // reset and check valid brightness
+        waitForIdleHandler(mPowerHandler);
+        displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, validBrightness);
+        waitForIdleHandler(mPowerHandler);
+        assertEquals(validBrightness,
+                displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
+                FLOAT_TOLERANCE);
+
+        // set and check minimum brightness
+        waitForIdleHandler(mPowerHandler);
+        displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, minimumBrightness);
+        waitForIdleHandler(mPowerHandler);
+        assertEquals(PowerManager.BRIGHTNESS_MIN,
+                displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
+                FLOAT_TOLERANCE);
+    }
+
+    @Test
     public void testResolutionChangeGetsBackedUp() throws Exception {
         when(mMockFlags.isResolutionBackupRestoreEnabled()).thenReturn(true);
         DisplayManagerService displayManager =
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java
index f9dc122..da79f30 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java
@@ -226,7 +226,7 @@
         float clampedBrightness = 0.6f;
         float customAnimationRate = 0.01f;
         when(mMockClamper.getBrightnessCap()).thenReturn(clampedBrightness);
-        when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.THERMAL);
+        when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.POWER);
         when(mMockClamper.getCustomAnimationRate()).thenReturn(customAnimationRate);
         when(mMockClamper.isActive()).thenReturn(false);
         mTestInjector.mCapturedChangeListener.onChanged();
@@ -250,7 +250,7 @@
         float clampedBrightness = 0.6f;
         float customAnimationRate = 0.01f;
         when(mMockClamper.getBrightnessCap()).thenReturn(clampedBrightness);
-        when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.THERMAL);
+        when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.POWER);
         when(mMockClamper.getCustomAnimationRate()).thenReturn(customAnimationRate);
         when(mMockClamper.isActive()).thenReturn(true);
         mTestInjector.mCapturedChangeListener.onChanged();
@@ -274,7 +274,7 @@
         float clampedBrightness = 0.8f;
         float customAnimationRate = 0.01f;
         when(mMockClamper.getBrightnessCap()).thenReturn(clampedBrightness);
-        when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.THERMAL);
+        when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.POWER);
         when(mMockClamper.getCustomAnimationRate()).thenReturn(customAnimationRate);
         when(mMockClamper.isActive()).thenReturn(true);
         mTestInjector.mCapturedChangeListener.onChanged();
@@ -298,7 +298,7 @@
         float clampedBrightness = 0.6f;
         float customAnimationRate = 0.01f;
         when(mMockClamper.getBrightnessCap()).thenReturn(clampedBrightness);
-        when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.THERMAL);
+        when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.POWER);
         when(mMockClamper.getCustomAnimationRate()).thenReturn(customAnimationRate);
         when(mMockClamper.isActive()).thenReturn(true);
         mTestInjector.mCapturedChangeListener.onChanged();
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalClamperTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalClamperTest.java
deleted file mode 100644
index 9d16594..0000000
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalClamperTest.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (C) 2023 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.display.brightness.clamper;
-
-import static com.android.server.display.config.DisplayDeviceConfigTestUtilsKt.createSensorData;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.verify;
-
-import android.hardware.display.DisplayManager;
-import android.os.IThermalEventListener;
-import android.os.IThermalService;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.Temperature;
-import android.provider.DeviceConfig;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.Keep;
-import com.android.server.display.DisplayDeviceConfig;
-import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData;
-import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel;
-import com.android.server.display.config.SensorData;
-import com.android.server.display.feature.DeviceConfigParameterProvider;
-import com.android.server.testutils.FakeDeviceConfigInterface;
-import com.android.server.testutils.TestHandler;
-
-import junitparams.JUnitParamsRunner;
-import junitparams.Parameters;
-
-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;
-
-import java.util.List;
-
-@RunWith(JUnitParamsRunner.class)
-public class BrightnessThermalClamperTest {
-
-    private static final float FLOAT_TOLERANCE = 0.001f;
-
-    private static final String DISPLAY_ID = "displayId";
-    @Mock
-    private IThermalService mMockThermalService;
-    @Mock
-    private BrightnessClamperController.ClamperChangeListener mMockClamperChangeListener;
-
-    private final FakeDeviceConfigInterface mFakeDeviceConfigInterface =
-            new FakeDeviceConfigInterface();
-    private final TestHandler mTestHandler = new TestHandler(null);
-    private BrightnessThermalClamper mClamper;
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mClamper = new BrightnessThermalClamper(new TestInjector(), mTestHandler,
-                mMockClamperChangeListener, new TestThermalData());
-        mTestHandler.flush();
-    }
-
-    @Test
-    public void testTypeIsThermal() {
-        assertEquals(BrightnessClamper.Type.THERMAL, mClamper.getType());
-    }
-
-    @Test
-    public void testNoThrottlingData() {
-        assertFalse(mClamper.isActive());
-        assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-    }
-
-    @Keep
-    private static Object[][] testThrottlingData() {
-        // throttlingLevels, throttlingStatus, expectedActive, expectedBrightness
-        return new Object[][] {
-                // no throttling data
-                {List.of(), Temperature.THROTTLING_LIGHT, false, PowerManager.BRIGHTNESS_MAX},
-                // throttlingStatus < min throttling data
-                {List.of(
-                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
-                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
-                        Temperature.THROTTLING_LIGHT, false, PowerManager.BRIGHTNESS_MAX},
-                // throttlingStatus = min throttling data
-                {List.of(
-                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
-                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
-                        Temperature.THROTTLING_MODERATE, true, 0.5f},
-                // throttlingStatus between min and max throttling data
-                {List.of(
-                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
-                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
-                        Temperature.THROTTLING_SEVERE, true, 0.5f},
-                // throttlingStatus = max throttling data
-                {List.of(
-                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
-                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
-                        Temperature.THROTTLING_CRITICAL, true, 0.1f},
-                // throttlingStatus > max throttling data
-                {List.of(
-                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
-                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
-                        Temperature.THROTTLING_EMERGENCY, true, 0.1f},
-        };
-    }
-    @Test
-    @Parameters(method = "testThrottlingData")
-    public void testNotifyThrottlingAfterOnDisplayChange(List<ThrottlingLevel> throttlingLevels,
-            @Temperature.ThrottlingStatus int throttlingStatus,
-            boolean expectedActive, float expectedBrightness) throws RemoteException {
-        IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
-        mClamper.onDisplayChanged(new TestThermalData(throttlingLevels));
-        mTestHandler.flush();
-        assertFalse(mClamper.isActive());
-        assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-
-        thermalEventListener.notifyThrottling(createSkinTemperature(throttlingStatus));
-        mTestHandler.flush();
-        assertEquals(expectedActive, mClamper.isActive());
-        assertEquals(expectedBrightness, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-    }
-
-    @Test
-    @Parameters(method = "testThrottlingData")
-    public void testOnDisplayChangeAfterNotifyThrottling(List<ThrottlingLevel> throttlingLevels,
-            @Temperature.ThrottlingStatus int throttlingStatus,
-            boolean expectedActive, float expectedBrightness) throws RemoteException {
-        IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
-        thermalEventListener.notifyThrottling(createSkinTemperature(throttlingStatus));
-        mTestHandler.flush();
-        assertFalse(mClamper.isActive());
-        assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-
-        mClamper.onDisplayChanged(new TestThermalData(throttlingLevels));
-        mTestHandler.flush();
-        assertEquals(expectedActive, mClamper.isActive());
-        assertEquals(expectedBrightness, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-    }
-
-    @Test
-    public void testOverrideData() throws RemoteException {
-        IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
-        thermalEventListener.notifyThrottling(createSkinTemperature(Temperature.THROTTLING_SEVERE));
-        mTestHandler.flush();
-        assertFalse(mClamper.isActive());
-        assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-
-        mClamper.onDisplayChanged(new TestThermalData(
-                List.of(new ThrottlingLevel(PowerManager.THERMAL_STATUS_SEVERE, 0.5f))));
-        mTestHandler.flush();
-        assertTrue(mClamper.isActive());
-        assertEquals(0.5f, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-
-        overrideThrottlingData("displayId,1,emergency,0.4");
-        mClamper.onDeviceConfigChanged();
-        mTestHandler.flush();
-
-        assertFalse(mClamper.isActive());
-        assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-
-        overrideThrottlingData("displayId,1,moderate,0.4");
-        mClamper.onDeviceConfigChanged();
-        mTestHandler.flush();
-
-        assertTrue(mClamper.isActive());
-        assertEquals(0.4f, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-    }
-
-    @Test
-    public void testDisplaySensorBasedThrottling() throws RemoteException {
-        final int severity = PowerManager.THERMAL_STATUS_SEVERE;
-        IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
-        // Update config to listen to display type sensor.
-        final SensorData tempSensor = createSensorData("DISPLAY", "VIRTUAL-SKIN-DISPLAY");
-        final TestThermalData thermalData =
-                    new TestThermalData(
-                        DISPLAY_ID,
-                        DisplayDeviceConfig.DEFAULT_ID,
-                        List.of(new ThrottlingLevel(severity, 0.5f)),
-                        tempSensor);
-        mClamper.onDisplayChanged(thermalData);
-        mTestHandler.flush();
-        verify(mMockThermalService).unregisterThermalEventListener(thermalEventListener);
-        thermalEventListener = captureThermalEventListener(Temperature.TYPE_DISPLAY);
-        assertFalse(mClamper.isActive());
-
-        // Verify no throttling triggered when any other sensor notification received.
-        thermalEventListener.notifyThrottling(createSkinTemperature(severity));
-        mTestHandler.flush();
-        assertFalse(mClamper.isActive());
-
-        thermalEventListener.notifyThrottling(createDisplayTemperature("OTHER-SENSOR", severity));
-        mTestHandler.flush();
-        assertFalse(mClamper.isActive());
-
-        assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-
-        // Verify throttling triggered when display sensor of given name throttled.
-        thermalEventListener.notifyThrottling(createDisplayTemperature(tempSensor.name, severity));
-        mTestHandler.flush();
-        assertTrue(mClamper.isActive());
-        assertEquals(0.5f, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-    }
-
-    private IThermalEventListener captureSkinThermalEventListener() throws RemoteException {
-        return captureThermalEventListener(Temperature.TYPE_SKIN);
-    }
-
-    private IThermalEventListener captureThermalEventListener(int type) throws RemoteException {
-        ArgumentCaptor<IThermalEventListener> captor = ArgumentCaptor.forClass(
-                IThermalEventListener.class);
-        verify(mMockThermalService).registerThermalEventListenerWithType(captor.capture(), eq(
-                type));
-        return captor.getValue();
-    }
-
-    private Temperature createDisplayTemperature(
-                @NonNull String sensorName, @Temperature.ThrottlingStatus int status) {
-        return new Temperature(100, Temperature.TYPE_DISPLAY, sensorName, status);
-    }
-
-    private Temperature createSkinTemperature(@Temperature.ThrottlingStatus int status) {
-        return new Temperature(100, Temperature.TYPE_SKIN, "test_temperature", status);
-    }
-
-    private void overrideThrottlingData(String data) {
-        mFakeDeviceConfigInterface.putProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
-                DisplayManager.DeviceConfig.KEY_BRIGHTNESS_THROTTLING_DATA, data);
-    }
-
-    private class TestInjector extends BrightnessThermalClamper.Injector {
-        @Override
-        IThermalService getThermalService() {
-            return mMockThermalService;
-        }
-
-        @Override
-        DeviceConfigParameterProvider getDeviceConfigParameterProvider() {
-            return new DeviceConfigParameterProvider(mFakeDeviceConfigInterface);
-        }
-    }
-
-    private static class TestThermalData implements BrightnessThermalClamper.ThermalData {
-
-        private final String mUniqueDisplayId;
-        private final String mDataId;
-        private final ThermalBrightnessThrottlingData mData;
-        private final SensorData mTempSensor;
-
-        private TestThermalData() {
-            this(DISPLAY_ID, DisplayDeviceConfig.DEFAULT_ID, null,
-                    SensorData.loadTempSensorUnspecifiedConfig());
-        }
-
-        private TestThermalData(List<ThrottlingLevel> data) {
-            this(DISPLAY_ID, DisplayDeviceConfig.DEFAULT_ID, data,
-                    SensorData.loadTempSensorUnspecifiedConfig());
-        }
-
-        private TestThermalData(String uniqueDisplayId, String dataId, List<ThrottlingLevel> data,
-                    SensorData tempSensor) {
-            mUniqueDisplayId = uniqueDisplayId;
-            mDataId = dataId;
-            mData = ThermalBrightnessThrottlingData.create(data);
-            mTempSensor = tempSensor;
-        }
-
-        @NonNull
-        @Override
-        public String getUniqueDisplayId() {
-            return mUniqueDisplayId;
-        }
-
-        @NonNull
-        @Override
-        public String getThermalThrottlingDataId() {
-            return mDataId;
-        }
-
-        @Nullable
-        @Override
-        public ThermalBrightnessThrottlingData getThermalBrightnessThrottlingData() {
-            return mData;
-        }
-
-        @NonNull
-        @Override
-        public SensorData getTempSensor() {
-            return mTempSensor;
-        }
-    }
-}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalModifierTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalModifierTest.java
new file mode 100644
index 0000000..35d384b
--- /dev/null
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalModifierTest.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2023 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.display.brightness.clamper;
+
+import static com.android.server.display.config.DisplayDeviceConfigTestUtilsKt.createSensorData;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.display.BrightnessInfo;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
+import android.os.IBinder;
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.Temperature;
+import android.provider.DeviceConfig;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.annotations.Keep;
+import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.DisplayDeviceConfig;
+import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData;
+import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel;
+import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.clamper.BrightnessClamperController.ModifiersAggregatedState;
+import com.android.server.display.config.SensorData;
+import com.android.server.display.feature.DeviceConfigParameterProvider;
+import com.android.server.testutils.FakeDeviceConfigInterface;
+import com.android.server.testutils.TestHandler;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+
+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;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RunWith(JUnitParamsRunner.class)
+public class BrightnessThermalModifierTest {
+    private static final int NO_MODIFIER = 0;
+
+    private static final float FLOAT_TOLERANCE = 0.001f;
+
+    private static final String DISPLAY_ID = "displayId";
+    @Mock
+    private IThermalService mMockThermalService;
+    @Mock
+    private BrightnessClamperController.ClamperChangeListener mMockClamperChangeListener;
+    @Mock
+    private DisplayManagerInternal.DisplayPowerRequest mMockRequest;
+    @Mock
+    private DisplayDeviceConfig mMockDisplayDeviceConfig;
+    @Mock
+    private IBinder mMockBinder;
+
+    private final FakeDeviceConfigInterface mFakeDeviceConfigInterface =
+            new FakeDeviceConfigInterface();
+    private final TestHandler mTestHandler = new TestHandler(null);
+    private BrightnessThermalModifier mModifier;
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mMockDisplayDeviceConfig.getTempSensor())
+                .thenReturn(SensorData.loadTempSensorUnspecifiedConfig());
+        mModifier = new BrightnessThermalModifier(new TestInjector(), mTestHandler,
+                mMockClamperChangeListener,
+                ClamperTestUtilsKt.createDisplayDeviceData(mMockDisplayDeviceConfig, mMockBinder));
+        mTestHandler.flush();
+    }
+
+
+    @Test
+    public void testNoThrottlingData() {
+        assertModifierState(
+                0.3f, true,
+                PowerManager.BRIGHTNESS_MAX, 0.3f,
+                false, true);
+    }
+
+    @Keep
+    private static Object[][] testThrottlingData() {
+        // throttlingLevels, throttlingStatus, expectedActive, expectedBrightness
+        return new Object[][] {
+                // no throttling data
+                {List.of(), Temperature.THROTTLING_LIGHT, false, PowerManager.BRIGHTNESS_MAX},
+                // throttlingStatus < min throttling data
+                {List.of(
+                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
+                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
+                        Temperature.THROTTLING_LIGHT, false, PowerManager.BRIGHTNESS_MAX},
+                // throttlingStatus = min throttling data
+                {List.of(
+                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
+                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
+                        Temperature.THROTTLING_MODERATE, true, 0.5f},
+                // throttlingStatus between min and max throttling data
+                {List.of(
+                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
+                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
+                        Temperature.THROTTLING_SEVERE, true, 0.5f},
+                // throttlingStatus = max throttling data
+                {List.of(
+                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
+                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
+                        Temperature.THROTTLING_CRITICAL, true, 0.1f},
+                // throttlingStatus > max throttling data
+                {List.of(
+                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
+                        new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
+                        Temperature.THROTTLING_EMERGENCY, true, 0.1f},
+        };
+    }
+    @Test
+    @Parameters(method = "testThrottlingData")
+    public void testNotifyThrottlingAfterOnDisplayChange(List<ThrottlingLevel> throttlingLevels,
+            @Temperature.ThrottlingStatus int throttlingStatus,
+            boolean expectedActive, float expectedBrightness) throws RemoteException {
+        IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
+        onDisplayChange(throttlingLevels);
+        mTestHandler.flush();
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+                false, true);
+
+        thermalEventListener.notifyThrottling(createSkinTemperature(throttlingStatus));
+        mTestHandler.flush();
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                expectedBrightness, expectedBrightness,
+                expectedActive, !expectedActive);
+    }
+
+    @Test
+    @Parameters(method = "testThrottlingData")
+    public void testOnDisplayChangeAfterNotifyThrottling(List<ThrottlingLevel> throttlingLevels,
+            @Temperature.ThrottlingStatus int throttlingStatus,
+            boolean expectedActive, float expectedBrightness) throws RemoteException {
+        IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
+        thermalEventListener.notifyThrottling(createSkinTemperature(throttlingStatus));
+        mTestHandler.flush();
+
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+                false, true);
+
+        onDisplayChange(throttlingLevels);
+        mTestHandler.flush();
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                expectedBrightness, expectedBrightness,
+                expectedActive, !expectedActive);
+    }
+
+    @Test
+    public void testAppliesFastChangeOnlyOnActivation() throws RemoteException  {
+        IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
+        onDisplayChange(List.of(new ThrottlingLevel(PowerManager.THERMAL_STATUS_SEVERE, 0.5f)));
+        mTestHandler.flush();
+
+        thermalEventListener.notifyThrottling(createSkinTemperature(Temperature.THROTTLING_SEVERE));
+        mTestHandler.flush();
+
+        // expectedSlowChange = false
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                0.5f, 0.5f,
+                true, false);
+
+        // slowChange is unchanged
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                0.5f, 0.5f,
+                true, true);
+    }
+
+    @Test
+    public void testCapsMaxBrightnessOnly_currentBrightnessIsLowAndFastChange()
+            throws RemoteException {
+        IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
+        onDisplayChange(List.of(new ThrottlingLevel(PowerManager.THERMAL_STATUS_SEVERE, 0.5f)));
+        mTestHandler.flush();
+
+        thermalEventListener.notifyThrottling(createSkinTemperature(Temperature.THROTTLING_SEVERE));
+        mTestHandler.flush();
+
+        assertModifierState(
+                0.1f, false,
+                0.5f, 0.1f,
+                true, false);
+    }
+
+    @Test
+    public void testOverrideData() throws RemoteException {
+        IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
+        thermalEventListener.notifyThrottling(createSkinTemperature(Temperature.THROTTLING_SEVERE));
+        mTestHandler.flush();
+
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+                false, true);
+
+        onDisplayChange(List.of(new ThrottlingLevel(PowerManager.THERMAL_STATUS_SEVERE, 0.5f)));
+        mTestHandler.flush();
+
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                0.5f, 0.5f,
+                true, false);
+
+        overrideThrottlingData("displayId,1,emergency,0.4");
+        mModifier.onDeviceConfigChanged();
+        mTestHandler.flush();
+
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+                false, true);
+
+        overrideThrottlingData("displayId,1,moderate,0.4");
+        mModifier.onDeviceConfigChanged();
+        mTestHandler.flush();
+
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                0.4f, 0.4f,
+                true, false);
+    }
+
+    @Test
+    public void testDisplaySensorBasedThrottling() throws RemoteException {
+        final int severity = PowerManager.THERMAL_STATUS_SEVERE;
+        IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
+        // Update config to listen to display type sensor.
+        SensorData tempSensor = createSensorData("DISPLAY", "VIRTUAL-SKIN-DISPLAY");
+
+        when(mMockDisplayDeviceConfig.getTempSensor()).thenReturn(tempSensor);
+        onDisplayChange(List.of(new ThrottlingLevel(severity, 0.5f)));
+        mTestHandler.flush();
+
+        verify(mMockThermalService).unregisterThermalEventListener(thermalEventListener);
+        thermalEventListener = captureThermalEventListener(Temperature.TYPE_DISPLAY);
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+                false, true);
+
+        // Verify no throttling triggered when any other sensor notification received.
+        thermalEventListener.notifyThrottling(createSkinTemperature(severity));
+        mTestHandler.flush();
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+                false, true);
+
+        thermalEventListener.notifyThrottling(createDisplayTemperature("OTHER-SENSOR", severity));
+        mTestHandler.flush();
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+                false, true);
+
+        // Verify throttling triggered when display sensor of given name throttled.
+        thermalEventListener.notifyThrottling(createDisplayTemperature(tempSensor.name, severity));
+        mTestHandler.flush();
+        assertModifierState(
+                PowerManager.BRIGHTNESS_MAX, true,
+                0.5f, 0.5f,
+                true, false);
+    }
+
+    private IThermalEventListener captureSkinThermalEventListener() throws RemoteException {
+        return captureThermalEventListener(Temperature.TYPE_SKIN);
+    }
+
+    private IThermalEventListener captureThermalEventListener(int type) throws RemoteException {
+        ArgumentCaptor<IThermalEventListener> captor = ArgumentCaptor.forClass(
+                IThermalEventListener.class);
+        verify(mMockThermalService).registerThermalEventListenerWithType(captor.capture(), eq(
+                type));
+        return captor.getValue();
+    }
+
+    private Temperature createDisplayTemperature(
+                @NonNull String sensorName, @Temperature.ThrottlingStatus int status) {
+        return new Temperature(100, Temperature.TYPE_DISPLAY, sensorName, status);
+    }
+
+    private Temperature createSkinTemperature(@Temperature.ThrottlingStatus int status) {
+        return new Temperature(100, Temperature.TYPE_SKIN, "test_temperature", status);
+    }
+
+    private void overrideThrottlingData(String data) {
+        mFakeDeviceConfigInterface.putProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+                DisplayManager.DeviceConfig.KEY_BRIGHTNESS_THROTTLING_DATA, data);
+    }
+
+    private void onDisplayChange(List<ThrottlingLevel> throttlingLevels) {
+        Map<String, ThermalBrightnessThrottlingData> throttlingLevelsMap = new HashMap<>();
+        throttlingLevelsMap.put(DisplayDeviceConfig.DEFAULT_ID,
+                ThermalBrightnessThrottlingData.create(throttlingLevels));
+        when(mMockDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId())
+                .thenReturn(throttlingLevelsMap);
+        mModifier.onDisplayChanged(ClamperTestUtilsKt.createDisplayDeviceData(
+                mMockDisplayDeviceConfig, mMockBinder, DISPLAY_ID, DisplayDeviceConfig.DEFAULT_ID));
+    }
+
+    private void assertModifierState(
+            float currentBrightness,
+            boolean currentSlowChange,
+            float maxBrightness, float brightness,
+            boolean isActive,
+            boolean isSlowChange) {
+        ModifiersAggregatedState modifierState = new ModifiersAggregatedState();
+        DisplayBrightnessState.Builder stateBuilder = DisplayBrightnessState.builder();
+        stateBuilder.setBrightness(currentBrightness);
+        stateBuilder.setIsSlowChange(currentSlowChange);
+
+        int maxBrightnessReason = isActive ? BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL
+                : BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
+        int modifier = isActive ? BrightnessReason.MODIFIER_THROTTLED : NO_MODIFIER;
+
+        mModifier.applyStateChange(modifierState);
+        assertThat(modifierState.mMaxBrightness).isEqualTo(maxBrightness);
+        assertThat(modifierState.mMaxBrightnessReason).isEqualTo(maxBrightnessReason);
+
+        mModifier.apply(mMockRequest, stateBuilder);
+
+        assertThat(stateBuilder.getMaxBrightness()).isWithin(FLOAT_TOLERANCE).of(maxBrightness);
+        assertThat(stateBuilder.getBrightness()).isWithin(FLOAT_TOLERANCE).of(brightness);
+        assertThat(stateBuilder.getBrightnessMaxReason()).isEqualTo(maxBrightnessReason);
+        assertThat(stateBuilder.getBrightnessReason().getModifier()).isEqualTo(modifier);
+        assertThat(stateBuilder.isSlowChange()).isEqualTo(isSlowChange);
+    }
+
+
+    private class TestInjector extends BrightnessThermalModifier.Injector {
+        @Override
+        IThermalService getThermalService() {
+            return mMockThermalService;
+        }
+
+        @Override
+        DeviceConfigParameterProvider getDeviceConfigParameterProvider() {
+            return new DeviceConfigParameterProvider(mFakeDeviceConfigInterface);
+        }
+    }
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/ClamperTestUtils.kt b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/ClamperTestUtils.kt
index 5fd848f..f21749e 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/ClamperTestUtils.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/ClamperTestUtils.kt
@@ -21,6 +21,7 @@
 import com.android.server.display.DisplayDeviceConfig
 import com.android.server.display.brightness.clamper.BrightnessClamperController.DisplayDeviceData
 
+@JvmOverloads
 fun createDisplayDeviceData(
     displayDeviceConfig: DisplayDeviceConfig,
     displayToken: IBinder,
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobParametersTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobParametersTest.java
new file mode 100644
index 0000000..c8e4f89
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobParametersTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2024 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.job;
+
+import static android.app.job.Flags.FLAG_CLEANUP_EMPTY_JOBS;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+
+import android.app.job.IJobCallback;
+import android.app.job.JobParameters;
+import android.net.Uri;
+import android.os.Parcel;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+public class JobParametersTest {
+    private static final String TAG = JobParametersTest.class.getSimpleName();
+    private static final int TEST_JOB_ID_1 = 123;
+    private static final String TEST_NAMESPACE = "TEST_NAMESPACE";
+    private static final String TEST_DEBUG_STOP_REASON = "TEST_DEBUG_STOP_REASON";
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
+    private MockitoSession mMockingSession;
+    @Mock private Parcel mMockParcel;
+    @Mock private IJobCallback.Stub mMockJobCallbackStub;
+
+    @Before
+    public void setUp() throws Exception {
+        mMockingSession =
+                mockitoSession().initMocks(this).strictness(Strictness.LENIENT).startMocking();
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockingSession != null) {
+            mMockingSession.finishMocking();
+        }
+
+        when(mMockParcel.readInt())
+                .thenReturn(TEST_JOB_ID_1) // Job ID
+                .thenReturn(0) // No clip data
+                .thenReturn(0) // No deadline expired
+                .thenReturn(0) // No network
+                .thenReturn(0) // No stop reason
+                .thenReturn(0); // Internal stop reason
+        when(mMockParcel.readString())
+                .thenReturn(TEST_NAMESPACE) // Job namespace
+                .thenReturn(TEST_DEBUG_STOP_REASON); // Debug stop reason
+        when(mMockParcel.readPersistableBundle()).thenReturn(null);
+        when(mMockParcel.readBundle()).thenReturn(null);
+        when(mMockParcel.readStrongBinder()).thenReturn(mMockJobCallbackStub);
+        when(mMockParcel.readBoolean())
+                .thenReturn(false) // expedited
+                .thenReturn(false); // user initiated
+        when(mMockParcel.createTypedArray(any())).thenReturn(new Uri[0]);
+        when(mMockParcel.createStringArray()).thenReturn(new String[0]);
+    }
+
+    /**
+     * Test to verify that the JobParameters created using Non-Parcelable constructor has not
+     * cleaner attached
+     */
+    @Test
+    public void testJobParametersNonParcelableConstructor_noCleaner() {
+        JobParameters jobParameters =
+                new JobParameters(
+                        null,
+                        TEST_NAMESPACE,
+                        TEST_JOB_ID_1,
+                        null,
+                        null,
+                        null,
+                        0,
+                        false,
+                        false,
+                        false,
+                        null,
+                        null,
+                        null);
+
+        // Verify that cleaner is not registered
+        assertThat(jobParameters.getCleanable()).isNull();
+        assertThat(jobParameters.getJobCleanupCallback()).isNull();
+    }
+
+    /**
+     * Test to verify that the JobParameters created using Parcelable constructor has not cleaner
+     * attached
+     */
+    @Test
+    public void testJobParametersParcelableConstructor_noCleaner() {
+        JobParameters jobParameters = JobParameters.CREATOR.createFromParcel(mMockParcel);
+
+        // Verify that cleaner is not registered
+        assertThat(jobParameters.getCleanable()).isNull();
+        assertThat(jobParameters.getJobCleanupCallback()).isNull();
+    }
+
+    /** Test to verify that the JobParameters Cleaner is disabled */
+    @RequiresFlagsEnabled(FLAG_CLEANUP_EMPTY_JOBS)
+    @Test
+    public void testCleanerWithLeakedJobCleanerDisabled_flagCleanupEmptyJobsEnabled() {
+        // Inject real JobCallbackCleanup
+        JobParameters jobParameters = JobParameters.CREATOR.createFromParcel(mMockParcel);
+
+        // Enable the cleaner
+        jobParameters.enableCleaner();
+
+        // Verify the cleaner is enabled
+        assertThat(jobParameters.getCleanable()).isNotNull();
+        assertThat(jobParameters.getJobCleanupCallback()).isNotNull();
+        assertThat(jobParameters.getJobCleanupCallback().isCleanerEnabled()).isTrue();
+
+        // Disable the cleaner
+        jobParameters.disableCleaner();
+
+        // Verify the cleaner is disabled
+        assertThat(jobParameters.getCleanable()).isNull();
+        assertThat(jobParameters.getJobCleanupCallback()).isNull();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
index 1cd61e9..e5005d1 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
@@ -44,6 +44,8 @@
 import android.graphics.PointF;
 import android.os.Looper;
 import android.os.SystemClock;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.testing.DexmakerShareClassLoaderRule;
 import android.view.InputDevice;
 import android.view.MotionEvent;
@@ -56,6 +58,7 @@
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.accessibility.AccessibilityTraceManager;
 import com.android.server.accessibility.EventStreamTransformation;
+import com.android.server.accessibility.Flags;
 import com.android.server.accessibility.utils.GestureLogParser;
 import com.android.server.testutils.OffsettableClock;
 
@@ -119,6 +122,9 @@
     public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
             new DexmakerShareClassLoaderRule();
 
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     /**
      * {@link TouchExplorer#sendDownForAllNotInjectedPointers} injecting events with the same object
      * is resulting {@link ArgumentCaptor} to capture events with last state. Before implementation
@@ -154,18 +160,43 @@
         mHandler = new TestHandler();
         mTouchExplorer = new TouchExplorer(mContext, mMockAms, null, mHandler);
         mTouchExplorer.setNext(mCaptor);
+        // Start TouchExplorer in the state where it has already reset InputDispatcher so that
+        // all tests do not start with an irrelevant ACTION_CANCEL.
+        mTouchExplorer.setHasResetInputDispatcherState(true);
     }
 
     @Test
     public void testOneFingerMove_shouldInjectHoverEvents() {
-        goFromStateClearTo(STATE_TOUCH_EXPLORING_1FINGER);
-        // Wait for transiting to touch exploring state.
+        triggerTouchExplorationWithOneFingerDownMoveUp();
+        assertCapturedEvents(ACTION_HOVER_ENTER, ACTION_HOVER_MOVE, ACTION_HOVER_EXIT);
+        assertState(STATE_TOUCH_EXPLORING);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_RESET_INPUT_DISPATCHER_BEFORE_FIRST_TOUCH_EXPLORATION)
+    public void testStartTouchExploration_shouldResetInputDispatcherStateWithActionCancel() {
+        // Start TouchExplorer in the state where it has *not yet* reset InputDispatcher.
+        mTouchExplorer.setHasResetInputDispatcherState(false);
+        // Trigger touch exploration twice, with a handler fast-forward in between so TouchExplorer
+        // treats these as two separate interactions.
+        triggerTouchExplorationWithOneFingerDownMoveUp();
+        mHandler.fastForward(2 * USER_INTENT_TIMEOUT);
+        triggerTouchExplorationWithOneFingerDownMoveUp();
+
+        assertCapturedEvents(
+                ACTION_CANCEL, // Only one ACTION_CANCEL before the first touch exploration
+                ACTION_HOVER_ENTER, ACTION_HOVER_MOVE, ACTION_HOVER_EXIT,
+                ACTION_HOVER_ENTER, ACTION_HOVER_MOVE, ACTION_HOVER_EXIT);
+        assertState(STATE_TOUCH_EXPLORING);
+    }
+
+    private void triggerTouchExplorationWithOneFingerDownMoveUp() {
+        send(downEvent());
+        // Fast forward so that TouchExplorer's timeouts transition us to the touch exploring state.
         mHandler.fastForward(2 * USER_INTENT_TIMEOUT);
         moveEachPointers(mLastEvent, p(10, 10));
         send(mLastEvent);
-        goToStateClearFrom(STATE_TOUCH_EXPLORING_1FINGER);
-        assertCapturedEvents(ACTION_HOVER_ENTER, ACTION_HOVER_MOVE, ACTION_HOVER_EXIT);
-        assertState(STATE_TOUCH_EXPLORING);
+        send(upEvent());
     }
 
     /**
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index 6b8e414..b4b3612 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -558,7 +558,9 @@
         waitForIdle();
         verify(mReceiver1).onError(
                 eq(BiometricAuthenticator.TYPE_NONE),
-                eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE),
+                eq(Flags.mandatoryBiometrics()
+                        ? BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS
+                        : BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE),
                 eq(0 /* vendorCode */));
 
         // Enrolled, not disabled in settings, user requires confirmation in settings
@@ -1450,7 +1452,9 @@
     }
 
     @Test
-    public void testCanAuthenticate_whenBiometricsNotEnabledForApps() throws Exception {
+    @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+    public void testCanAuthenticate_whenBiometricsNotEnabledForApps_returnsHardwareUnavailable()
+            throws Exception {
         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
         when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false);
         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
@@ -1468,6 +1472,25 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+    public void testCanAuthenticate_whenBiometricsNotEnabledForApps() throws Exception {
+        setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
+        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false);
+        when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
+                .thenReturn(true);
+
+        // When only biometric is requested
+        int authenticators = Authenticators.BIOMETRIC_STRONG;
+        assertEquals(BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS,
+                invokeCanAuthenticate(mBiometricService, authenticators));
+
+        // When credential and biometric are requested
+        authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL;
+        assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
+                invokeCanAuthenticate(mBiometricService, authenticators));
+    }
+
+    @Test
     public void testCanAuthenticate_whenNoBiometricSensor() throws Exception {
         mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider);
         mBiometricService.onStart();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
index 760d38e..b758f57 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
@@ -20,6 +20,7 @@
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
 import static android.hardware.biometrics.BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
+import static android.hardware.biometrics.BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS;
 
 import static com.android.server.biometrics.sensors.LockoutTracker.LOCKOUT_NONE;
 
@@ -266,6 +267,29 @@
 
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+    public void testCalculateByPriority()
+            throws Exception {
+        when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false);
+        when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false);
+
+        BiometricSensor faceSensor = getFaceSensor();
+        BiometricSensor fingerprintSensor = getFingerprintSensor();
+        PromptInfo promptInfo = new PromptInfo();
+        promptInfo.setConfirmationRequested(false /* requireConfirmation */);
+        promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
+        promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */);
+        PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+                mSettingObserver, List.of(faceSensor, fingerprintSensor),
+                0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
+                false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager);
+
+        assertThat(preAuthInfo.eligibleSensors).hasSize(0);
+        assertThat(preAuthInfo.getCanAuthenticateResult()).isEqualTo(
+                BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
     public void testMandatoryBiometricsNegativeButtonText_whenSet()
             throws Exception {
         when(mTrustManager.isInSignificantPlace()).thenReturn(false);
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
index 6ace9f1..fca0cfb 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
@@ -20,6 +20,7 @@
 
 import static com.android.server.hdmi.HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP;
 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_BOOT_UP;
+import static com.android.server.hdmi.HdmiCecFeatureAction.DELAY_GIVE_AUDIO_STATUS;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.TruthJUnit.assume;
@@ -582,6 +583,9 @@
         );
         mTestLooper.dispatchAll();
 
+        mTestLooper.moveTimeForward(DELAY_GIVE_AUDIO_STATUS);
+        mTestLooper.dispatchAll();
+
         assertThat(mNativeWrapper.getResultMessages()).contains(
                 HdmiCecMessageBuilder.buildUserControlPressed(getLogicalAddress(),
                         getSystemAudioDeviceLogicalAddress(), CEC_KEYCODE_VOLUME_UP));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/BaseTvToAudioSystemAvbTest.java b/services/tests/servicestests/src/com/android/server/hdmi/BaseTvToAudioSystemAvbTest.java
index 6731403..ec44a91 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/BaseTvToAudioSystemAvbTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/BaseTvToAudioSystemAvbTest.java
@@ -17,6 +17,7 @@
 package com.android.server.hdmi;
 
 import static com.android.server.hdmi.HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP;
+import static com.android.server.hdmi.HdmiCecFeatureAction.DELAY_GIVE_AUDIO_STATUS;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -223,6 +224,9 @@
         );
         mTestLooper.dispatchAll();
 
+        mTestLooper.moveTimeForward(DELAY_GIVE_AUDIO_STATUS);
+        mTestLooper.dispatchAll();
+
         assertThat(mNativeWrapper.getResultMessages()).contains(
                 HdmiCecMessageBuilder.buildUserControlPressed(getLogicalAddress(),
                         getSystemAudioDeviceLogicalAddress(), CEC_KEYCODE_VOLUME_UP));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index a5f1fcd..2d95740 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -30,6 +30,7 @@
 import static com.android.server.hdmi.HdmiControlService.WAKE_UP_SCREEN_ON;
 import static com.android.server.hdmi.RequestActiveSourceAction.TIMEOUT_WAIT_FOR_LAUNCHERX_API_CALL_MS;
 import static com.android.server.hdmi.RoutingControlAction.TIMEOUT_ROUTING_INFORMATION_MS;
+import static com.android.server.hdmi.RequestSadAction.RETRY_COUNTER_MAX;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -273,13 +274,12 @@
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
 
         // Finish querying SADs
-        assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
-        mNativeWrapper.clearResultMessages();
-        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
-        mTestLooper.dispatchAll();
-        assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
-        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
-        mTestLooper.dispatchAll();
+        for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+            assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+            mNativeWrapper.clearResultMessages();
+            mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+            mTestLooper.dispatchAll();
+        }
 
         assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
         mNativeWrapper.clearResultMessages();
@@ -685,18 +685,46 @@
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
 
         // Finish querying SADs
-        assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
-        mNativeWrapper.clearResultMessages();
-        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
-        mTestLooper.dispatchAll();
-        assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
-        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
-        mTestLooper.dispatchAll();
+        for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+            assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+            mNativeWrapper.clearResultMessages();
+            mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+            mTestLooper.dispatchAll();
+        }
 
         assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
     }
 
     @Test
+    public void handleInitiateArc_arcAlreadyEstablished_noRequestSad() {
+        // Emulate Audio device on port 0x2000 (supports ARC)
+        mNativeWrapper.setPortConnectionStatus(2, true);
+        HdmiCecMessage reportPhysicalAddress =
+                HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+                        ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
+        mNativeWrapper.onCecMessage(reportPhysicalAddress);
+        mTestLooper.dispatchAll();
+
+        assertThat(mHdmiCecLocalDeviceTv.isArcEstablished()).isFalse();
+
+        HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildInitiateArc(
+                ADDR_AUDIO_SYSTEM,
+                ADDR_TV);
+        mNativeWrapper.onCecMessage(requestArcInitiation);
+        mTestLooper.dispatchAll();
+
+        // Finish querying SADs
+        for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+            assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+            mNativeWrapper.clearResultMessages();
+            mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+            mTestLooper.dispatchAll();
+        }
+
+        assertThat(mHdmiCecLocalDeviceTv.isArcEstablished()).isTrue();
+    }
+
+    @Test
     public void handleTerminateArc_noAudioDevice() {
         HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
                 ADDR_AUDIO_SYSTEM,
@@ -970,13 +998,12 @@
         // <Report ARC Initiated> should only be sent after SAD querying is done
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
         // Finish querying SADs
-        assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
-        mNativeWrapper.clearResultMessages();
-        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
-        mTestLooper.dispatchAll();
-        assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
-        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
-        mTestLooper.dispatchAll();
+        for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+            assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+            mNativeWrapper.clearResultMessages();
+            mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+            mTestLooper.dispatchAll();
+        }
 
         assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
         mNativeWrapper.clearResultMessages();
@@ -1171,13 +1198,12 @@
         mTestLooper.dispatchAll();
 
         // Finish querying SADs
-        assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
-        mNativeWrapper.clearResultMessages();
-        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
-        mTestLooper.dispatchAll();
-        assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
-        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
-        mTestLooper.dispatchAll();
+        for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+            assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+            mNativeWrapper.clearResultMessages();
+            mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+            mTestLooper.dispatchAll();
+        }
 
         // ARC should be established after RequestSadAction is finished
         assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
@@ -1327,13 +1353,12 @@
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
 
         // Finish querying SADs
-        assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
-        mNativeWrapper.clearResultMessages();
-        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
-        mTestLooper.dispatchAll();
-        assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
-        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
-        mTestLooper.dispatchAll();
+        for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+            assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+            mNativeWrapper.clearResultMessages();
+            mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+            mTestLooper.dispatchAll();
+        }
 
         assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
     }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java
index f8e465c..4cf2937 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java
@@ -18,6 +18,7 @@
 
 import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
+import static com.android.server.hdmi.RequestSadAction.RETRY_COUNTER_MAX;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -144,7 +145,7 @@
     }
 
     @Test
-    public void noResponse_queryAgainOnce_emptyResult() {
+    public void noResponse_queryAgain_emptyResult() {
         RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
                 mCallback);
         action.start();
@@ -154,13 +155,13 @@
         HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
                 mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM,
                 CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
-        assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
-        mNativeWrapper.clearResultMessages();
-        mTestLooper.moveTimeForward(TIMEOUT_MS);
-        mTestLooper.dispatchAll();
-        assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
-        mTestLooper.moveTimeForward(TIMEOUT_MS);
-        mTestLooper.dispatchAll();
+
+        for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+            assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+            mNativeWrapper.clearResultMessages();
+            mTestLooper.moveTimeForward(TIMEOUT_MS);
+            mTestLooper.dispatchAll();
+        }
 
         assertThat(mSupportedSads).isNotNull();
         assertThat(mSupportedSads.size()).isEqualTo(0);
@@ -507,7 +508,7 @@
     }
 
     @Test
-    public void invalidMessageLength_queryAgainOnce() {
+    public void invalidMessageLength_queryAgain() {
         RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
                 mCallback);
         action.start();
@@ -524,16 +525,13 @@
                 0x27, 0x20, 0x0A};
         HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
                 Constants.ADDR_AUDIO_SYSTEM, mTvLogicalAddress, sadsToRespond_1);
-        assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
-        mNativeWrapper.clearResultMessages();
-        action.processCommand(response1);
-        mTestLooper.dispatchAll();
-        mTestLooper.moveTimeForward(TIMEOUT_MS);
-        mTestLooper.dispatchAll();
-        assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
-        mNativeWrapper.clearResultMessages();
-        mTestLooper.moveTimeForward(TIMEOUT_MS);
-        mTestLooper.dispatchAll();
+
+        for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+            assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+            mNativeWrapper.clearResultMessages();
+            mTestLooper.moveTimeForward(TIMEOUT_MS);
+            mTestLooper.dispatchAll();
+        }
 
         assertThat(mSupportedSads).isNotNull();
         assertThat(mSupportedSads.size()).isEqualTo(0);
diff --git a/services/tests/servicestests/src/com/android/server/rollback/ApexdRevertLoggerTest.java b/services/tests/servicestests/src/com/android/server/rollback/ApexdRevertLoggerTest.java
new file mode 100644
index 0000000..4aa6d39
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/rollback/ApexdRevertLoggerTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2024 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.rollback;
+
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class ApexdRevertLoggerTest {
+
+    private Context mMockContext = mock(Context.class);
+    private PackageManager mMockPm;
+    private PackageInfo mPackageInfo;
+
+    private static final String LOGGING_PARENT_KEY = "android.content.pm.LOGGING_PARENT";
+    private static final int PACKAGE_INFO_FLAGS = PackageManager.MATCH_APEX
+            | PackageManager.GET_META_DATA;
+    private static final List<String> sFailingPackages =
+            List.of("package1", "package2", "package3");
+
+    @Before
+    public void setUp() {
+        mMockPm = mock(PackageManager.class);
+        when(mMockContext.getPackageManager()).thenReturn(mMockPm);
+        PackageInstaller mockPi = mock(PackageInstaller.class);
+        when(mMockPm.getPackageInstaller()).thenReturn(mockPi);
+        PackageInstaller.SessionInfo mockSessionInfo = mock(PackageInstaller.SessionInfo.class);
+        when(mockPi.getSessionInfo(anyInt())).thenReturn(mockSessionInfo);
+        mPackageInfo = new PackageInfo();
+    }
+
+    /**
+     * Ensures that we make the correct Package Manager calls in the case that the failing packages
+     * are correctly configured with parent packages.
+     */
+    @Test
+    public void testApexdLoggingCallsWithParents() throws Exception {
+        for (String failingPackage: sFailingPackages) {
+            PackageInfo packageInfo = new PackageInfo();
+            ApplicationInfo applicationInfo = new ApplicationInfo();
+            Bundle bundle = new Bundle();
+            bundle.putString(LOGGING_PARENT_KEY, getParent(failingPackage));
+            applicationInfo.metaData = bundle;
+            packageInfo.applicationInfo = applicationInfo;
+            when(mMockPm.getPackageInfo(same(failingPackage), anyInt())).thenReturn(packageInfo);
+        }
+
+        when(mMockPm.getPackageInfo(anyString(), eq(0))).thenReturn(mPackageInfo);
+        ApexdRevertLogger.logApexdRevert(mMockContext, sFailingPackages, "test_process");
+        for (String failingPackage: sFailingPackages) {
+            verify(mMockPm, times(1)).getPackageInfo(failingPackage, PACKAGE_INFO_FLAGS);
+            verify(mMockPm, times(1)).getPackageInfo(getParent(failingPackage), 0);
+        }
+    }
+
+    /**
+     * Ensures that we don't make any calls to parent packages in the case that packages are not
+     * correctly configured with parent packages.
+     */
+    @Test
+    public void testApexdLoggingCallsWithNoParents() throws Exception {
+        for (String failingPackage: sFailingPackages) {
+            PackageInfo packageInfo = new PackageInfo();
+            packageInfo.applicationInfo = new ApplicationInfo();
+            when(mMockPm.getPackageInfo(same(failingPackage), anyInt())).thenReturn(packageInfo);
+        }
+        when(mMockPm.getPackageInfo(anyString(), eq(0))).thenReturn(mPackageInfo);
+
+        ApexdRevertLogger.logApexdRevert(mMockContext, sFailingPackages, "test_process");
+        verify(mMockPm, times(sFailingPackages.size())).getPackageInfo(anyString(), anyInt());
+        for (String failingPackage: sFailingPackages) {
+            verify(mMockPm, times(1)).getPackageInfo(failingPackage, PACKAGE_INFO_FLAGS);
+        }
+    }
+
+    private String getParent(String packageName) {
+        return packageName + "-parent";
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/rollback/WatchdogRollbackLoggerTest.java b/services/tests/servicestests/src/com/android/server/rollback/WatchdogRollbackLoggerTest.java
index d1c9643..8257168 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/WatchdogRollbackLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/WatchdogRollbackLoggerTest.java
@@ -20,7 +20,6 @@
 
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.same;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -139,52 +138,4 @@
         verify(mMockPm, times(1)).getPackageInfo(
                 sTestPackageV1.getPackageName(), PACKAGE_INFO_FLAGS);
     }
-
-    /**
-     * Ensures that we make the correct Package Manager calls in the case that the failing packages
-     * are correctly configured with parent packages.
-     */
-    @Test
-    public void testApexdLoggingCallsWithParents() throws Exception {
-        for (String failingPackage: sFailingPackages) {
-            PackageInfo packageInfo = new PackageInfo();
-            ApplicationInfo applicationInfo = new ApplicationInfo();
-            Bundle bundle = new Bundle();
-            bundle.putString(LOGGING_PARENT_KEY, getParent(failingPackage));
-            applicationInfo.metaData = bundle;
-            packageInfo.applicationInfo = applicationInfo;
-            when(mMockPm.getPackageInfo(same(failingPackage), anyInt())).thenReturn(packageInfo);
-        }
-
-        when(mMockPm.getPackageInfo(anyString(), eq(0))).thenReturn(mPackageInfo);
-        WatchdogRollbackLogger.logApexdRevert(mMockContext, sFailingPackages, "test_process");
-        for (String failingPackage: sFailingPackages) {
-            verify(mMockPm, times(1)).getPackageInfo(failingPackage, PACKAGE_INFO_FLAGS);
-            verify(mMockPm, times(1)).getPackageInfo(getParent(failingPackage), 0);
-        }
-    }
-
-    /**
-     * Ensures that we don't make any calls to parent packages in the case that packages are not
-     * correctly configured with parent packages.
-     */
-    @Test
-    public void testApexdLoggingCallsWithNoParents() throws Exception {
-        for (String failingPackage: sFailingPackages) {
-            PackageInfo packageInfo = new PackageInfo();
-            packageInfo.applicationInfo = new ApplicationInfo();
-            when(mMockPm.getPackageInfo(same(failingPackage), anyInt())).thenReturn(packageInfo);
-        }
-        when(mMockPm.getPackageInfo(anyString(), eq(0))).thenReturn(mPackageInfo);
-
-        WatchdogRollbackLogger.logApexdRevert(mMockContext, sFailingPackages, "test_process");
-        verify(mMockPm, times(sFailingPackages.size())).getPackageInfo(anyString(), anyInt());
-        for (String failingPackage: sFailingPackages) {
-            verify(mMockPm, times(1)).getPackageInfo(failingPackage, PACKAGE_INFO_FLAGS);
-        }
-    }
-
-    private String getParent(String packageName) {
-        return packageName + "-parent";
-    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
index 4a19973..1890879 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
@@ -39,6 +39,7 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
+import android.app.KeyguardManager;
 import android.app.UiModeManager;
 import android.app.WallpaperManager;
 import android.content.BroadcastReceiver;
@@ -78,6 +79,7 @@
     private DefaultDeviceEffectsApplier mApplier;
     @Mock PowerManager mPowerManager;
     @Mock ColorDisplayManager mColorDisplayManager;
+    @Mock KeyguardManager mKeyguardManager;
     @Mock UiModeManager mUiModeManager;
     @Mock WallpaperManager mWallpaperManager;
 
@@ -87,6 +89,7 @@
         mContext = spy(new TestableContext(InstrumentationRegistry.getContext(), null));
         mContext.addMockSystemService(PowerManager.class, mPowerManager);
         mContext.addMockSystemService(ColorDisplayManager.class, mColorDisplayManager);
+        mContext.addMockSystemService(KeyguardManager.class, mKeyguardManager);
         mContext.addMockSystemService(UiModeManager.class, mUiModeManager);
         mContext.addMockSystemService(WallpaperManager.class, mWallpaperManager);
         when(mWallpaperManager.isWallpaperSupported()).thenReturn(true);
@@ -311,6 +314,22 @@
     }
 
     @Test
+    @EnableFlags({android.app.Flags.FLAG_MODES_API, android.app.Flags.FLAG_MODES_UI})
+    public void apply_nightModeWithScreenOnAndKeyguardShowing_appliedImmediately(
+            @TestParameter ZenChangeOrigin origin) {
+
+        when(mPowerManager.isInteractive()).thenReturn(true);
+        when(mKeyguardManager.isKeyguardLocked()).thenReturn(true);
+
+        mApplier.apply(new ZenDeviceEffects.Builder().setShouldUseNightMode(true).build(),
+                origin.value());
+
+        // Effect was applied, and no broadcast receiver was registered.
+        verify(mUiModeManager).setAttentionModeThemeOverlay(eq(MODE_ATTENTION_THEME_OVERLAY_NIGHT));
+        verify(mContext, never()).registerReceiver(any(), any(), anyInt());
+    }
+
+    @Test
     @TestParameters({"{origin: ORIGIN_USER_IN_SYSTEMUI}", "{origin: ORIGIN_USER_IN_APP}",
             "{origin: ORIGIN_INIT}", "{origin: ORIGIN_INIT_USER}"})
     public void apply_nightModeWithScreenOn_appliedImmediatelyBasedOnOrigin(
diff --git a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
index e694c0b..536dcfb 100644
--- a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
@@ -42,7 +42,6 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.clearInvocations;
 
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
@@ -135,15 +134,13 @@
         doNothing().when(mPhoneWindowManager).initializeHdmiState();
         final boolean[] isScreenTurnedOff = { false };
         final DisplayPolicy displayPolicy = mock(DisplayPolicy.class);
-        doAnswer(invocation -> isScreenTurnedOff[0] = true).when(displayPolicy).screenTurnedOff();
+        doAnswer(invocation -> isScreenTurnedOff[0] = true).when(displayPolicy).screenTurnedOff(
+                anyBoolean());
         doAnswer(invocation -> !isScreenTurnedOff[0]).when(displayPolicy).isScreenOnEarly();
         doAnswer(invocation -> !isScreenTurnedOff[0]).when(displayPolicy).isScreenOnFully();
 
         mPhoneWindowManager.mDefaultDisplayPolicy = displayPolicy;
         mPhoneWindowManager.mDefaultDisplayRotation = mock(DisplayRotation.class);
-        final ActivityTaskManagerInternal.SleepTokenAcquirer tokenAcquirer =
-                mock(ActivityTaskManagerInternal.SleepTokenAcquirer.class);
-        doReturn(tokenAcquirer).when(mAtmInternal).createSleepTokenAcquirer(anyString());
         final PowerManager pm = mock(PowerManager.class);
         doReturn(true).when(pm).isInteractive();
         doReturn(pm).when(mContext).getSystemService(eq(Context.POWER_SERVICE));
@@ -155,9 +152,8 @@
         assertThat(mPhoneWindowManager.mIsGoingToSleepDefaultDisplay).isFalse();
 
         // Skip sleep-token for non-sleep-screen-off.
-        clearInvocations(tokenAcquirer);
         mPhoneWindowManager.screenTurnedOff(DEFAULT_DISPLAY, true /* isSwappingDisplay */);
-        verify(tokenAcquirer, never()).acquire(anyInt());
+        verify(displayPolicy).screenTurnedOff(false /* acquireSleepToken */);
         assertThat(isScreenTurnedOff[0]).isTrue();
 
         // Apply sleep-token for sleep-screen-off.
@@ -165,21 +161,10 @@
         mPhoneWindowManager.startedGoingToSleep(DEFAULT_DISPLAY, 0 /* reason */);
         assertThat(mPhoneWindowManager.mIsGoingToSleepDefaultDisplay).isTrue();
         mPhoneWindowManager.screenTurnedOff(DEFAULT_DISPLAY, true /* isSwappingDisplay */);
-        verify(tokenAcquirer).acquire(eq(DEFAULT_DISPLAY));
+        verify(displayPolicy).screenTurnedOff(true /* acquireSleepToken */);
 
         mPhoneWindowManager.finishedGoingToSleep(DEFAULT_DISPLAY, 0 /* reason */);
         assertThat(mPhoneWindowManager.mIsGoingToSleepDefaultDisplay).isFalse();
-
-        // Simulate unexpected reversed order: screenTurnedOff -> startedGoingToSleep. The sleep
-        // token can still be acquired.
-        isScreenTurnedOff[0] = false;
-        clearInvocations(tokenAcquirer);
-        mPhoneWindowManager.screenTurnedOff(DEFAULT_DISPLAY, true /* isSwappingDisplay */);
-        verify(tokenAcquirer, never()).acquire(anyInt());
-        assertThat(displayPolicy.isScreenOnEarly()).isFalse();
-        assertThat(displayPolicy.isScreenOnFully()).isFalse();
-        mPhoneWindowManager.startedGoingToSleep(DEFAULT_DISPLAY, 0 /* reason */);
-        verify(tokenAcquirer).acquire(eq(DEFAULT_DISPLAY));
     }
 
     @Test
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 1e035da..e2e76d6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -3231,7 +3231,7 @@
         mDisplayContent.mOpeningApps.remove(activity);
         mDisplayContent.mClosingApps.remove(activity);
         activity.commitVisibility(false /* visible */, false /* performLayout */);
-        mDisplayContent.getDisplayPolicy().screenTurnedOff();
+        mDisplayContent.getDisplayPolicy().screenTurnedOff(false /* acquireSleepToken */);
         final KeyguardController controller = mSupervisor.getKeyguardController();
         doReturn(true).when(controller).isKeyguardGoingAway(anyInt());
         activity.setVisibility(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index caeb41c..f32a234 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -284,11 +284,11 @@
         final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
         policy.addWindowLw(mNotificationShadeWindow, mNotificationShadeWindow.mAttrs);
 
-        policy.screenTurnedOff();
+        policy.screenTurnedOff(false /* acquireSleepToken */);
         policy.setAwake(false);
         policy.screenTurningOn(null /* screenOnListener */);
         assertTrue(wpc.isShowingUiWhileDozing());
-        policy.screenTurnedOff();
+        policy.screenTurnedOff(false /* acquireSleepToken */);
         assertFalse(wpc.isShowingUiWhileDozing());
 
         policy.screenTurningOn(null /* screenOnListener */);
@@ -393,7 +393,7 @@
                 info.logicalWidth, info.logicalHeight).mConfigFrame);
 
         // If screen is not fully turned on, then the cache should be preserved.
-        displayPolicy.screenTurnedOff();
+        displayPolicy.screenTurnedOff(false /* acquireSleepToken */);
         final TransitionController transitionController = mDisplayContent.mTransitionController;
         spyOn(transitionController);
         doReturn(true).when(transitionController).isCollecting();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index cc1805a..fd959b9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -242,7 +242,7 @@
 
         final Rect relStartBounds = new Rect(mTaskFragment.getRelativeEmbeddedBounds());
         final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
-        displayPolicy.screenTurnedOff();
+        displayPolicy.screenTurnedOff(false /* acquireSleepToken */);
 
         assertFalse(mTaskFragment.okToAnimate());
 
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index ff4be55..d89c9c1 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -2339,6 +2339,7 @@
      * @return True if the digits were processed as an MMI code, false otherwise.
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
     public boolean handleMmi(String dialString) {
         ITelecomService service = getTelecomService();
         if (service != null) {
@@ -2364,6 +2365,7 @@
      * @return True if the digits were processed as an MMI code, false otherwise.
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
     public boolean handleMmi(String dialString, PhoneAccountHandle accountHandle) {
         ITelecomService service = getTelecomService();
         if (service != null) {
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 112471b..c85374e 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -376,7 +376,8 @@
      */
     void requestLogMark(in String message);
 
-    void setTestPhoneAcctSuggestionComponent(String flattenedComponentName);
+    void setTestPhoneAcctSuggestionComponent(String flattenedComponentName,
+        in UserHandle userHandle);
 
     void setTestDefaultCallScreeningApp(String packageName);
 
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index f0850af..51e0c33 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1456,21 +1456,21 @@
     public static final int SERVICE_CAPABILITY_MAX = SERVICE_CAPABILITY_DATA;
 
     /**
-     * Bitmask for {@code SERVICE_CAPABILITY_VOICE}.
+     * Bitmask for {@link #SERVICE_CAPABILITY_VOICE}.
      * @hide
      */
     public static final int SERVICE_CAPABILITY_VOICE_BITMASK =
             serviceCapabilityToBitmask(SERVICE_CAPABILITY_VOICE);
 
     /**
-     * Bitmask for {@code SERVICE_CAPABILITY_SMS}.
+     * Bitmask for {@link #SERVICE_CAPABILITY_SMS}.
      * @hide
      */
     public static final int SERVICE_CAPABILITY_SMS_BITMASK =
             serviceCapabilityToBitmask(SERVICE_CAPABILITY_SMS);
 
     /**
-     * Bitmask for {@code SERVICE_CAPABILITY_DATA}.
+     * Bitmask for {@link #SERVICE_CAPABILITY_DATA}.
      * @hide
      */
     public static final int SERVICE_CAPABILITY_DATA_BITMASK =
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 3ff1e2c..3e226cc 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -6907,7 +6907,6 @@
         return false;
     }
 
-    // TODO(b/316183370): replace all @code with @link in javadoc after feature is released
     /**
      * @return true if the current device is "voice capable".
      * <p>
@@ -6921,10 +6920,10 @@
      * PackageManager.FEATURE_TELEPHONY system feature, which is available
      * on any device with a telephony radio, even if the device is
      * data-only.
-     * @deprecated Replaced by {@code #isDeviceVoiceCapable()}. Starting from Android 15, voice
+     * @deprecated Replaced by {@link #isDeviceVoiceCapable()}. Starting from Android 15, voice
      * capability may also be overridden by carriers for a given subscription. For voice capable
-     * device (when {@code #isDeviceVoiceCapable} return {@code true}), caller should check for
-     * subscription-level voice capability as well. See {@code #isDeviceVoiceCapable} for details.
+     * device (when {@link #isDeviceVoiceCapable} return {@code true}), caller should check for
+     * subscription-level voice capability as well. See {@link #isDeviceVoiceCapable} for details.
      */
     @Deprecated
     public boolean isVoiceCapable() {
@@ -6946,8 +6945,8 @@
      * <p>
      * Starting from Android 15, voice capability may also be overridden by carrier for a given
      * subscription on a voice capable device. To check if a subscription is "voice capable",
-     * call method {@code SubscriptionInfo#getServiceCapabilities()} and check if
-     * {@code SubscriptionManager#SERVICE_CAPABILITY_VOICE} is included.
+     * call method {@link SubscriptionInfo#getServiceCapabilities()} and check if
+     * {@link SubscriptionManager#SERVICE_CAPABILITY_VOICE} is included.
      *
      * @see SubscriptionInfo#getServiceCapabilities()
      */
@@ -6964,10 +6963,10 @@
      * <p>
      * Note: Voicemail waiting sms, cell broadcasting sms, and MMS are
      *       disabled when device doesn't support sms.
-     * @deprecated Replaced by {@code #isDeviceSmsCapable()}. Starting from Android 15, SMS
+     * @deprecated Replaced by {@link #isDeviceSmsCapable()}. Starting from Android 15, SMS
      * capability may also be overridden by carriers for a given subscription. For SMS capable
-     * device (when {@code #isDeviceSmsCapable} return {@code true}), caller should check for
-     * subscription-level SMS capability as well. See {@code #isDeviceSmsCapable} for details.
+     * device (when {@link #isDeviceSmsCapable} return {@code true}), caller should check for
+     * subscription-level SMS capability as well. See {@link #isDeviceSmsCapable} for details.
      */
     @Deprecated
     public boolean isSmsCapable() {
@@ -6986,8 +6985,8 @@
      * <p>
      * Starting from Android 15, SMS capability may also be overridden by carriers for a given
      * subscription on an SMS capable device. To check if a subscription is "SMS capable",
-     * call method {@code SubscriptionInfo#getServiceCapabilities()} and check if
-     * {@code SubscriptionManager#SERVICE_CAPABILITY_SMS} is included.
+     * call method {@link SubscriptionInfo#getServiceCapabilities()} and check if
+     * {@link SubscriptionManager#SERVICE_CAPABILITY_SMS} is included.
      *
      * @see SubscriptionInfo#getServiceCapabilities()
      */
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 3944b8e..284e2bd 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -420,6 +420,14 @@
     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
     public static final int SATELLITE_RESULT_DISABLE_IN_PROGRESS = 28;
 
+    /**
+     * Enabling satellite is in progress.
+     *
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    public static final int SATELLITE_RESULT_ENABLE_IN_PROGRESS = 29;
+
     /** @hide */
     @IntDef(prefix = {"SATELLITE_RESULT_"}, value = {
             SATELLITE_RESULT_SUCCESS,
@@ -450,7 +458,8 @@
             SATELLITE_RESULT_LOCATION_DISABLED,
             SATELLITE_RESULT_LOCATION_NOT_AVAILABLE,
             SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS,
-            SATELLITE_RESULT_DISABLE_IN_PROGRESS
+            SATELLITE_RESULT_DISABLE_IN_PROGRESS,
+            SATELLITE_RESULT_ENABLE_IN_PROGRESS
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SatelliteResult {}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index e852e6b..e57c207 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -3394,4 +3394,19 @@
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
     void provisionSatellite(in List<SatelliteSubscriberInfo> list, in ResultReceiver result);
+
+    /**
+     * This API can be used by only CTS to override the cached value for the device overlay config
+     * value :
+     * config_satellite_gateway_service_package and
+     * config_satellite_carrier_roaming_esos_provisioned_class.
+     * These values are set before sending an intent to broadcast there are any change to list of
+     * subscriber informations.
+     *
+     * @param name the name is one of the following that constitute an intent.
+     * Component package name, or component class name.
+     * @return {@code true} if the setting is successful, {@code false} otherwise.
+     * @hide
+     */
+    boolean setSatelliteSubscriberIdListChangedIntentComponent(in String name);
 }
diff --git a/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java
index ad0ef1b..0f08be2 100644
--- a/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java
+++ b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java
@@ -26,7 +26,9 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.graphics.Color;
 import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
 import android.testing.TestableContext;
 import android.view.MotionEvent;
 import android.view.View;
@@ -40,6 +42,8 @@
 
 import com.android.cts.input.MotionEventBuilder;
 import com.android.cts.input.PointerBuilder;
+import com.android.server.input.TouchpadFingerState;
+import com.android.server.input.TouchpadHardwareState;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -289,4 +293,36 @@
         assertEquals(initialX, mWindowLayoutParamsCaptor.getValue().x);
         assertEquals(initialY, mWindowLayoutParamsCaptor.getValue().y);
     }
+
+    @Test
+    public void testTouchpadClick() {
+        View child;
+
+        mTouchpadDebugView.updateHardwareState(
+                new TouchpadHardwareState(0, 1 /* buttonsDown */, 0, 0,
+                        new TouchpadFingerState[0]));
+
+        for (int i = 0; i < mTouchpadDebugView.getChildCount(); i++) {
+            child = mTouchpadDebugView.getChildAt(i);
+            assertEquals(((ColorDrawable) child.getBackground()).getColor(), Color.BLUE);
+        }
+
+        mTouchpadDebugView.updateHardwareState(
+                new TouchpadHardwareState(0, 0 /* buttonsDown */, 0, 0,
+                        new TouchpadFingerState[0]));
+
+        for (int i = 0; i < mTouchpadDebugView.getChildCount(); i++) {
+            child = mTouchpadDebugView.getChildAt(i);
+            assertEquals(((ColorDrawable) child.getBackground()).getColor(), Color.RED);
+        }
+
+        mTouchpadDebugView.updateHardwareState(
+                new TouchpadHardwareState(0, 1 /* buttonsDown */, 0, 0,
+                        new TouchpadFingerState[0]));
+
+        for (int i = 0; i < mTouchpadDebugView.getChildCount(); i++) {
+            child = mTouchpadDebugView.getChildAt(i);
+            assertEquals(((ColorDrawable) child.getBackground()).getColor(), Color.BLUE);
+        }
+    }
 }
diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
index 27cc923..e841d9e 100644
--- a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
@@ -16,8 +16,6 @@
 
 package com.android.internal.protolog;
 
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
@@ -30,7 +28,6 @@
 
 import static java.io.File.createTempFile;
 
-import android.content.Context;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
 import android.tools.ScenarioBuilder;
@@ -45,6 +42,7 @@
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.internal.protolog.ProtoLogConfigurationService.ViewerConfigFileTracer;
 import com.android.internal.protolog.common.IProtoLogGroup;
 import com.android.internal.protolog.common.LogDataType;
 import com.android.internal.protolog.common.LogLevel;
@@ -53,11 +51,11 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
 
 import perfetto.protos.Protolog;
 import perfetto.protos.ProtologCommon;
@@ -76,6 +74,7 @@
 @RunWith(JUnit4.class)
 public class PerfettoProtoLogImplTest {
     private static final String TEST_PROTOLOG_DATASOURCE_NAME = "test.android.protolog";
+    private static final String MOCK_VIEWER_CONFIG_FILE = "my/mock/viewer/config/file.pb";
     private final File mTracingDirectory = InstrumentationRegistry.getInstrumentation()
             .getTargetContext().getFilesDir();
 
@@ -92,29 +91,19 @@
             new TraceConfig(false, true, false)
     );
 
-    private ProtoLogConfigurationService mProtoLogConfigurationService;
-    private PerfettoProtoLogImpl mProtoLog;
-    private Protolog.ProtoLogViewerConfig.Builder mViewerConfigBuilder;
-    private File mFile;
-    private Runnable mCacheUpdater;
+    private static ProtoLogConfigurationService sProtoLogConfigurationService;
+    private static PerfettoProtoLogImpl sProtoLog;
+    private static Protolog.ProtoLogViewerConfig.Builder sViewerConfigBuilder;
+    private static Runnable sCacheUpdater;
 
-    private ProtoLogViewerConfigReader mReader;
+    private static ProtoLogViewerConfigReader sReader;
 
     public PerfettoProtoLogImplTest() throws IOException {
     }
 
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        final Context testContext = getInstrumentation().getContext();
-        mFile = testContext.getFileStreamPath("tracing_test.dat");
-        //noinspection ResultOfMethodCallIgnored
-        mFile.delete();
-
-        TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false);
-        TestProtoLogGroup.TEST_GROUP.setLogToProto(false);
-
-        mViewerConfigBuilder = Protolog.ProtoLogViewerConfig.newBuilder()
+    @BeforeClass
+    public static void setUp() throws Exception {
+        sViewerConfigBuilder = Protolog.ProtoLogViewerConfig.newBuilder()
                 .addGroups(
                         Protolog.ProtoLogViewerConfig.Group.newBuilder()
                                 .setId(1)
@@ -160,33 +149,52 @@
         ViewerConfigInputStreamProvider viewerConfigInputStreamProvider = Mockito.mock(
                 ViewerConfigInputStreamProvider.class);
         Mockito.when(viewerConfigInputStreamProvider.getInputStream())
-                .thenAnswer(it -> new ProtoInputStream(mViewerConfigBuilder.build().toByteArray()));
+                .thenAnswer(it -> new ProtoInputStream(sViewerConfigBuilder.build().toByteArray()));
 
-        mCacheUpdater = () -> {};
-        mReader = Mockito.spy(new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider));
+        sCacheUpdater = () -> {};
+        sReader = Mockito.spy(new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider));
 
         final ProtoLogDataSourceBuilder dataSourceBuilder =
                 (onStart, onFlush, onStop) -> new ProtoLogDataSource(
                         onStart, onFlush, onStop, TEST_PROTOLOG_DATASOURCE_NAME);
-        mProtoLogConfigurationService =
-                new ProtoLogConfigurationService(dataSourceBuilder);
-        mProtoLog = new PerfettoProtoLogImpl(
-                viewerConfigInputStreamProvider, mReader, () -> mCacheUpdater.run(),
-                TestProtoLogGroup.values(), dataSourceBuilder, mProtoLogConfigurationService);
+        final ViewerConfigFileTracer tracer = (dataSource, viewerConfigFilePath) -> {
+            Utils.dumpViewerConfig(dataSource, () -> {
+                if (!viewerConfigFilePath.equals(MOCK_VIEWER_CONFIG_FILE)) {
+                    throw new RuntimeException(
+                            "Unexpected viewer config file path provided");
+                }
+                return new ProtoInputStream(sViewerConfigBuilder.build().toByteArray());
+            });
+        };
+        sProtoLogConfigurationService = new ProtoLogConfigurationService(dataSourceBuilder, tracer);
+
+        if (android.tracing.Flags.clientSideProtoLogging()) {
+            sProtoLog = new PerfettoProtoLogImpl(
+                    MOCK_VIEWER_CONFIG_FILE, sReader, () -> sCacheUpdater.run(),
+                    TestProtoLogGroup.values(), dataSourceBuilder, sProtoLogConfigurationService);
+        } else {
+            sProtoLog = new PerfettoProtoLogImpl(
+                    viewerConfigInputStreamProvider, sReader, () -> sCacheUpdater.run(),
+                    TestProtoLogGroup.values(), dataSourceBuilder, sProtoLogConfigurationService);
+        }
+    }
+
+    @Before
+    public void before() {
+        Mockito.reset(sReader);
+
+        TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false);
+        TestProtoLogGroup.TEST_GROUP.setLogToProto(false);
     }
 
     @After
     public void tearDown() {
-        if (mFile != null) {
-            //noinspection ResultOfMethodCallIgnored
-            mFile.delete();
-        }
         ProtoLogImpl.setSingleInstance(null);
     }
 
     @Test
     public void isEnabled_returnsFalseByDefault() {
-        assertFalse(mProtoLog.isProtoEnabled());
+        assertFalse(sProtoLog.isProtoEnabled());
     }
 
     @Test
@@ -196,7 +204,7 @@
                 .build();
         try {
             traceMonitor.start();
-            assertTrue(mProtoLog.isProtoEnabled());
+            assertTrue(sProtoLog.isProtoEnabled());
         } finally {
             traceMonitor.stop(mWriter);
         }
@@ -209,12 +217,12 @@
                 .build();
         try {
             traceMonitor.start();
-            assertTrue(mProtoLog.isProtoEnabled());
+            assertTrue(sProtoLog.isProtoEnabled());
         } finally {
             traceMonitor.stop(mWriter);
         }
 
-        assertFalse(mProtoLog.isProtoEnabled());
+        assertFalse(sProtoLog.isProtoEnabled());
     }
 
     @Test
@@ -226,15 +234,15 @@
             traceMonitor.start();
             // Shouldn't be logging anything except WTF unless explicitly requested in the group
             // override.
-            mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+            sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
+            sProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
+            sProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
+            sProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
+            sProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
                     LogDataType.BOOLEAN, new Object[]{true});
         } finally {
             traceMonitor.stop(mWriter);
@@ -258,15 +266,15 @@
                 ).build();
         try {
             traceMonitor.start();
-            mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+            sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
+            sProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
+            sProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
+            sProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
+            sProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
                     LogDataType.BOOLEAN, new Object[]{true});
         } finally {
             traceMonitor.stop(mWriter);
@@ -294,15 +302,15 @@
                     ).build();
         try {
             traceMonitor.start();
-            mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+            sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
+            sProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
+            sProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
+            sProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
+            sProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
                     LogDataType.BOOLEAN, new Object[]{true});
         } finally {
             traceMonitor.stop(mWriter);
@@ -324,15 +332,15 @@
                 .build();
         try {
             traceMonitor.start();
-            mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+            sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
+            sProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
+            sProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
+            sProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
                     LogDataType.BOOLEAN, new Object[]{true});
-            mProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
+            sProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
                     LogDataType.BOOLEAN, new Object[]{true});
         } finally {
             traceMonitor.stop(mWriter);
@@ -351,8 +359,8 @@
 
     @Test
     public void log_logcatEnabled() {
-        when(mReader.getViewerString(anyLong())).thenReturn("test %b %d %% 0x%x %s %f");
-        PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog);
+        when(sReader.getViewerString(anyLong())).thenReturn("test %b %d %% 0x%x %s %f");
+        PerfettoProtoLogImpl implSpy = Mockito.spy(sProtoLog);
         TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true);
         TestProtoLogGroup.TEST_GROUP.setLogToProto(false);
 
@@ -363,13 +371,13 @@
         verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq(
                 LogLevel.INFO),
                 eq("test true 10000 % 0x7530 test 3.0E-6"));
-        verify(mReader).getViewerString(eq(1234L));
+        verify(sReader).getViewerString(eq(1234L));
     }
 
     @Test
     public void log_logcatEnabledInvalidMessage() {
-        when(mReader.getViewerString(anyLong())).thenReturn("test %b %d %% %x %s %f");
-        PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog);
+        when(sReader.getViewerString(anyLong())).thenReturn("test %b %d %% %x %s %f");
+        PerfettoProtoLogImpl implSpy = Mockito.spy(sProtoLog);
         TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true);
         TestProtoLogGroup.TEST_GROUP.setLogToProto(false);
 
@@ -381,29 +389,28 @@
                 LogLevel.INFO),
                 eq("FORMAT_ERROR \"test %b %d %% %x %s %f\", "
                         + "args=(true, 10000, 1.0E-4, 2.0E-5, test)"));
-        verify(mReader).getViewerString(eq(1234L));
+        verify(sReader).getViewerString(eq(1234L));
     }
 
     @Test
     public void log_logcatEnabledNoMessage() {
-        when(mReader.getViewerString(anyLong())).thenReturn(null);
-        PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog);
+        when(sReader.getViewerString(anyLong())).thenReturn(null);
+        PerfettoProtoLogImpl implSpy = Mockito.spy(sProtoLog);
         TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true);
         TestProtoLogGroup.TEST_GROUP.setLogToProto(false);
 
-        implSpy.log(
-                LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321,
+        implSpy.log(LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321,
                 new Object[]{5});
 
         verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq(
                 LogLevel.INFO), eq("UNKNOWN MESSAGE args = (5)"));
-        verify(mReader).getViewerString(eq(1234L));
+        verify(sReader).getViewerString(eq(1234L));
     }
 
     @Test
     public void log_logcatDisabled() {
-        when(mReader.getViewerString(anyLong())).thenReturn("test %d");
-        PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog);
+        when(sReader.getViewerString(anyLong())).thenReturn("test %d");
+        PerfettoProtoLogImpl implSpy = Mockito.spy(sProtoLog);
         TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false);
 
         implSpy.log(
@@ -411,7 +418,7 @@
                 new Object[]{5});
 
         verify(implSpy, never()).passToLogcat(any(), any(), any());
-        verify(mReader, never()).getViewerString(anyLong());
+        verify(sReader, never()).getViewerString(anyLong());
     }
 
     @Test
@@ -426,11 +433,12 @@
         long before;
         long after;
         try {
+            assertFalse(sProtoLog.isProtoEnabled());
             traceMonitor.start();
-            assertTrue(mProtoLog.isProtoEnabled());
+            assertTrue(sProtoLog.isProtoEnabled());
 
             before = SystemClock.elapsedRealtimeNanos();
-            mProtoLog.log(
+            sProtoLog.log(
                     LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, messageHash,
                     0b1110101001010100,
                     new Object[]{"test", 1, 2, 3, 0.4, 0.5, 0.6, true});
@@ -448,7 +456,8 @@
         Truth.assertThat(protolog.messages.getFirst().getTimestamp().getElapsedNanos())
                 .isAtMost(after);
         Truth.assertThat(protolog.messages.getFirst().getMessage())
-                .isEqualTo("My test message :: test, 2, 4, 6, 0.400000, 5.000000e-01, 0.6, true");
+                .isEqualTo(
+                        "My test message :: test, 1, 2, 3, 0.400000, 5.000000e-01, 0.6, true");
     }
 
     @Test
@@ -460,10 +469,10 @@
         long after;
         try {
             traceMonitor.start();
-            assertTrue(mProtoLog.isProtoEnabled());
+            assertTrue(sProtoLog.isProtoEnabled());
 
             before = SystemClock.elapsedRealtimeNanos();
-            mProtoLog.log(
+            sProtoLog.log(
                     LogLevel.INFO, TestProtoLogGroup.TEST_GROUP,
                     "My test message :: %s, %d, %x, %f, %b",
                     "test", 1, 3, 0.4, true);
@@ -481,7 +490,7 @@
         Truth.assertThat(protolog.messages.getFirst().getTimestamp().getElapsedNanos())
                 .isAtMost(after);
         Truth.assertThat(protolog.messages.getFirst().getMessage())
-                .isEqualTo("My test message :: test, 2, 6, 0.400000, true");
+                .isEqualTo("My test message :: test, 1, 3, 0.400000, true");
     }
 
     @Test
@@ -491,7 +500,7 @@
                 .build();
         try {
             traceMonitor.start();
-            mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+            sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
                     LogDataType.BOOLEAN, new Object[]{true});
         } finally {
             traceMonitor.stop(mWriter);
@@ -507,7 +516,7 @@
 
     private long addMessageToConfig(ProtologCommon.ProtoLogLevel logLevel, String message) {
         final long messageId = new Random().nextLong();
-        mViewerConfigBuilder.addMessages(Protolog.ProtoLogViewerConfig.MessageData.newBuilder()
+        sViewerConfigBuilder.addMessages(Protolog.ProtoLogViewerConfig.MessageData.newBuilder()
                 .setMessageId(messageId)
                 .setMessage(message)
                 .setLevel(logLevel)
@@ -530,7 +539,7 @@
         try {
             traceMonitor.start();
             before = SystemClock.elapsedRealtimeNanos();
-            mProtoLog.log(
+            sProtoLog.log(
                     LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, messageHash,
                     0b01100100,
                     new Object[]{"test", 1, 0.1, true});
@@ -550,7 +559,7 @@
                 .build();
         try {
             traceMonitor.start();
-            mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+            sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
                     0b11, new Object[]{true});
         } finally {
             traceMonitor.stop(mWriter);
@@ -575,7 +584,7 @@
         try {
             traceMonitor.start();
 
-            ProtoLogImpl.setSingleInstance(mProtoLog);
+            ProtoLogImpl.setSingleInstance(sProtoLog);
             ProtoLogImpl.d(TestProtoLogGroup.TEST_GROUP, 1,
                     0b11, true);
         } finally {
@@ -599,7 +608,7 @@
     @Test
     public void cacheIsUpdatedWhenTracesStartAndStop() {
         final AtomicInteger cacheUpdateCallCount = new AtomicInteger(0);
-        mCacheUpdater = cacheUpdateCallCount::incrementAndGet;
+        sCacheUpdater = cacheUpdateCallCount::incrementAndGet;
 
         PerfettoTraceMonitor traceMonitor1 = PerfettoTraceMonitor.newBuilder()
                 .enableProtoLog(true,
@@ -641,17 +650,17 @@
 
     @Test
     public void isEnabledUpdatesBasedOnRunningTraces() {
-        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+        Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
                 .isFalse();
-        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+        Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
                 .isFalse();
-        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+        Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
                 .isFalse();
-        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+        Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
                 .isFalse();
-        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+        Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
                 .isFalse();
-        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF)).isFalse();
+        Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF)).isFalse();
 
         PerfettoTraceMonitor traceMonitor1 =
                 PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
@@ -670,65 +679,65 @@
         try {
             traceMonitor1.start();
 
-            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+            Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
                     .isFalse();
-            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+            Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
                     .isFalse();
-            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+            Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
                     .isFalse();
-            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+            Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
                     .isTrue();
-            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+            Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
                     .isTrue();
-            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+            Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
                     .isTrue();
 
             try {
                 traceMonitor2.start();
 
-                Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+                Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
                         .isTrue();
-                Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP,
+                Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP,
                         LogLevel.VERBOSE)).isTrue();
-                Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+                Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
                         .isTrue();
-                Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+                Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
                         .isTrue();
-                Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+                Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
                         .isTrue();
-                Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+                Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
                         .isTrue();
             } finally {
                 traceMonitor2.stop(mWriter);
             }
 
-            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+            Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
                     .isFalse();
-            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+            Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
                     .isFalse();
-            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+            Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
                     .isFalse();
-            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+            Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
                     .isTrue();
-            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+            Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
                     .isTrue();
-            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+            Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
                     .isTrue();
         } finally {
             traceMonitor1.stop(mWriter);
         }
 
-        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+        Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
                 .isFalse();
-        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+        Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
                 .isFalse();
-        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+        Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
                 .isFalse();
-        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+        Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
                 .isFalse();
-        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+        Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
                 .isFalse();
-        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+        Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
                 .isFalse();
     }
 
@@ -741,7 +750,7 @@
         try {
             traceMonitor.start();
 
-            mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
+            sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
                     "My test null string: %s", (Object) null);
         } finally {
             traceMonitor.stop(mWriter);
@@ -764,7 +773,7 @@
         try {
             traceMonitor.start();
 
-            mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
+            sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
                     "My null args: %d, %f, %b", null, null, null);
         } finally {
             traceMonitor.stop(mWriter);
@@ -775,7 +784,7 @@
 
         Truth.assertThat(protolog.messages).hasSize(1);
         Truth.assertThat(protolog.messages.get(0).getMessage())
-                .isEqualTo("My null args: 0, 0, false");
+                .isEqualTo("My null args: 0, 0.000000, false");
     }
 
     @Test
@@ -798,7 +807,7 @@
             traceMonitor1.start();
             traceMonitor2.start();
 
-            mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+            sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
                     LogDataType.BOOLEAN, new Object[]{true});
         } finally {
             traceMonitor1.stop(mWriter);
@@ -827,12 +836,12 @@
                 .build();
         try {
             traceMonitor.start();
-            mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
-                "This message should not be logged");
-            mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP,
-                "This message should logged %d", 123);
-            mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP,
-                "This message should also be logged %d", 567);
+            sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
+                    "This message should not be logged");
+            sProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP,
+                    "This message should be logged %d", 123);
+            sProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP,
+                    "This message should also be logged %d", 567);
         } finally {
             traceMonitor.stop(mWriter);
         }
@@ -845,7 +854,7 @@
         Truth.assertThat(protolog.messages.get(0).getLevel())
                 .isEqualTo(LogLevel.WARN);
         Truth.assertThat(protolog.messages.get(0).getMessage())
-                .isEqualTo("This message should logged 123");
+                .isEqualTo("This message should be logged 123");
 
         Truth.assertThat(protolog.messages.get(1).getLevel())
                 .isEqualTo(LogLevel.ERROR);
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
index 887630b..b5cc553 100644
--- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -59,7 +59,6 @@
 import android.os.ParcelUuid;
 import android.os.PersistableBundle;
 import android.os.test.TestLooper;
-import android.platform.test.flag.junit.SetFlagsRule;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -73,10 +72,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.internal.telephony.flags.Flags;
-
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -133,8 +129,6 @@
         TEST_SUBID_TO_CARRIER_CONFIG_MAP = Collections.unmodifiableMap(subIdToCarrierConfigMap);
     }
 
-    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
 
     @NonNull private final Context mContext;
     @NonNull private final TestLooper mTestLooper;
@@ -193,7 +187,6 @@
 
     @Before
     public void setUp() throws Exception {
-        mSetFlagsRule.enableFlags(Flags.FLAG_FIX_CRASH_ON_GETTING_CONFIG_WHEN_PHONE_IS_GONE);
         doReturn(2).when(mTelephonyManager).getActiveModemCount();
 
         mCallback = mock(TelephonySubscriptionTrackerCallback.class);
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index 5e0f87f..60c4bf5 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -292,13 +292,12 @@
             }
             if (!hasData) {
                 const String8& srcName = file->getSourceFile();
-                time_t fileModWhen;
-                fileModWhen = getFileModDate(srcName.c_str());
-                if (fileModWhen == (time_t) -1) { // file existence tested earlier,
-                    return false;                 //  not expecting an error here
+                auto fileModWhen = getFileModDate(srcName.c_str());
+                if (fileModWhen == kInvalidModDate) { // file existence tested earlier,
+                    return false;                     //  not expecting an error here
                 }
-    
-                if (fileModWhen > entry->getModWhen()) {
+
+                if (toTimeT(fileModWhen) > entry->getModWhen()) {
                     // mark as deleted so add() will succeed
                     if (bundle->getVerbose()) {
                         printf("      (removing old '%s')\n", storageName.c_str());
diff --git a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRedirect.java
similarity index 76%
copy from ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java
copy to tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRedirect.java
index 4b9cf85..bc9471b 100644
--- a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRedirect.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -13,9 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.ravenwood.annotation;
+package android.hosttest.annotation;
 
-import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -24,13 +24,9 @@
 /**
  * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
  * QUESTIONS ABOUT IT.
- *
- * TODO: Javadoc
- *
  * @hide
  */
-@Target({TYPE})
+@Target({METHOD})
 @Retention(RetentionPolicy.CLASS)
-public @interface RavenwoodNativeSubstitutionClass {
-    String value();
+public @interface HostSideTestRedirect {
 }
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRedirectionClass.java
similarity index 95%
rename from tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java
rename to tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRedirectionClass.java
index 9c81383..28ad236 100644
--- a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRedirectionClass.java
@@ -30,6 +30,6 @@
  */
 @Target({TYPE})
 @Retention(RetentionPolicy.CLASS)
-public @interface HostSideTestNativeSubstitutionClass {
+public @interface HostSideTestRedirectionClass {
     String value();
 }
diff --git a/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
index e72c9a4..eba8e62 100644
--- a/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
+++ b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
@@ -27,8 +27,11 @@
 --substitute-annotation
     android.hosttest.annotation.HostSideTestSubstitute
 
---native-substitute-annotation
-    android.hosttest.annotation.HostSideTestNativeSubstitutionClass
+--redirect-annotation
+    android.hosttest.annotation.HostSideTestRedirect
+
+--redirection-class-annotation
+    android.hosttest.annotation.HostSideTestRedirectionClass
 
 --class-load-hook-annotation
     android.hosttest.annotation.HostSideTestClassLoadHook
diff --git a/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh b/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh
index 5f0368a..084448d 100755
--- a/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh
+++ b/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh
@@ -100,8 +100,10 @@
           android.hosttest.annotation.HostSideTestRemove \
       --substitute-annotation \
           android.hosttest.annotation.HostSideTestSubstitute \
-      --native-substitute-annotation \
-          android.hosttest.annotation.HostSideTestNativeSubstitutionClass \
+      --redirect-annotation \
+          android.hosttest.annotation.HostSideTestRedirect \
+      --redirection-class-annotation \
+          android.hosttest.annotation.HostSideTestRedirectionClass \
       --class-load-hook-annotation \
           android.hosttest.annotation.HostSideTestClassLoadHook \
       --keep-static-initializer-annotation \
@@ -223,4 +225,4 @@
 
 
 echo "All tests passed"
-exit 0
\ No newline at end of file
+exit 0
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
index 0f38fe7..34aaaa9 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -24,8 +24,9 @@
 import com.android.hoststubgen.filters.FilterPolicy
 import com.android.hoststubgen.filters.FilterRemapper
 import com.android.hoststubgen.filters.ImplicitOutputFilter
-import com.android.hoststubgen.filters.NativeFilter
+import com.android.hoststubgen.filters.KeepNativeFilter
 import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.filters.SanitizationFilter
 import com.android.hoststubgen.filters.createFilterFromTextPolicyFile
 import com.android.hoststubgen.filters.printAsTextPolicy
 import com.android.hoststubgen.utils.ClassFilter
@@ -134,7 +135,7 @@
         var filter: OutputFilter = ConstantFilter(options.defaultPolicy.get, "default-by-options")
 
         // Next, we build a filter that preserves all native methods by default
-        filter = NativeFilter(allClasses, filter)
+        filter = KeepNativeFilter(allClasses, filter)
 
         // Next, we need a filter that resolves "class-wide" policies.
         // This is used when a member (methods, fields, nested classes) don't get any polices
@@ -166,11 +167,12 @@
             options.throwAnnotations,
             options.removeAnnotations,
             options.substituteAnnotations,
-            options.nativeSubstituteAnnotations,
+            options.redirectAnnotations,
+            options.redirectionClassAnnotations,
             options.classLoadHookAnnotations,
             options.keepStaticInitializerAnnotations,
             annotationAllowedClassesFilter,
-            filter,
+            filter
         )
 
         // Next, "text based" filter, which allows to override polices without touching
@@ -182,6 +184,9 @@
         // Apply the implicit filter.
         filter = ImplicitOutputFilter(errors, allClasses, filter)
 
+        // Add a final sanitization step.
+        filter = SanitizationFilter(errors, allClasses, filter)
+
         return filter
     }
 
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
index 1cedcc3..057a52c 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -85,9 +85,10 @@
         var throwAnnotations: MutableSet<String> = mutableSetOf(),
         var removeAnnotations: MutableSet<String> = mutableSetOf(),
         var keepClassAnnotations: MutableSet<String> = mutableSetOf(),
+        var redirectAnnotations: MutableSet<String> = mutableSetOf(),
 
         var substituteAnnotations: MutableSet<String> = mutableSetOf(),
-        var nativeSubstituteAnnotations: MutableSet<String> = mutableSetOf(),
+        var redirectionClassAnnotations: MutableSet<String> = mutableSetOf(),
         var classLoadHookAnnotations: MutableSet<String> = mutableSetOf(),
         var keepStaticInitializerAnnotations: MutableSet<String> = mutableSetOf(),
 
@@ -186,8 +187,11 @@
                         "--substitute-annotation" ->
                             ret.substituteAnnotations.addUniqueAnnotationArg()
 
-                        "--native-substitute-annotation" ->
-                            ret.nativeSubstituteAnnotations.addUniqueAnnotationArg()
+                        "--redirect-annotation" ->
+                            ret.redirectAnnotations.addUniqueAnnotationArg()
+
+                        "--redirection-class-annotation" ->
+                            ret.redirectionClassAnnotations.addUniqueAnnotationArg()
 
                         "--class-load-hook-annotation" ->
                             ret.classLoadHookAnnotations.addUniqueAnnotationArg()
@@ -275,7 +279,7 @@
               removeAnnotations=$removeAnnotations,
               keepClassAnnotations=$keepClassAnnotations,
               substituteAnnotations=$substituteAnnotations,
-              nativeSubstituteAnnotations=$nativeSubstituteAnnotations,
+              nativeSubstituteAnnotations=$redirectionClassAnnotations,
               classLoadHookAnnotations=$classLoadHookAnnotations,
               keepStaticInitializerAnnotations=$keepStaticInitializerAnnotations,
               packageRedirects=$packageRedirects,
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
index 7197e0e..a02082d 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -29,33 +29,24 @@
 
 
 /** Name of the class initializer method. */
-val CLASS_INITIALIZER_NAME = "<clinit>"
+const val CLASS_INITIALIZER_NAME = "<clinit>"
 
 /** Descriptor of the class initializer method. */
-val CLASS_INITIALIZER_DESC = "()V"
+const val CLASS_INITIALIZER_DESC = "()V"
 
 /** Name of constructors. */
-val CTOR_NAME = "<init>"
+const val CTOR_NAME = "<init>"
 
 /**
- * Find any of [anyAnnotations] from the list of visible / invisible annotations.
+ * Find any of [set] from the list of visible / invisible annotations.
  */
 fun findAnyAnnotation(
-        anyAnnotations: Set<String>,
-        visibleAnnotations: List<AnnotationNode>?,
-        invisibleAnnotations: List<AnnotationNode>?,
-    ): AnnotationNode? {
-    for (an in visibleAnnotations ?: emptyList()) {
-        if (anyAnnotations.contains(an.desc)) {
-            return an
-        }
-    }
-    for (an in invisibleAnnotations ?: emptyList()) {
-        if (anyAnnotations.contains(an.desc)) {
-            return an
-        }
-    }
-    return null
+    set: Set<String>,
+    visibleAnnotations: List<AnnotationNode>?,
+    invisibleAnnotations: List<AnnotationNode>?,
+): AnnotationNode? {
+    return visibleAnnotations?.find { it.desc in set }
+        ?: invisibleAnnotations?.find { it.desc in set }
 }
 
 fun ClassNode.findAnyAnnotation(set: Set<String>): AnnotationNode? {
@@ -70,6 +61,27 @@
     return findAnyAnnotation(set, this.visibleAnnotations, this.invisibleAnnotations)
 }
 
+fun findAllAnnotations(
+    set: Set<String>,
+    visibleAnnotations: List<AnnotationNode>?,
+    invisibleAnnotations: List<AnnotationNode>?
+): List<AnnotationNode> {
+    return (visibleAnnotations ?: emptyList()).filter { it.desc in set } +
+            (invisibleAnnotations ?: emptyList()).filter { it.desc in set }
+}
+
+fun ClassNode.findAllAnnotations(set: Set<String>): List<AnnotationNode> {
+    return findAllAnnotations(set, this.visibleAnnotations, this.invisibleAnnotations)
+}
+
+fun MethodNode.findAllAnnotations(set: Set<String>): List<AnnotationNode> {
+    return findAllAnnotations(set, this.visibleAnnotations, this.invisibleAnnotations)
+}
+
+fun FieldNode.findAllAnnotations(set: Set<String>): List<AnnotationNode> {
+    return findAllAnnotations(set, this.visibleAnnotations, this.invisibleAnnotations)
+}
+
 fun <T> findAnnotationValueAsObject(
     an: AnnotationNode,
     propertyName: String,
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
index 38a41b2..a6b8cdb 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
@@ -18,12 +18,15 @@
 import com.android.hoststubgen.ClassParseException
 import com.android.hoststubgen.HostStubGenErrors
 import com.android.hoststubgen.InvalidAnnotationException
-import com.android.hoststubgen.addNonNullElement
+import com.android.hoststubgen.addLists
 import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC
 import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME
 import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.findAllAnnotations
 import com.android.hoststubgen.asm.findAnnotationValueAsString
 import com.android.hoststubgen.asm.findAnyAnnotation
+import com.android.hoststubgen.asm.getPackageNameFromFullClassName
+import com.android.hoststubgen.asm.resolveClassNameWithDefaultPackage
 import com.android.hoststubgen.asm.toHumanReadableClassName
 import com.android.hoststubgen.asm.toHumanReadableMethodName
 import com.android.hoststubgen.asm.toJvmClassName
@@ -46,7 +49,8 @@
     throwAnnotations_: Set<String>,
     removeAnnotations_: Set<String>,
     substituteAnnotations_: Set<String>,
-    nativeSubstituteAnnotations_: Set<String>,
+    redirectAnnotations_: Set<String>,
+    redirectionClassAnnotations_: Set<String>,
     classLoadHookAnnotations_: Set<String>,
     keepStaticInitializerAnnotations_: Set<String>,
     private val annotationAllowedClassesFilter: ClassFilter,
@@ -56,8 +60,10 @@
     private val keepClassAnnotations = convertToInternalNames(keepClassAnnotations_)
     private val throwAnnotations = convertToInternalNames(throwAnnotations_)
     private val removeAnnotations = convertToInternalNames(removeAnnotations_)
+    private val redirectAnnotations = convertToInternalNames(redirectAnnotations_)
     private val substituteAnnotations = convertToInternalNames(substituteAnnotations_)
-    private val nativeSubstituteAnnotations = convertToInternalNames(nativeSubstituteAnnotations_)
+    private val redirectionClassAnnotations =
+        convertToInternalNames(redirectionClassAnnotations_)
     private val classLoadHookAnnotations = convertToInternalNames(classLoadHookAnnotations_)
     private val keepStaticInitializerAnnotations =
         convertToInternalNames(keepStaticInitializerAnnotations_)
@@ -67,11 +73,12 @@
             keepClassAnnotations +
             throwAnnotations +
             removeAnnotations +
+            redirectAnnotations +
             substituteAnnotations
 
     /** All the annotations we use. */
     private val allAnnotations = visibilityAnnotations +
-            nativeSubstituteAnnotations +
+            redirectionClassAnnotations +
             classLoadHookAnnotations +
             keepStaticInitializerAnnotations
 
@@ -84,8 +91,9 @@
                 keepClassAnnotations_ +
                 throwAnnotations_ +
                 removeAnnotations_ +
+                redirectAnnotations_ +
                 substituteAnnotations_ +
-                nativeSubstituteAnnotations_ +
+                redirectionClassAnnotations_ +
                 classLoadHookAnnotations_ +
                 keepStaticInitializerAnnotations_
     )
@@ -99,6 +107,7 @@
             in substituteAnnotations -> FilterPolicy.Substitute.withReason(REASON_ANNOTATION)
             in throwAnnotations -> FilterPolicy.Throw.withReason(REASON_ANNOTATION)
             in removeAnnotations -> FilterPolicy.Remove.withReason(REASON_ANNOTATION)
+            in redirectAnnotations -> FilterPolicy.Redirect.withReason(REASON_ANNOTATION)
             else -> null
         }
     }
@@ -129,13 +138,6 @@
         descriptor: String
     ): FilterPolicyWithReason {
         val cn = classes.getClass(className)
-
-        if (methodName == CLASS_INITIALIZER_NAME && descriptor == CLASS_INITIALIZER_DESC) {
-            if (cn.findAnyAnnotation(keepStaticInitializerAnnotations) != null) {
-                return FilterPolicy.Keep.withReason(REASON_ANNOTATION)
-            }
-        }
-
         return getAnnotationPolicy(cn).methodPolicies[MethodKey(methodName, descriptor)]
             ?: super.getPolicyForMethod(className, methodName, descriptor)
     }
@@ -150,22 +152,14 @@
             ?: super.getRenameTo(className, methodName, descriptor)
     }
 
-    override fun getNativeSubstitutionClass(className: String): String? {
-        classes.getClass(className).let { cn ->
-            cn.findAnyAnnotation(nativeSubstituteAnnotations)?.let { an ->
-                return getAnnotationField(an, "value")?.toJvmClassName()
-            }
-        }
-        return null
+    override fun getRedirectionClass(className: String): String? {
+        val cn = classes.getClass(className)
+        return getAnnotationPolicy(cn).redirectionClass
     }
 
     override fun getClassLoadHooks(className: String): List<String> {
-        val e = classes.getClass(className).let { cn ->
-            cn.findAnyAnnotation(classLoadHookAnnotations)?.let { an ->
-                getAnnotationField(an, "value")?.toHumanReadableMethodName()
-            }
-        }
-        return addNonNullElement(super.getClassLoadHooks(className), e)
+        val cn = classes.getClass(className)
+        return addLists(super.getClassLoadHooks(className), getAnnotationPolicy(cn).classLoadHooks)
     }
 
     private data class MethodKey(val name: String, val desc: String)
@@ -195,6 +189,8 @@
         val fieldPolicies = mutableMapOf<String, FilterPolicyWithReason>()
         val methodPolicies = mutableMapOf<MethodKey, FilterPolicyWithReason>()
         val renamedMethods = mutableMapOf<MethodKey, String>()
+        val redirectionClass: String?
+        val classLoadHooks: List<String>
 
         init {
             val allowAnnotation = annotationAllowedClassesFilter.matches(cn.name)
@@ -204,6 +200,16 @@
                 "class", cn.name
             )
             classPolicy = cn.findAnyAnnotation(visibilityAnnotations)?.policy
+            redirectionClass = cn.findAnyAnnotation(redirectionClassAnnotations)?.let { an ->
+                getAnnotationField(an, "value")?.let { resolveRelativeClass(cn, it) }
+            }
+            classLoadHooks = cn.findAllAnnotations(classLoadHookAnnotations).mapNotNull { an ->
+                getAnnotationField(an, "value")?.toHumanReadableMethodName()
+            }
+            if (cn.findAnyAnnotation(keepStaticInitializerAnnotations) != null) {
+                methodPolicies[MethodKey(CLASS_INITIALIZER_NAME, CLASS_INITIALIZER_DESC)] =
+                    FilterPolicy.Keep.withReason(REASON_ANNOTATION)
+            }
 
             for (fn in cn.fields ?: emptyList()) {
                 detectInvalidAnnotations(
@@ -297,25 +303,36 @@
                 )
             }
         }
-    }
 
-    /**
-     * Return the (String) value of 'value' parameter from an annotation.
-     */
-    private fun getAnnotationField(
-        an: AnnotationNode,
-        name: String,
-        required: Boolean = true
-    ): String? {
-        try {
-            val suffix = findAnnotationValueAsString(an, name)
-            if (suffix == null && required) {
-                errors.onErrorFound("Annotation \"${an.desc}\" must have field $name")
+        /**
+         * Return the (String) value of 'value' parameter from an annotation.
+         */
+        private fun getAnnotationField(
+            an: AnnotationNode,
+            name: String,
+            required: Boolean = true
+        ): String? {
+            try {
+                val suffix = findAnnotationValueAsString(an, name)
+                if (suffix == null && required) {
+                    errors.onErrorFound("Annotation \"${an.desc}\" must have field $name")
+                }
+                return suffix
+            } catch (e: ClassParseException) {
+                errors.onErrorFound(e.message!!)
+                return null
             }
-            return suffix
-        } catch (e: ClassParseException) {
-            errors.onErrorFound(e.message!!)
-            return null
+        }
+
+        /**
+         * Resolve the full class name if the class is relative
+         */
+        private fun resolveRelativeClass(
+            cn: ClassNode,
+            name: String
+        ): String {
+            val packageName = getPackageNameFromFullClassName(cn.name)
+            return resolveClassNameWithDefaultPackage(name, packageName).toJvmClassName()
         }
     }
 
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
index 8ee3a94..f8bb526 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
@@ -16,7 +16,6 @@
 package com.android.hoststubgen.filters
 
 import com.android.hoststubgen.asm.ClassNodes
-import com.android.hoststubgen.asm.isNative
 
 /**
  * This is used as the second last fallback filter. This filter propagates the class-wide policy
@@ -88,16 +87,7 @@
         methodName: String,
         descriptor: String
     ): FilterPolicyWithReason {
-        return outermostFilter.getNativeSubstitutionClass(className)?.let {
-            // First check native substitution
-            classes.findMethod(className, methodName, descriptor)?.let { mn ->
-                if (mn.isNative()) {
-                    FilterPolicy.NativeSubstitute.withReason("class-wide in $className")
-                } else {
-                    null
-                }
-            }
-        } ?: getClassWidePolicy(className, resolve = true)
-        ?: super.getPolicyForMethod(className, methodName, descriptor)
+        return getClassWidePolicy(className, resolve = true)
+            ?: super.getPolicyForMethod(className, methodName, descriptor)
     }
-}
\ No newline at end of file
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt
index 6fcffb8..b8b0d8a 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt
@@ -72,8 +72,8 @@
         return fallback.getRenameTo(className, methodName, descriptor)
     }
 
-    override fun getNativeSubstitutionClass(className: String): String? {
-        return fallback.getNativeSubstitutionClass(className)
+    override fun getRedirectionClass(className: String): String? {
+        return fallback.getRedirectionClass(className)
     }
 
     override fun getClassLoadHooks(className: String): List<String> {
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
index ab03874..2f2f81b 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
@@ -33,9 +33,9 @@
     Substitute,
 
     /**
-     * Only usable with methods. Replace a native method with a "substitution" method,
+     * Only usable with methods. Redirect a method to a method in the substitution class.
      */
-    NativeSubstitute,
+    Redirect,
 
     /**
      * Only usable with methods. The item will be kept in the impl jar file, but when called,
@@ -102,8 +102,7 @@
     val isSupported: Boolean
         get() {
             return when (this) {
-                // TODO: handle native method with no substitution as being unsupported
-                Keep, KeepClass, Substitute, NativeSubstitute -> true
+                Keep, KeepClass, Substitute, Redirect -> true
                 else -> false
             }
         }
@@ -111,7 +110,7 @@
     val isMethodRewriteBody: Boolean
         get() {
             return when (this) {
-                NativeSubstitute, Throw, Ignore -> true
+                Redirect, Throw, Ignore -> true
                 else -> false
             }
         }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
index 2e144f5..59fa464 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
@@ -19,6 +19,7 @@
 import com.android.hoststubgen.asm.ClassNodes
 import com.android.hoststubgen.asm.toHumanReadableClassName
 import com.android.hoststubgen.asm.toHumanReadableMethodName
+import com.android.hoststubgen.asm.toJvmClassName
 import com.android.hoststubgen.log
 
 // TODO: Validate all input names.
@@ -29,7 +30,7 @@
 ) : DelegatingFilter(fallback) {
     private val mPolicies: MutableMap<String, FilterPolicyWithReason> = mutableMapOf()
     private val mRenames: MutableMap<String, String> = mutableMapOf()
-    private val mNativeSubstitutionClasses: MutableMap<String, String> = mutableMapOf()
+    private val mRedirectionClasses: MutableMap<String, String> = mutableMapOf()
     private val mClassLoadHooks: MutableMap<String, String> = mutableMapOf()
 
     private fun getClassKey(className: String): String {
@@ -115,17 +116,17 @@
         mRenames[getMethodKey(className, methodName, descriptor)] = toName
     }
 
-    override fun getNativeSubstitutionClass(className: String): String? {
-        return mNativeSubstitutionClasses[getClassKey(className)]
-                ?: super.getNativeSubstitutionClass(className)
+    override fun getRedirectionClass(className: String): String? {
+        return mRedirectionClasses[getClassKey(className)]
+                ?: super.getRedirectionClass(className)
     }
 
-    fun setNativeSubstitutionClass(from: String, to: String) {
+    fun setRedirectionClass(from: String, to: String) {
         checkClass(from)
 
-        // Native substitute classes may be provided from other jars, so we can't do this check.
+        // Redirection classes may be provided from other jars, so we can't do this check.
         // ensureClassExists(to)
-        mNativeSubstitutionClasses[getClassKey(from)] = to.toHumanReadableClassName()
+        mRedirectionClasses[getClassKey(from)] = to.toJvmClassName()
     }
 
     override fun getClassLoadHooks(className: String): List<String> {
@@ -136,4 +137,4 @@
     fun setClassLoadHook(className: String, methodName: String) {
         mClassLoadHooks[getClassKey(className)] = methodName.toHumanReadableMethodName()
     }
-}
\ No newline at end of file
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/NativeFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepNativeFilter.kt
similarity index 82%
rename from tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/NativeFilter.kt
rename to tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepNativeFilter.kt
index bd71931..00e7d77 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/NativeFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepNativeFilter.kt
@@ -18,7 +18,12 @@
 import com.android.hoststubgen.asm.ClassNodes
 import com.android.hoststubgen.asm.isNative
 
-class NativeFilter(
+/**
+ *  For native methods that weren't handled by outer filters, we keep it so that
+ *  native method registration will not crash at runtime. Ideally we shouldn't need
+ *  this, but in practice unsupported native method registrations do occur.
+ */
+class KeepNativeFilter(
     private val classes: ClassNodes,
     fallback: OutputFilter
 ) : DelegatingFilter(fallback) {
@@ -28,8 +33,6 @@
         descriptor: String,
     ): FilterPolicyWithReason {
         return classes.findMethod(className, methodName, descriptor)?.let { mn ->
-            // For native methods that weren't handled by outer filters,
-            // we keep it so that native method registration will not crash.
             if (mn.isNative()) {
                 FilterPolicy.Keep.withReason("native-preserve")
             } else {
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt
index 1049e2b..f99ce90 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt
@@ -35,10 +35,6 @@
      * using it.
      */
     open var outermostFilter: OutputFilter = this
-        get() = field
-        set(value) {
-            field = value
-        }
 
     abstract fun getPolicyForClass(className: String): FilterPolicyWithReason
 
@@ -60,13 +56,13 @@
     }
 
     /**
-     * Return a "native substitution class" name for a given class.
+     * Return a "redirection class" name for a given class.
      *
-     * The result will be in a "human readable" form. (e.g. uses '.'s instead of '/'s)
+     * The result will be in a JVM internal form. (e.g. uses '/'s instead of '.'s)
      *
-     * (which corresponds to @HostSideTestNativeSubstitutionClass of the standard annotations.)
+     * (which corresponds to @HostSideTestRedirectClass of the standard annotations.)
      */
-    open fun getNativeSubstitutionClass(className: String): String? {
+    open fun getRedirectionClass(className: String): String? {
         return null
     }
 
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/SanitizationFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/SanitizationFilter.kt
new file mode 100644
index 0000000..18a1e16
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/SanitizationFilter.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 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.hoststubgen.filters
+
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.toHumanReadableClassName
+import com.android.hoststubgen.log
+
+/**
+ * Check whether the policies in the inner layers make sense, and sanitize the results.
+ */
+class SanitizationFilter(
+    private val errors: HostStubGenErrors,
+    private val classes: ClassNodes,
+    fallback: OutputFilter
+) : DelegatingFilter(fallback) {
+    override fun getPolicyForMethod(
+        className: String,
+        methodName: String,
+        descriptor: String
+    ): FilterPolicyWithReason {
+        val policy = super.getPolicyForMethod(className, methodName, descriptor)
+        if (policy.policy == FilterPolicy.Redirect) {
+            // Check whether the hosting class has a redirection class
+            if (getRedirectionClass(className) == null) {
+                errors.onErrorFound("Method $methodName$descriptor requires a redirection " +
+                        "class set on ${className.toHumanReadableClassName()}")
+            }
+        }
+        return policy
+    }
+
+    override fun getRedirectionClass(className: String): String? {
+        return super.getRedirectionClass(className)?.also { clazz ->
+            if (classes.findClass(clazz) == null) {
+                log.w("Redirection class $clazz not found. Class must be available at runtime.")
+            } else if (outermostFilter.getPolicyForClass(clazz).policy != FilterPolicy.KeepClass) {
+                // If the class exists, it must have a KeepClass policy.
+                errors.onErrorFound("Redirection class $clazz must have @KeepWholeClass.")
+            }
+        }
+    }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
index 14fd82b..073b503 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
@@ -142,9 +142,9 @@
                                     throw ParseException(
                                             "Special class can't have a substitution")
                                 }
-                                // It's a native-substitution.
+                                // It's a redirection class.
                                 val toClass = fields[2].substring(1)
-                                imf.setNativeSubstitutionClass(className, toClass)
+                                imf.setRedirectionClass(className, toClass)
                             } else if (fields[2].startsWith("~")) {
                                 if (classType != SpecialClass.NotSpecial) {
                                     // We could support it, but not needed at least for now.
@@ -350,6 +350,7 @@
         "r", "remove" -> FilterPolicy.Remove
         "kc", "keepclass" -> FilterPolicy.KeepClass
         "i", "ignore" -> FilterPolicy.Ignore
+        "rdr", "redirect" -> FilterPolicy.Redirect
         else -> {
             if (s.startsWith("@")) {
                 FilterPolicy.Substitute
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
index 41ba928..261ef59c 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
@@ -21,8 +21,6 @@
 import com.android.hoststubgen.asm.ClassNodes
 import com.android.hoststubgen.asm.UnifiedVisitor
 import com.android.hoststubgen.asm.getPackageNameFromFullClassName
-import com.android.hoststubgen.asm.resolveClassNameWithDefaultPackage
-import com.android.hoststubgen.asm.toJvmClassName
 import com.android.hoststubgen.filters.FilterPolicy
 import com.android.hoststubgen.filters.FilterPolicyWithReason
 import com.android.hoststubgen.filters.OutputFilter
@@ -57,7 +55,7 @@
 
     protected lateinit var currentPackageName: String
     protected lateinit var currentClassName: String
-    protected var nativeSubstitutionClass: String? = null
+    protected var redirectionClass: String? = null
     protected lateinit var classPolicy: FilterPolicyWithReason
 
     override fun visit(
@@ -72,34 +70,13 @@
         currentClassName = name
         currentPackageName = getPackageNameFromFullClassName(name)
         classPolicy = filter.getPolicyForClass(currentClassName)
+        redirectionClass = filter.getRedirectionClass(currentClassName)
 
         log.d("[%s] visit: %s (package: %s)", this.javaClass.simpleName, name, currentPackageName)
         log.indent()
         log.v("Emitting class: %s", name)
         log.indent()
 
-        filter.getNativeSubstitutionClass(currentClassName)?.let { className ->
-            val fullClassName = resolveClassNameWithDefaultPackage(className, currentPackageName)
-                .toJvmClassName()
-            log.d("  NativeSubstitutionClass: $fullClassName")
-            if (classes.findClass(fullClassName) == null) {
-                log.w(
-                    "Native substitution class $fullClassName not found. Class must be " +
-                            "available at runtime."
-                )
-            } else {
-                // If the class exists, it must have a KeepClass policy.
-                if (filter.getPolicyForClass(fullClassName).policy != FilterPolicy.KeepClass) {
-                    // TODO: Use real annotation name.
-                    options.errors.onErrorFound(
-                        "Native substitution class $fullClassName should have @Keep."
-                    )
-                }
-            }
-
-            nativeSubstitutionClass = fullClassName
-        }
-
         // Inject annotations to generated classes.
         UnifiedVisitor.on(this).visitAnnotation(HostStubGenProcessedAsKeep.CLASS_DESCRIPTOR, true)
     }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
index 057d653..567a69e 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
@@ -184,9 +184,12 @@
                     return IgnoreMethodAdapter(descriptor, forceCreateBody, innerVisitor)
                         .withAnnotation(HostStubGenProcessedAsIgnore.CLASS_DESCRIPTOR)
                 }
-                FilterPolicy.NativeSubstitute -> {
-                    log.v("Rewriting native method...")
-                    return NativeSubstitutingMethodAdapter(access, name, descriptor, innerVisitor)
+                FilterPolicy.Redirect -> {
+                    log.v("Redirecting method...")
+                    return RedirectMethodAdapter(
+                        access, name, descriptor,
+                        forceCreateBody, innerVisitor
+                    )
                         .withAnnotation(HostStubGenProcessedAsSubstitute.CLASS_DESCRIPTOR)
                 }
                 else -> {}
@@ -274,15 +277,16 @@
     }
 
     /**
-     * A method adapter that rewrite a native method body with a
-     * call to a method in the "native substitution" class.
+     * A method adapter that rewrite a method body with a
+     * call to a method in the redirection class.
      */
-    private inner class NativeSubstitutingMethodAdapter(
+    private inner class RedirectMethodAdapter(
         access: Int,
         private val name: String,
         private val descriptor: String,
+        createBody: Boolean,
         next: MethodVisitor?
-    ) : BodyReplacingMethodVisitor(true, next) {
+    ) : BodyReplacingMethodVisitor(createBody, next) {
 
         private val isStatic = (access and Opcodes.ACC_STATIC) != 0
 
@@ -290,7 +294,7 @@
             var targetDescriptor = descriptor
             var argOffset = 0
 
-            // For non-static native method, we need to tweak it a bit.
+            // For non-static method, we need to tweak it a bit.
             if (!isStatic) {
                 // Push `this` as the first argument.
                 this.visitVarInsn(Opcodes.ALOAD, 0)
@@ -310,7 +314,7 @@
 
             visitMethodInsn(
                 INVOKESTATIC,
-                nativeSubstitutionClass,
+                redirectionClass,
                 name,
                 targetDescriptor,
                 false
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
index 5fde14f..82586bb 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -41,20 +41,40 @@
     java.lang.annotation.Retention(
       value=Ljava/lang/annotation/RetentionPolicy;.CLASS
     )
-## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class
-  Compiled from "HostSideTestNativeSubstitutionClass.java"
-public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation
+## Class: android/hosttest/annotation/HostSideTestRedirect.class
+  Compiled from "HostSideTestRedirect.java"
+public interface android.hosttest.annotation.HostSideTestRedirect extends java.lang.annotation.Annotation
   minor version: 0
   major version: 61
   flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
-  this_class: #x                          // android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+  this_class: #x                          // android/hosttest/annotation/HostSideTestRedirect
+  super_class: #x                         // java/lang/Object
+  interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestRedirect.java"
+RuntimeVisibleAnnotations:
+  x: #x(#x=[e#x.#x])
+    java.lang.annotation.Target(
+      value=[Ljava/lang/annotation/ElementType;.METHOD]
+    )
+  x: #x(#x=e#x.#x)
+    java.lang.annotation.Retention(
+      value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+    )
+## Class: android/hosttest/annotation/HostSideTestRedirectionClass.class
+  Compiled from "HostSideTestRedirectionClass.java"
+public interface android.hosttest.annotation.HostSideTestRedirectionClass extends java.lang.annotation.Annotation
+  minor version: 0
+  major version: 61
+  flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+  this_class: #x                          // android/hosttest/annotation/HostSideTestRedirectionClass
   super_class: #x                         // java/lang/Object
   interfaces: 1, fields: 0, methods: 1, attributes: 2
   public abstract java.lang.String value();
     descriptor: ()Ljava/lang/String;
     flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
 }
-SourceFile: "HostSideTestNativeSubstitutionClass.java"
+SourceFile: "HostSideTestRedirectionClass.java"
 RuntimeVisibleAnnotations:
   x: #x(#x=[e#x.#x])
     java.lang.annotation.Target(
@@ -1925,7 +1945,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                         // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 12, attributes: 2
+  interfaces: 0, fields: 1, methods: 14, attributes: 2
   int value;
     descriptor: I
     flags: (0x0000)
@@ -1946,6 +1966,9 @@
   public static native int nativeAddTwo(int);
     descriptor: (I)I
     flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
 
   public static int nativeAddTwo_should_be_like_this(int);
     descriptor: (I)I
@@ -1963,6 +1986,9 @@
   public static native long nativeLongPlus(long, long);
     descriptor: (JJ)J
     flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
 
   public static long nativeLongPlus_should_be_like_this(long, long);
     descriptor: (JJ)J
@@ -1997,6 +2023,9 @@
   public native int nativeNonStaticAddToValue(int);
     descriptor: (I)I
     flags: (0x0101) ACC_PUBLIC, ACC_NATIVE
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
 
   public int nativeNonStaticAddToValue_should_be_like_this(int);
     descriptor: (I)I
@@ -2023,9 +2052,6 @@
   public static native void nativeStillKeep();
     descriptor: ()V
     flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestKeep
 
   public static void nativeStillNotSupported_should_be_like_this();
     descriptor: ()V
@@ -2041,13 +2067,47 @@
   public static native byte nativeBytePlus(byte, byte);
     descriptor: (BB)B
     flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
+
+  public void notNativeRedirected();
+    descriptor: ()V
+    flags: (0x0001) ACC_PUBLIC
+    Code:
+      stack=2, locals=1, args_size=1
+         x: new           #x                 // class java/lang/RuntimeException
+         x: dup
+         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":()V
+         x: athrow
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0       8     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
+
+  public static void notNativeStaticRedirected();
+    descriptor: ()V
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=2, locals=0, args_size=0
+         x: new           #x                 // class java/lang/RuntimeException
+         x: dup
+         x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":()V
+         x: athrow
+      LineNumberTable:
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
 }
 SourceFile: "TinyFrameworkNative.java"
 RuntimeInvisibleAnnotations:
   x: #x()
     android.hosttest.annotation.HostSideTestWholeClassKeep
   x: #x(#x=s#x)
-    android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+    android.hosttest.annotation.HostSideTestRedirectionClass(
       value="TinyFrameworkNative_host"
     )
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class
@@ -2058,7 +2118,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                         // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 5, attributes: 2
+  interfaces: 0, fields: 0, methods: 7, attributes: 2
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host();
     descriptor: ()V
     flags: (0x0001) ACC_PUBLIC
@@ -2132,6 +2192,25 @@
         Start  Length  Slot  Name   Signature
             0       5     0  arg1   B
             0       5     1  arg2   B
+
+  public static void notNativeRedirected(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative);
+    descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=0, locals=1, args_size=1
+         x: return
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0       1     0 source   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+
+  public static void notNativeStaticRedirected();
+    descriptor: ()V
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=0, locals=0, args_size=0
+         x: return
+      LineNumberTable:
 }
 SourceFile: "TinyFrameworkNative_host.java"
 RuntimeInvisibleAnnotations:
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
index e41d46d..31bbcc5 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
@@ -48,13 +48,35 @@
     java.lang.annotation.Retention(
       value=Ljava/lang/annotation/RetentionPolicy;.CLASS
     )
-## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class
-  Compiled from "HostSideTestNativeSubstitutionClass.java"
-public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation
+## Class: android/hosttest/annotation/HostSideTestRedirect.class
+  Compiled from "HostSideTestRedirect.java"
+public interface android.hosttest.annotation.HostSideTestRedirect extends java.lang.annotation.Annotation
   minor version: 0
   major version: 61
   flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
-  this_class: #x                          // android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+  this_class: #x                          // android/hosttest/annotation/HostSideTestRedirect
+  super_class: #x                         // java/lang/Object
+  interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestRedirect.java"
+RuntimeVisibleAnnotations:
+  x: #x()
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+  x: #x(#x=[e#x.#x])
+    java.lang.annotation.Target(
+      value=[Ljava/lang/annotation/ElementType;.METHOD]
+    )
+  x: #x(#x=e#x.#x)
+    java.lang.annotation.Retention(
+      value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+    )
+## Class: android/hosttest/annotation/HostSideTestRedirectionClass.class
+  Compiled from "HostSideTestRedirectionClass.java"
+public interface android.hosttest.annotation.HostSideTestRedirectionClass extends java.lang.annotation.Annotation
+  minor version: 0
+  major version: 61
+  flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+  this_class: #x                          // android/hosttest/annotation/HostSideTestRedirectionClass
   super_class: #x                         // java/lang/Object
   interfaces: 1, fields: 0, methods: 1, attributes: 2
   public abstract java.lang.String value();
@@ -64,7 +86,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
-SourceFile: "HostSideTestNativeSubstitutionClass.java"
+SourceFile: "HostSideTestRedirectionClass.java"
 RuntimeVisibleAnnotations:
   x: #x()
     com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
@@ -2076,7 +2098,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 12, attributes: 3
+  interfaces: 0, fields: 1, methods: 14, attributes: 3
   int value;
     descriptor: I
     flags: (0x0000)
@@ -2113,6 +2135,9 @@
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
 
   public static int nativeAddTwo_should_be_like_this(int);
     descriptor: (I)I
@@ -2144,6 +2169,9 @@
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
 
   public static long nativeLongPlus_should_be_like_this(long, long);
     descriptor: (JJ)J
@@ -2195,6 +2223,9 @@
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
 
   public int nativeNonStaticAddToValue_should_be_like_this(int);
     descriptor: (I)I
@@ -2240,9 +2271,6 @@
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestKeep
 
   public static void nativeStillNotSupported_should_be_like_this();
     descriptor: ()V
@@ -2272,6 +2300,42 @@
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
+
+  public void notNativeRedirected();
+    descriptor: ()V
+    flags: (0x0001) ACC_PUBLIC
+    Code:
+      stack=1, locals=1, args_size=1
+         x: aload_0
+         x: invokestatic  #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.notNativeRedirected:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V
+         x: return
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
+
+  public static void notNativeStaticRedirected();
+    descriptor: ()V
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=0, locals=0, args_size=0
+         x: invokestatic  #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.notNativeStaticRedirected:()V
+         x: return
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
 }
 SourceFile: "TinyFrameworkNative.java"
 RuntimeVisibleAnnotations:
@@ -2281,7 +2345,7 @@
   x: #x()
     android.hosttest.annotation.HostSideTestWholeClassKeep
   x: #x(#x=s#x)
-    android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+    android.hosttest.annotation.HostSideTestRedirectionClass(
       value="TinyFrameworkNative_host"
     )
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class
@@ -2292,7 +2356,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 5, attributes: 3
+  interfaces: 0, fields: 0, methods: 7, attributes: 3
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host();
     descriptor: ()V
     flags: (0x0001) ACC_PUBLIC
@@ -2381,6 +2445,31 @@
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  public static void notNativeRedirected(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative);
+    descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=0, locals=1, args_size=1
+         x: return
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0       1     0 source   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  public static void notNativeStaticRedirected();
+    descriptor: ()V
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=0, locals=0, args_size=0
+         x: return
+      LineNumberTable:
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkNative_host.java"
 RuntimeVisibleAnnotations:
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
index 2ca723b..41f459a 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
@@ -67,13 +67,44 @@
     java.lang.annotation.Retention(
       value=Ljava/lang/annotation/RetentionPolicy;.CLASS
     )
-## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class
-  Compiled from "HostSideTestNativeSubstitutionClass.java"
-public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation
+## Class: android/hosttest/annotation/HostSideTestRedirect.class
+  Compiled from "HostSideTestRedirect.java"
+public interface android.hosttest.annotation.HostSideTestRedirect extends java.lang.annotation.Annotation
   minor version: 0
   major version: 61
   flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
-  this_class: #x                          // android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+  this_class: #x                          // android/hosttest/annotation/HostSideTestRedirect
+  super_class: #x                         // java/lang/Object
+  interfaces: 1, fields: 0, methods: 1, attributes: 2
+  private static {};
+    descriptor: ()V
+    flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+    Code:
+      stack=2, locals=0, args_size=0
+         x: ldc           #x                  // class android/hosttest/annotation/HostSideTestRedirect
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+         x: return
+}
+SourceFile: "HostSideTestRedirect.java"
+RuntimeVisibleAnnotations:
+  x: #x()
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+  x: #x(#x=[e#x.#x])
+    java.lang.annotation.Target(
+      value=[Ljava/lang/annotation/ElementType;.METHOD]
+    )
+  x: #x(#x=e#x.#x)
+    java.lang.annotation.Retention(
+      value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+    )
+## Class: android/hosttest/annotation/HostSideTestRedirectionClass.class
+  Compiled from "HostSideTestRedirectionClass.java"
+public interface android.hosttest.annotation.HostSideTestRedirectionClass extends java.lang.annotation.Annotation
+  minor version: 0
+  major version: 61
+  flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+  this_class: #x                          // android/hosttest/annotation/HostSideTestRedirectionClass
   super_class: #x                         // java/lang/Object
   interfaces: 1, fields: 0, methods: 2, attributes: 2
   private static {};
@@ -81,7 +112,7 @@
     flags: (0x000a) ACC_PRIVATE, ACC_STATIC
     Code:
       stack=2, locals=0, args_size=0
-         x: ldc           #x                  // class android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+         x: ldc           #x                  // class android/hosttest/annotation/HostSideTestRedirectionClass
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
          x: return
@@ -93,7 +124,7 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
-SourceFile: "HostSideTestNativeSubstitutionClass.java"
+SourceFile: "HostSideTestRedirectionClass.java"
 RuntimeVisibleAnnotations:
   x: #x()
     com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
@@ -2612,7 +2643,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 13, attributes: 3
+  interfaces: 0, fields: 1, methods: 15, attributes: 3
   int value;
     descriptor: I
     flags: (0x0000)
@@ -2669,6 +2700,9 @@
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
 
   public static int nativeAddTwo_should_be_like_this(int);
     descriptor: (I)I
@@ -2710,6 +2744,9 @@
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
 
   public static long nativeLongPlus_should_be_like_this(long, long);
     descriptor: (JJ)J
@@ -2776,6 +2813,9 @@
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
 
   public int nativeNonStaticAddToValue_should_be_like_this(int);
     descriptor: (I)I
@@ -2831,9 +2871,6 @@
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
-    RuntimeInvisibleAnnotations:
-      x: #x()
-        android.hosttest.annotation.HostSideTestKeep
 
   public static void nativeStillNotSupported_should_be_like_this();
     descriptor: ()V
@@ -2873,6 +2910,52 @@
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
+
+  public void notNativeRedirected();
+    descriptor: ()V
+    flags: (0x0001) ACC_PUBLIC
+    Code:
+      stack=4, locals=1, args_size=1
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+         x: ldc           #x                 // String notNativeRedirected
+         x: ldc           #x                 // String ()V
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: aload_0
+        x: invokestatic  #x                // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.notNativeRedirected:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V
+        x: return
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
+
+  public static void notNativeStaticRedirected();
+    descriptor: ()V
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=0, args_size=0
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+         x: ldc           #x                // String notNativeStaticRedirected
+         x: ldc           #x                 // String ()V
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: invokestatic  #x                // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.notNativeStaticRedirected:()V
+        x: return
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+    RuntimeInvisibleAnnotations:
+      x: #x()
+        android.hosttest.annotation.HostSideTestRedirect
 }
 SourceFile: "TinyFrameworkNative.java"
 RuntimeVisibleAnnotations:
@@ -2882,7 +2965,7 @@
   x: #x()
     android.hosttest.annotation.HostSideTestWholeClassKeep
   x: #x(#x=s#x)
-    android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+    android.hosttest.annotation.HostSideTestRedirectionClass(
       value="TinyFrameworkNative_host"
     )
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class
@@ -2893,7 +2976,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 6, attributes: 3
+  interfaces: 0, fields: 0, methods: 8, attributes: 3
   private static {};
     descriptor: ()V
     flags: (0x000a) ACC_PRIVATE, ACC_STATIC
@@ -3017,6 +3100,41 @@
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  public static void notNativeRedirected(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative);
+    descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=1, args_size=1
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+         x: ldc           #x                 // String notNativeRedirected
+         x: ldc           #x                 // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: return
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+           11       1     0 source   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  public static void notNativeStaticRedirected();
+    descriptor: ()V
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=0, args_size=0
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+         x: ldc           #x                 // String notNativeStaticRedirected
+         x: ldc           #x                 // String ()V
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: return
+      LineNumberTable:
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 SourceFile: "TinyFrameworkNative_host.java"
 RuntimeVisibleAnnotations:
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
index 73b5e2f..04a551c 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
@@ -15,20 +15,23 @@
  */
 package com.android.hoststubgen.test.tinyframework;
 
-import android.hosttest.annotation.HostSideTestKeep;
-import android.hosttest.annotation.HostSideTestNativeSubstitutionClass;
+import android.hosttest.annotation.HostSideTestRedirect;
+import android.hosttest.annotation.HostSideTestRedirectionClass;
 import android.hosttest.annotation.HostSideTestThrow;
 import android.hosttest.annotation.HostSideTestWholeClassKeep;
 
 @HostSideTestWholeClassKeep
-@HostSideTestNativeSubstitutionClass("TinyFrameworkNative_host")
+@HostSideTestRedirectionClass("TinyFrameworkNative_host")
 public class TinyFrameworkNative {
+
+    @HostSideTestRedirect
     public static native int nativeAddTwo(int arg);
 
     public static int nativeAddTwo_should_be_like_this(int arg) {
         return TinyFrameworkNative_host.nativeAddTwo(arg);
     }
 
+    @HostSideTestRedirect
     public static native long nativeLongPlus(long arg1, long arg2);
 
     public static long nativeLongPlus_should_be_like_this(long arg1, long arg2) {
@@ -41,6 +44,7 @@
         this.value = v;
     }
 
+    @HostSideTestRedirect
     public native int nativeNonStaticAddToValue(int arg);
 
     public int nativeNonStaticAddToValue_should_be_like_this(int arg) {
@@ -50,12 +54,22 @@
     @HostSideTestThrow
     public static native void nativeStillNotSupported();
 
-    @HostSideTestKeep
     public static native void nativeStillKeep();
 
     public static void nativeStillNotSupported_should_be_like_this() {
         throw new RuntimeException();
     }
 
+    @HostSideTestRedirect
     public static native byte nativeBytePlus(byte arg1, byte arg2);
+
+    @HostSideTestRedirect
+    public void notNativeRedirected() {
+        throw new RuntimeException();
+    }
+
+    @HostSideTestRedirect
+    public static void notNativeStaticRedirected() {
+        throw new RuntimeException();
+    }
 }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
index b23c216..c7a29a1 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
@@ -17,8 +17,6 @@
 
 import android.hosttest.annotation.HostSideTestWholeClassKeep;
 
-// TODO: This annotation shouldn't be needed.
-// We should infer it from HostSideTestNativeSubstitutionClass.
 @HostSideTestWholeClassKeep
 public class TinyFrameworkNative_host {
     public static int nativeAddTwo(int arg) {
@@ -38,4 +36,10 @@
     public static byte nativeBytePlus(byte arg1, byte arg2) {
         return (byte) (arg1 + arg2);
     }
+
+    public static void notNativeRedirected(TinyFrameworkNative source) {
+    }
+
+    public static void notNativeStaticRedirected() {
+    }
 }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
index 14229a0..68673dc 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
@@ -164,6 +164,12 @@
     }
 
     @Test
+    public void testNotNativeRedirect() {
+        TinyFrameworkNative.notNativeStaticRedirected();
+        new TinyFrameworkNative().notNativeRedirected();
+    }
+
+    @Test
     public void testExitLog() {
         thrown.expect(RuntimeException.class);
         thrown.expectMessage("Outer exception");
diff --git a/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt b/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
index 24d203f..f5af99e 100644
--- a/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
+++ b/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
@@ -24,20 +24,31 @@
 import org.jetbrains.uast.UMethod
 
 /**
- * Given a UMethod, determine if this method is the entrypoint to an interface
- * generated by AIDL, returning the interface name if so, otherwise returning
- * null
+ * Given a UMethod, determine if this method is the entrypoint to an interface generated by AIDL,
+ * returning the interface name if so, otherwise returning null.
  */
 fun getContainingAidlInterface(context: JavaContext, node: UMethod): String? {
+    return containingAidlInterfacePsiClass(context, node)?.name
+}
+
+/**
+ * Given a UMethod, determine if this method is the entrypoint to an interface generated by AIDL,
+ * returning the fully qualified interface name if so, otherwise returning null.
+ */
+fun getContainingAidlInterfaceQualified(context: JavaContext, node: UMethod): String? {
+    return containingAidlInterfacePsiClass(context, node)?.qualifiedName
+}
+
+private fun containingAidlInterfacePsiClass(context: JavaContext, node: UMethod): PsiClass? {
     val containingStub = containingStub(context, node) ?: return null
     val superMethod = node.findSuperMethods(containingStub)
     if (superMethod.isEmpty()) return null
-    return containingStub.containingClass?.name
+    return containingStub.containingClass
 }
 
-/* Returns the containing Stub class if any. This is not sufficient to infer
- * that the method itself extends an AIDL generated method. See
- * getContainingAidlInterface for that purpose.
+/**
+ * Returns the containing Stub class if any. This is not sufficient to infer that the method itself
+ * extends an AIDL generated method. See getContainingAidlInterface for that purpose.
  */
 fun containingStub(context: JavaContext, node: UMethod?): PsiClass? {
     var superClass = node?.containingClass?.superClass
@@ -48,7 +59,7 @@
     return null
 }
 
-private fun isStub(context: JavaContext, psiClass: PsiClass?): Boolean {
+fun isStub(context: JavaContext, psiClass: PsiClass?): Boolean {
     if (psiClass == null) return false
     if (psiClass.name != "Stub") return false
     if (!context.evaluator.isStatic(psiClass)) return false
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfaces.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfaces.kt
new file mode 100644
index 0000000..8777712
--- /dev/null
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfaces.kt
@@ -0,0 +1,774 @@
+/*
+ * Copyright (C) 2024 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.google.android.lint.aidl
+
+/**
+ * The exemptAidlInterfaces set was generated by running ExemptAidlInterfacesGenerator on the
+ * entire source tree. To reproduce the results, run generate-exempt-aidl-interfaces.sh
+ * located in tools/lint/utils.
+ *
+ * TODO: b/363248121 - Use the exemptAidlInterfaces set inside PermissionAnnotationDetector when it
+ * gets migrated to a global lint check.
+ */
+val exemptAidlInterfaces = setOf(
+    "android.accessibilityservice.IAccessibilityServiceConnection",
+    "android.accessibilityservice.IBrailleDisplayConnection",
+    "android.accounts.IAccountAuthenticatorResponse",
+    "android.accounts.IAccountManager",
+    "android.accounts.IAccountManagerResponse",
+    "android.adservices.adid.IAdIdProviderService",
+    "android.adservices.adid.IAdIdService",
+    "android.adservices.adid.IGetAdIdCallback",
+    "android.adservices.adid.IGetAdIdProviderCallback",
+    "android.adservices.adselection.AdSelectionCallback",
+    "android.adservices.adselection.AdSelectionOverrideCallback",
+    "android.adservices.adselection.AdSelectionService",
+    "android.adservices.adselection.GetAdSelectionDataCallback",
+    "android.adservices.adselection.PersistAdSelectionResultCallback",
+    "android.adservices.adselection.ReportImpressionCallback",
+    "android.adservices.adselection.ReportInteractionCallback",
+    "android.adservices.adselection.SetAppInstallAdvertisersCallback",
+    "android.adservices.adselection.UpdateAdCounterHistogramCallback",
+    "android.adservices.appsetid.IAppSetIdProviderService",
+    "android.adservices.appsetid.IAppSetIdService",
+    "android.adservices.appsetid.IGetAppSetIdCallback",
+    "android.adservices.appsetid.IGetAppSetIdProviderCallback",
+    "android.adservices.cobalt.IAdServicesCobaltUploadService",
+    "android.adservices.common.IAdServicesCommonCallback",
+    "android.adservices.common.IAdServicesCommonService",
+    "android.adservices.common.IAdServicesCommonStatesCallback",
+    "android.adservices.common.IEnableAdServicesCallback",
+    "android.adservices.common.IUpdateAdIdCallback",
+    "android.adservices.customaudience.CustomAudienceOverrideCallback",
+    "android.adservices.customaudience.FetchAndJoinCustomAudienceCallback",
+    "android.adservices.customaudience.ICustomAudienceCallback",
+    "android.adservices.customaudience.ICustomAudienceService",
+    "android.adservices.customaudience.ScheduleCustomAudienceUpdateCallback",
+    "android.adservices.extdata.IAdServicesExtDataStorageService",
+    "android.adservices.extdata.IGetAdServicesExtDataCallback",
+    "android.adservices.measurement.IMeasurementApiStatusCallback",
+    "android.adservices.measurement.IMeasurementCallback",
+    "android.adservices.measurement.IMeasurementService",
+    "android.adservices.ondevicepersonalization.aidl.IDataAccessService",
+    "android.adservices.ondevicepersonalization.aidl.IDataAccessServiceCallback",
+    "android.adservices.ondevicepersonalization.aidl.IExecuteCallback",
+    "android.adservices.ondevicepersonalization.aidl.IFederatedComputeCallback",
+    "android.adservices.ondevicepersonalization.aidl.IFederatedComputeService",
+    "android.adservices.ondevicepersonalization.aidl.IIsolatedModelService",
+    "android.adservices.ondevicepersonalization.aidl.IIsolatedModelServiceCallback",
+    "android.adservices.ondevicepersonalization.aidl.IIsolatedService",
+    "android.adservices.ondevicepersonalization.aidl.IIsolatedServiceCallback",
+    "android.adservices.ondevicepersonalization.aidl.IOnDevicePersonalizationConfigService",
+    "android.adservices.ondevicepersonalization.aidl.IOnDevicePersonalizationConfigServiceCallback",
+    "android.adservices.ondevicepersonalization.aidl.IOnDevicePersonalizationDebugService",
+    "android.adservices.ondevicepersonalization.aidl.IOnDevicePersonalizationManagingService",
+    "android.adservices.ondevicepersonalization.aidl.IRegisterMeasurementEventCallback",
+    "android.adservices.ondevicepersonalization.aidl.IRequestSurfacePackageCallback",
+    "android.adservices.shell.IShellCommand",
+    "android.adservices.shell.IShellCommandCallback",
+    "android.adservices.signals.IProtectedSignalsService",
+    "android.adservices.signals.UpdateSignalsCallback",
+    "android.adservices.topics.IGetTopicsCallback",
+    "android.adservices.topics.ITopicsService",
+    "android.app.admin.IDevicePolicyManager",
+    "android.app.adservices.IAdServicesManager",
+    "android.app.ambientcontext.IAmbientContextManager",
+    "android.app.ambientcontext.IAmbientContextObserver",
+    "android.app.appsearch.aidl.IAppFunctionService",
+    "android.app.appsearch.aidl.IAppSearchBatchResultCallback",
+    "android.app.appsearch.aidl.IAppSearchManager",
+    "android.app.appsearch.aidl.IAppSearchObserverProxy",
+    "android.app.appsearch.aidl.IAppSearchResultCallback",
+    "android.app.backup.IBackupCallback",
+    "android.app.backup.IBackupManager",
+    "android.app.backup.IRestoreSession",
+    "android.app.blob.IBlobCommitCallback",
+    "android.app.blob.IBlobStoreManager",
+    "android.app.blob.IBlobStoreSession",
+    "android.app.contentsuggestions.IContentSuggestionsManager",
+    "android.app.contextualsearch.IContextualSearchManager",
+    "android.app.ecm.IEnhancedConfirmationManager",
+    "android.apphibernation.IAppHibernationService",
+    "android.app.IActivityClientController",
+    "android.app.IActivityController",
+    "android.app.IActivityTaskManager",
+    "android.app.IAlarmCompleteListener",
+    "android.app.IAlarmListener",
+    "android.app.IAlarmManager",
+    "android.app.IApplicationThread",
+    "android.app.IAppTask",
+    "android.app.IAppTraceRetriever",
+    "android.app.IAssistDataReceiver",
+    "android.app.IForegroundServiceObserver",
+    "android.app.IGameManagerService",
+    "android.app.IGrammaticalInflectionManager",
+    "android.app.ILocaleManager",
+    "android.app.INotificationManager",
+    "android.app.IParcelFileDescriptorRetriever",
+    "android.app.IProcessObserver",
+    "android.app.ISearchManager",
+    "android.app.IStopUserCallback",
+    "android.app.ITaskStackListener",
+    "android.app.IUiModeManager",
+    "android.app.IUriGrantsManager",
+    "android.app.IUserSwitchObserver",
+    "android.app.IWallpaperManager",
+    "android.app.job.IJobCallback",
+    "android.app.job.IJobScheduler",
+    "android.app.job.IJobService",
+    "android.app.ondeviceintelligence.IDownloadCallback",
+    "android.app.ondeviceintelligence.IFeatureCallback",
+    "android.app.ondeviceintelligence.IFeatureDetailsCallback",
+    "android.app.ondeviceintelligence.IListFeaturesCallback",
+    "android.app.ondeviceintelligence.IOnDeviceIntelligenceManager",
+    "android.app.ondeviceintelligence.IProcessingSignal",
+    "android.app.ondeviceintelligence.IResponseCallback",
+    "android.app.ondeviceintelligence.IStreamingResponseCallback",
+    "android.app.ondeviceintelligence.ITokenInfoCallback",
+    "android.app.people.IPeopleManager",
+    "android.app.pinner.IPinnerService",
+    "android.app.prediction.IPredictionManager",
+    "android.app.role.IOnRoleHoldersChangedListener",
+    "android.app.role.IRoleController",
+    "android.app.role.IRoleManager",
+    "android.app.sdksandbox.ILoadSdkCallback",
+    "android.app.sdksandbox.IRequestSurfacePackageCallback",
+    "android.app.sdksandbox.ISdkSandboxManager",
+    "android.app.sdksandbox.ISdkSandboxProcessDeathCallback",
+    "android.app.sdksandbox.ISdkToServiceCallback",
+    "android.app.sdksandbox.ISharedPreferencesSyncCallback",
+    "android.app.sdksandbox.IUnloadSdkCallback",
+    "android.app.sdksandbox.testutils.testscenario.ISdkSandboxTestExecutor",
+    "android.app.search.ISearchUiManager",
+    "android.app.slice.ISliceManager",
+    "android.app.smartspace.ISmartspaceManager",
+    "android.app.timedetector.ITimeDetectorService",
+    "android.app.timezonedetector.ITimeZoneDetectorService",
+    "android.app.trust.ITrustManager",
+    "android.app.usage.IStorageStatsManager",
+    "android.app.usage.IUsageStatsManager",
+    "android.app.wallpapereffectsgeneration.IWallpaperEffectsGenerationManager",
+    "android.app.wearable.IWearableSensingCallback",
+    "android.app.wearable.IWearableSensingManager",
+    "android.bluetooth.IBluetooth",
+    "android.bluetooth.IBluetoothA2dp",
+    "android.bluetooth.IBluetoothA2dpSink",
+    "android.bluetooth.IBluetoothActivityEnergyInfoListener",
+    "android.bluetooth.IBluetoothAvrcpController",
+    "android.bluetooth.IBluetoothCallback",
+    "android.bluetooth.IBluetoothConnectionCallback",
+    "android.bluetooth.IBluetoothCsipSetCoordinator",
+    "android.bluetooth.IBluetoothCsipSetCoordinatorLockCallback",
+    "android.bluetooth.IBluetoothGatt",
+    "android.bluetooth.IBluetoothGattCallback",
+    "android.bluetooth.IBluetoothGattServerCallback",
+    "android.bluetooth.IBluetoothHapClient",
+    "android.bluetooth.IBluetoothHapClientCallback",
+    "android.bluetooth.IBluetoothHeadset",
+    "android.bluetooth.IBluetoothHeadsetClient",
+    "android.bluetooth.IBluetoothHearingAid",
+    "android.bluetooth.IBluetoothHidDevice",
+    "android.bluetooth.IBluetoothHidDeviceCallback",
+    "android.bluetooth.IBluetoothHidHost",
+    "android.bluetooth.IBluetoothLeAudio",
+    "android.bluetooth.IBluetoothLeAudioCallback",
+    "android.bluetooth.IBluetoothLeBroadcastAssistant",
+    "android.bluetooth.IBluetoothLeBroadcastAssistantCallback",
+    "android.bluetooth.IBluetoothLeBroadcastCallback",
+    "android.bluetooth.IBluetoothLeCallControl",
+    "android.bluetooth.IBluetoothLeCallControlCallback",
+    "android.bluetooth.IBluetoothManager",
+    "android.bluetooth.IBluetoothManagerCallback",
+    "android.bluetooth.IBluetoothMap",
+    "android.bluetooth.IBluetoothMapClient",
+    "android.bluetooth.IBluetoothMcpServiceManager",
+    "android.bluetooth.IBluetoothMetadataListener",
+    "android.bluetooth.IBluetoothOobDataCallback",
+    "android.bluetooth.IBluetoothPan",
+    "android.bluetooth.IBluetoothPanCallback",
+    "android.bluetooth.IBluetoothPbap",
+    "android.bluetooth.IBluetoothPbapClient",
+    "android.bluetooth.IBluetoothPreferredAudioProfilesCallback",
+    "android.bluetooth.IBluetoothQualityReportReadyCallback",
+    "android.bluetooth.IBluetoothSap",
+    "android.bluetooth.IBluetoothScan",
+    "android.bluetooth.IBluetoothSocketManager",
+    "android.bluetooth.IBluetoothVolumeControl",
+    "android.bluetooth.IBluetoothVolumeControlCallback",
+    "android.bluetooth.le.IAdvertisingSetCallback",
+    "android.bluetooth.le.IDistanceMeasurementCallback",
+    "android.bluetooth.le.IPeriodicAdvertisingCallback",
+    "android.bluetooth.le.IScannerCallback",
+    "android.companion.ICompanionDeviceManager",
+    "android.companion.IOnMessageReceivedListener",
+    "android.companion.IOnTransportsChangedListener",
+    "android.companion.virtualcamera.IVirtualCameraCallback",
+    "android.companion.virtual.IVirtualDevice",
+    "android.companion.virtual.IVirtualDeviceManager",
+    "android.companion.virtualnative.IVirtualDeviceManagerNative",
+    "android.content.IClipboard",
+    "android.content.IContentService",
+    "android.content.IIntentReceiver",
+    "android.content.IIntentSender",
+    "android.content.integrity.IAppIntegrityManager",
+    "android.content.IRestrictionsManager",
+    "android.content.ISyncAdapterUnsyncableAccountCallback",
+    "android.content.ISyncContext",
+    "android.content.om.IOverlayManager",
+    "android.content.pm.dex.IArtManager",
+    "android.content.pm.dex.ISnapshotRuntimeProfileCallback",
+    "android.content.pm.IBackgroundInstallControlService",
+    "android.content.pm.ICrossProfileApps",
+    "android.content.pm.IDataLoaderManager",
+    "android.content.pm.IDataLoaderStatusListener",
+    "android.content.pm.ILauncherApps",
+    "android.content.pm.IOnChecksumsReadyListener",
+    "android.content.pm.IOtaDexopt",
+    "android.content.pm.IPackageDataObserver",
+    "android.content.pm.IPackageDeleteObserver",
+    "android.content.pm.IPackageInstaller",
+    "android.content.pm.IPackageInstallerSession",
+    "android.content.pm.IPackageInstallerSessionFileSystemConnector",
+    "android.content.pm.IPackageInstallObserver2",
+    "android.content.pm.IPackageLoadingProgressCallback",
+    "android.content.pm.IPackageManager",
+    "android.content.pm.IPackageManagerNative",
+    "android.content.pm.IPackageMoveObserver",
+    "android.content.pm.IPinItemRequest",
+    "android.content.pm.IShortcutService",
+    "android.content.pm.IStagedApexObserver",
+    "android.content.pm.verify.domain.IDomainVerificationManager",
+    "android.content.res.IResourcesManager",
+    "android.content.rollback.IRollbackManager",
+    "android.credentials.ICredentialManager",
+    "android.debug.IAdbTransport",
+    "android.devicelock.IDeviceLockService",
+    "android.devicelock.IGetDeviceIdCallback",
+    "android.devicelock.IGetKioskAppsCallback",
+    "android.devicelock.IIsDeviceLockedCallback",
+    "android.devicelock.IVoidResultCallback",
+    "android.federatedcompute.aidl.IExampleStoreCallback",
+    "android.federatedcompute.aidl.IExampleStoreIterator",
+    "android.federatedcompute.aidl.IExampleStoreIteratorCallback",
+    "android.federatedcompute.aidl.IExampleStoreService",
+    "android.federatedcompute.aidl.IFederatedComputeCallback",
+    "android.federatedcompute.aidl.IFederatedComputeService",
+    "android.federatedcompute.aidl.IResultHandlingService",
+    "android.flags.IFeatureFlags",
+    "android.frameworks.location.altitude.IAltitudeService",
+    "android.frameworks.vibrator.IVibratorController",
+    "android.frameworks.vibrator.IVibratorControlService",
+    "android.gsi.IGsiServiceCallback",
+    "android.hardware.biometrics.AuthenticationStateListener",
+    "android.hardware.biometrics.common.ICancellationSignal",
+    "android.hardware.biometrics.face.IFace",
+    "android.hardware.biometrics.face.ISession",
+    "android.hardware.biometrics.face.ISessionCallback",
+    "android.hardware.biometrics.fingerprint.IFingerprint",
+    "android.hardware.biometrics.fingerprint.ISession",
+    "android.hardware.biometrics.fingerprint.ISessionCallback",
+    "android.hardware.biometrics.IAuthService",
+    "android.hardware.biometrics.IBiometricAuthenticator",
+    "android.hardware.biometrics.IBiometricContextListener",
+    "android.hardware.biometrics.IBiometricSensorReceiver",
+    "android.hardware.biometrics.IBiometricService",
+    "android.hardware.biometrics.IBiometricStateListener",
+    "android.hardware.biometrics.IBiometricSysuiReceiver",
+    "android.hardware.biometrics.IInvalidationCallback",
+    "android.hardware.biometrics.ITestSession",
+    "android.hardware.broadcastradio.IAnnouncementListener",
+    "android.hardware.broadcastradio.ITunerCallback",
+    "android.hardware.contexthub.IContextHubCallback",
+    "android.hardware.devicestate.IDeviceStateManager",
+    "android.hardware.display.IColorDisplayManager",
+    "android.hardware.display.IDisplayManager",
+    "android.hardware.face.IFaceAuthenticatorsRegisteredCallback",
+    "android.hardware.face.IFaceService",
+    "android.hardware.face.IFaceServiceReceiver",
+    "android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback",
+    "android.hardware.fingerprint.IFingerprintClientActiveCallback",
+    "android.hardware.fingerprint.IFingerprintService",
+    "android.hardware.fingerprint.IFingerprintServiceReceiver",
+    "android.hardware.fingerprint.IUdfpsOverlayControllerCallback",
+    "android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback",
+    "android.hardware.hdmi.IHdmiControlCallback",
+    "android.hardware.hdmi.IHdmiControlService",
+    "android.hardware.hdmi.IHdmiDeviceEventListener",
+    "android.hardware.hdmi.IHdmiHotplugEventListener",
+    "android.hardware.hdmi.IHdmiSystemAudioModeChangeListener",
+    "android.hardware.health.IHealthInfoCallback",
+    "android.hardware.ICameraServiceProxy",
+    "android.hardware.IConsumerIrService",
+    "android.hardware.input.IInputManager",
+    "android.hardware.iris.IIrisService",
+    "android.hardware.ISensorPrivacyManager",
+    "android.hardware.ISerialManager",
+    "android.hardware.lights.ILightsManager",
+    "android.hardware.location.IContextHubClient",
+    "android.hardware.location.IContextHubClientCallback",
+    "android.hardware.location.IContextHubService",
+    "android.hardware.location.IContextHubTransactionCallback",
+    "android.hardware.location.ISignificantPlaceProviderManager",
+    "android.hardware.radio.IAnnouncementListener",
+    "android.hardware.radio.ICloseHandle",
+    "android.hardware.radio.ims.media.IImsMedia",
+    "android.hardware.radio.ims.media.IImsMediaListener",
+    "android.hardware.radio.ims.media.IImsMediaSession",
+    "android.hardware.radio.ims.media.IImsMediaSessionListener",
+    "android.hardware.radio.IRadioService",
+    "android.hardware.radio.ITuner",
+    "android.hardware.radio.sap.ISapCallback",
+    "android.hardware.soundtrigger3.ISoundTriggerHw",
+    "android.hardware.soundtrigger3.ISoundTriggerHwCallback",
+    "android.hardware.soundtrigger3.ISoundTriggerHwGlobalCallback",
+    "android.hardware.soundtrigger.IRecognitionStatusCallback",
+    "android.hardware.tetheroffload.ITetheringOffloadCallback",
+    "android.hardware.thermal.IThermalChangedCallback",
+    "android.hardware.tv.hdmi.cec.IHdmiCecCallback",
+    "android.hardware.tv.hdmi.connection.IHdmiConnectionCallback",
+    "android.hardware.tv.hdmi.earc.IEArcCallback",
+    "android.hardware.usb.gadget.IUsbGadgetCallback",
+    "android.hardware.usb.IUsbCallback",
+    "android.hardware.usb.IUsbManager",
+    "android.hardware.usb.IUsbSerialReader",
+    "android.hardware.wifi.hostapd.IHostapdCallback",
+    "android.hardware.wifi.IWifiChipEventCallback",
+    "android.hardware.wifi.IWifiEventCallback",
+    "android.hardware.wifi.IWifiNanIfaceEventCallback",
+    "android.hardware.wifi.IWifiRttControllerEventCallback",
+    "android.hardware.wifi.IWifiStaIfaceEventCallback",
+    "android.hardware.wifi.supplicant.INonStandardCertCallback",
+    "android.hardware.wifi.supplicant.ISupplicantP2pIfaceCallback",
+    "android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback",
+    "android.hardware.wifi.supplicant.ISupplicantStaNetworkCallback",
+    "android.health.connect.aidl.IAccessLogsResponseCallback",
+    "android.health.connect.aidl.IActivityDatesResponseCallback",
+    "android.health.connect.aidl.IAggregateRecordsResponseCallback",
+    "android.health.connect.aidl.IApplicationInfoResponseCallback",
+    "android.health.connect.aidl.IChangeLogsResponseCallback",
+    "android.health.connect.aidl.IDataStagingFinishedCallback",
+    "android.health.connect.aidl.IEmptyResponseCallback",
+    "android.health.connect.aidl.IGetChangeLogTokenCallback",
+    "android.health.connect.aidl.IGetHealthConnectDataStateCallback",
+    "android.health.connect.aidl.IGetHealthConnectMigrationUiStateCallback",
+    "android.health.connect.aidl.IGetPriorityResponseCallback",
+    "android.health.connect.aidl.IHealthConnectService",
+    "android.health.connect.aidl.IInsertRecordsResponseCallback",
+    "android.health.connect.aidl.IMedicalDataSourceResponseCallback",
+    "android.health.connect.aidl.IMedicalResourcesResponseCallback",
+    "android.health.connect.aidl.IMigrationCallback",
+    "android.health.connect.aidl.IReadMedicalResourcesResponseCallback",
+    "android.health.connect.aidl.IReadRecordsResponseCallback",
+    "android.health.connect.aidl.IRecordTypeInfoResponseCallback",
+    "android.health.connect.exportimport.IImportStatusCallback",
+    "android.health.connect.exportimport.IQueryDocumentProvidersCallback",
+    "android.health.connect.exportimport.IScheduledExportStatusCallback",
+    "android.location.ICountryDetector",
+    "android.location.IGpsGeofenceHardware",
+    "android.location.ILocationManager",
+    "android.location.provider.ILocationProviderManager",
+    "android.media.IAudioRoutesObserver",
+    "android.media.IMediaCommunicationService",
+    "android.media.IMediaCommunicationServiceCallback",
+    "android.media.IMediaController2",
+    "android.media.IMediaRoute2ProviderServiceCallback",
+    "android.media.IMediaRouterService",
+    "android.media.IMediaSession2",
+    "android.media.IMediaSession2Service",
+    "android.media.INativeSpatializerCallback",
+    "android.media.IPlaybackConfigDispatcher",
+    "android.media.IRecordingConfigDispatcher",
+    "android.media.IRemoteDisplayCallback",
+    "android.media.ISoundDoseCallback",
+    "android.media.ISpatializerHeadTrackingCallback",
+    "android.media.ITranscodingClientCallback",
+    "android.media.metrics.IMediaMetricsManager",
+    "android.media.midi.IMidiManager",
+    "android.media.musicrecognition.IMusicRecognitionAttributionTagCallback",
+    "android.media.musicrecognition.IMusicRecognitionManager",
+    "android.media.musicrecognition.IMusicRecognitionServiceCallback",
+    "android.media.projection.IMediaProjection",
+    "android.media.projection.IMediaProjectionCallback",
+    "android.media.projection.IMediaProjectionManager",
+    "android.media.projection.IMediaProjectionWatcherCallback",
+    "android.media.session.ISession",
+    "android.media.session.ISessionController",
+    "android.media.session.ISessionManager",
+    "android.media.soundtrigger.ISoundTriggerDetectionServiceClient",
+    "android.media.soundtrigger_middleware.IInjectGlobalEvent",
+    "android.media.soundtrigger_middleware.IInjectModelEvent",
+    "android.media.soundtrigger_middleware.IInjectRecognitionEvent",
+    "android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService",
+    "android.media.soundtrigger_middleware.ISoundTriggerModule",
+    "android.media.tv.ad.ITvAdManager",
+    "android.media.tv.ad.ITvAdSessionCallback",
+    "android.media.tv.interactive.ITvInteractiveAppManager",
+    "android.media.tv.interactive.ITvInteractiveAppServiceCallback",
+    "android.media.tv.interactive.ITvInteractiveAppSessionCallback",
+    "android.media.tv.ITvInputHardware",
+    "android.media.tv.ITvInputManager",
+    "android.media.tv.ITvInputServiceCallback",
+    "android.media.tv.ITvInputSessionCallback",
+    "android.media.tv.ITvRemoteServiceInput",
+    "android.nearby.aidl.IOffloadCallback",
+    "android.nearby.IBroadcastListener",
+    "android.nearby.INearbyManager",
+    "android.nearby.IScanListener",
+    "android.net.connectivity.aidl.ConnectivityNative",
+    "android.net.dhcp.IDhcpEventCallbacks",
+    "android.net.dhcp.IDhcpServer",
+    "android.net.dhcp.IDhcpServerCallbacks",
+    "android.net.ICaptivePortal",
+    "android.net.IConnectivityDiagnosticsCallback",
+    "android.net.IConnectivityManager",
+    "android.net.IEthernetManager",
+    "android.net.IEthernetServiceListener",
+    "android.net.IIntResultListener",
+    "android.net.IIpConnectivityMetrics",
+    "android.net.IIpMemoryStore",
+    "android.net.IIpMemoryStoreCallbacks",
+    "android.net.IIpSecService",
+    "android.net.INetdEventCallback",
+    "android.net.INetdUnsolicitedEventListener",
+    "android.net.INetworkActivityListener",
+    "android.net.INetworkAgent",
+    "android.net.INetworkAgentRegistry",
+    "android.net.INetworkInterfaceOutcomeReceiver",
+    "android.net.INetworkManagementEventObserver",
+    "android.net.INetworkMonitor",
+    "android.net.INetworkMonitorCallbacks",
+    "android.net.INetworkOfferCallback",
+    "android.net.INetworkPolicyListener",
+    "android.net.INetworkPolicyManager",
+    "android.net.INetworkScoreService",
+    "android.net.INetworkStackConnector",
+    "android.net.INetworkStackStatusCallback",
+    "android.net.INetworkStatsService",
+    "android.net.INetworkStatsSession",
+    "android.net.IOnCompleteListener",
+    "android.net.IPacProxyManager",
+    "android.net.ip.IIpClient",
+    "android.net.ip.IIpClientCallbacks",
+    "android.net.ipmemorystore.IOnBlobRetrievedListener",
+    "android.net.ipmemorystore.IOnL2KeyResponseListener",
+    "android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener",
+    "android.net.ipmemorystore.IOnSameL3NetworkResponseListener",
+    "android.net.ipmemorystore.IOnStatusAndCountListener",
+    "android.net.ipmemorystore.IOnStatusListener",
+    "android.net.IQosCallback",
+    "android.net.ISocketKeepaliveCallback",
+    "android.net.ITestNetworkManager",
+    "android.net.ITetheredInterfaceCallback",
+    "android.net.ITetheringConnector",
+    "android.net.ITetheringEventCallback",
+    "android.net.IVpnManager",
+    "android.net.mdns.aidl.IMDnsEventListener",
+    "android.net.metrics.INetdEventListener",
+    "android.net.netstats.IUsageCallback",
+    "android.net.netstats.provider.INetworkStatsProvider",
+    "android.net.netstats.provider.INetworkStatsProviderCallback",
+    "android.net.nsd.INsdManager",
+    "android.net.nsd.INsdManagerCallback",
+    "android.net.nsd.INsdServiceConnector",
+    "android.net.nsd.IOffloadEngine",
+    "android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener",
+    "android.net.thread.IActiveOperationalDatasetReceiver",
+    "android.net.thread.IConfigurationReceiver",
+    "android.net.thread.IOperationalDatasetCallback",
+    "android.net.thread.IOperationReceiver",
+    "android.net.thread.IStateCallback",
+    "android.net.thread.IThreadNetworkController",
+    "android.net.thread.IThreadNetworkManager",
+    "android.net.vcn.IVcnManagementService",
+    "android.net.wear.ICompanionDeviceManagerProxy",
+    "android.net.wifi.aware.IWifiAwareDiscoverySessionCallback",
+    "android.net.wifi.aware.IWifiAwareEventCallback",
+    "android.net.wifi.aware.IWifiAwareMacAddressProvider",
+    "android.net.wifi.aware.IWifiAwareManager",
+    "android.net.wifi.hotspot2.IProvisioningCallback",
+    "android.net.wifi.IActionListener",
+    "android.net.wifi.IBooleanListener",
+    "android.net.wifi.IByteArrayListener",
+    "android.net.wifi.ICoexCallback",
+    "android.net.wifi.IDppCallback",
+    "android.net.wifi.IIntegerListener",
+    "android.net.wifi.IInterfaceCreationInfoCallback",
+    "android.net.wifi.ILastCallerListener",
+    "android.net.wifi.IListListener",
+    "android.net.wifi.ILocalOnlyConnectionStatusListener",
+    "android.net.wifi.ILocalOnlyHotspotCallback",
+    "android.net.wifi.IMacAddressListListener",
+    "android.net.wifi.IMapListener",
+    "android.net.wifi.INetworkRequestMatchCallback",
+    "android.net.wifi.INetworkRequestUserSelectionCallback",
+    "android.net.wifi.IOnWifiActivityEnergyInfoListener",
+    "android.net.wifi.IOnWifiDriverCountryCodeChangedListener",
+    "android.net.wifi.IOnWifiUsabilityStatsListener",
+    "android.net.wifi.IPnoScanResultsCallback",
+    "android.net.wifi.IScanDataListener",
+    "android.net.wifi.IScanResultsCallback",
+    "android.net.wifi.IScoreUpdateObserver",
+    "android.net.wifi.ISoftApCallback",
+    "android.net.wifi.IStringListener",
+    "android.net.wifi.ISubsystemRestartCallback",
+    "android.net.wifi.ISuggestionConnectionStatusListener",
+    "android.net.wifi.ISuggestionUserApprovalStatusListener",
+    "android.net.wifi.ITrafficStateCallback",
+    "android.net.wifi.ITwtCallback",
+    "android.net.wifi.ITwtCapabilitiesListener",
+    "android.net.wifi.ITwtStatsListener",
+    "android.net.wifi.IWifiBandsListener",
+    "android.net.wifi.IWifiConnectedNetworkScorer",
+    "android.net.wifi.IWifiLowLatencyLockListener",
+    "android.net.wifi.IWifiManager",
+    "android.net.wifi.IWifiNetworkSelectionConfigListener",
+    "android.net.wifi.IWifiNetworkStateChangedListener",
+    "android.net.wifi.IWifiScanner",
+    "android.net.wifi.IWifiScannerListener",
+    "android.net.wifi.IWifiVerboseLoggingStatusChangedListener",
+    "android.net.wifi.p2p.IWifiP2pListener",
+    "android.net.wifi.p2p.IWifiP2pManager",
+    "android.net.wifi.rtt.IRttCallback",
+    "android.net.wifi.rtt.IWifiRttManager",
+    "android.ondevicepersonalization.IOnDevicePersonalizationSystemService",
+    "android.ondevicepersonalization.IOnDevicePersonalizationSystemServiceCallback",
+    "android.os.IBatteryPropertiesRegistrar",
+    "android.os.ICancellationSignal",
+    "android.os.IDeviceIdentifiersPolicyService",
+    "android.os.IDeviceIdleController",
+    "android.os.IDumpstate",
+    "android.os.IDumpstateListener",
+    "android.os.IExternalVibratorService",
+    "android.os.IHardwarePropertiesManager",
+    "android.os.IHintManager",
+    "android.os.IHintSession",
+    "android.os.IIncidentCompanion",
+    "android.os.image.IDynamicSystemService",
+    "android.os.incremental.IStorageHealthListener",
+    "android.os.INetworkManagementService",
+    "android.os.IPendingIntentRef",
+    "android.os.IPowerStatsService",
+    "android.os.IProfilingResultCallback",
+    "android.os.IProfilingService",
+    "android.os.IProgressListener",
+    "android.os.IPullAtomCallback",
+    "android.os.IRecoverySystem",
+    "android.os.IRemoteCallback",
+    "android.os.ISecurityStateManager",
+    "android.os.IServiceCallback",
+    "android.os.IStatsCompanionService",
+    "android.os.IStatsManagerService",
+    "android.os.IStatsQueryCallback",
+    "android.os.ISystemConfig",
+    "android.os.ISystemUpdateManager",
+    "android.os.IThermalEventListener",
+    "android.os.IUpdateLock",
+    "android.os.IUserManager",
+    "android.os.IUserRestrictionsListener",
+    "android.os.IVibratorManagerService",
+    "android.os.IVoldListener",
+    "android.os.IVoldMountCallback",
+    "android.os.IVoldTaskListener",
+    "android.os.logcat.ILogcatManagerService",
+    "android.permission.ILegacyPermissionManager",
+    "android.permission.IPermissionChecker",
+    "android.permission.IPermissionManager",
+    "android.print.IPrintManager",
+    "android.print.IPrintSpoolerCallbacks",
+    "android.print.IPrintSpoolerClient",
+    "android.printservice.IPrintServiceClient",
+    "android.printservice.recommendation.IRecommendationServiceCallbacks",
+    "android.provider.aidl.IDeviceConfigManager",
+    "android.remoteauth.IDeviceDiscoveryListener",
+    "android.safetycenter.IOnSafetyCenterDataChangedListener",
+    "android.safetycenter.ISafetyCenterManager",
+    "android.scheduling.IRebootReadinessManager",
+    "android.scheduling.IRequestRebootReadinessStatusListener",
+    "android.security.attestationverification.IAttestationVerificationManagerService",
+    "android.security.IFileIntegrityService",
+    "android.security.keystore.IKeyAttestationApplicationIdProvider",
+    "android.security.rkp.IRegistration",
+    "android.security.rkp.IRemoteProvisioning",
+    "android.service.appprediction.IPredictionService",
+    "android.service.assist.classification.IFieldClassificationCallback",
+    "android.service.attention.IAttentionCallback",
+    "android.service.attention.IProximityUpdateCallback",
+    "android.service.autofill.augmented.IFillCallback",
+    "android.service.autofill.IConvertCredentialCallback",
+    "android.service.autofill.IFillCallback",
+    "android.service.autofill.IInlineSuggestionUiCallback",
+    "android.service.autofill.ISaveCallback",
+    "android.service.autofill.ISurfacePackageResultCallback",
+    "android.service.contentcapture.IContentCaptureServiceCallback",
+    "android.service.contentcapture.IContentProtectionAllowlistCallback",
+    "android.service.contentcapture.IDataShareCallback",
+    "android.service.credentials.IBeginCreateCredentialCallback",
+    "android.service.credentials.IBeginGetCredentialCallback",
+    "android.service.credentials.IClearCredentialStateCallback",
+    "android.service.dreams.IDreamManager",
+    "android.service.games.IGameServiceController",
+    "android.service.games.IGameSessionController",
+    "android.service.notification.IStatusBarNotificationHolder",
+    "android.service.oemlock.IOemLockService",
+    "android.service.ondeviceintelligence.IProcessingUpdateStatusCallback",
+    "android.service.ondeviceintelligence.IRemoteProcessingService",
+    "android.service.ondeviceintelligence.IRemoteStorageService",
+    "android.service.persistentdata.IPersistentDataBlockService",
+    "android.service.resolver.IResolverRankerResult",
+    "android.service.rotationresolver.IRotationResolverCallback",
+    "android.service.textclassifier.ITextClassifierCallback",
+    "android.service.textclassifier.ITextClassifierService",
+    "android.service.timezone.ITimeZoneProviderManager",
+    "android.service.trust.ITrustAgentServiceCallback",
+    "android.service.voice.IDetectorSessionStorageService",
+    "android.service.voice.IDetectorSessionVisualQueryDetectionCallback",
+    "android.service.voice.IDspHotwordDetectionCallback",
+    "android.service.wallpaper.IWallpaperConnection",
+    "android.speech.IRecognitionListener",
+    "android.speech.IRecognitionService",
+    "android.speech.IRecognitionServiceManager",
+    "android.speech.tts.ITextToSpeechManager",
+    "android.speech.tts.ITextToSpeechSession",
+    "android.system.composd.ICompilationTaskCallback",
+    "android.system.virtualizationmaintenance.IVirtualizationReconciliationCallback",
+    "android.system.virtualizationservice.IVirtualMachineCallback",
+    "android.system.vmtethering.IVmTethering",
+    "android.telephony.imsmedia.IImsAudioSession",
+    "android.telephony.imsmedia.IImsAudioSessionCallback",
+    "android.telephony.imsmedia.IImsMedia",
+    "android.telephony.imsmedia.IImsMediaCallback",
+    "android.telephony.imsmedia.IImsTextSession",
+    "android.telephony.imsmedia.IImsTextSessionCallback",
+    "android.telephony.imsmedia.IImsVideoSession",
+    "android.telephony.imsmedia.IImsVideoSessionCallback",
+    "android.tracing.ITracingServiceProxy",
+    "android.uwb.IOnUwbActivityEnergyInfoListener",
+    "android.uwb.IUwbAdapter",
+    "android.uwb.IUwbAdapterStateCallbacks",
+    "android.uwb.IUwbAdfProvisionStateCallbacks",
+    "android.uwb.IUwbOemExtensionCallback",
+    "android.uwb.IUwbRangingCallbacks",
+    "android.uwb.IUwbVendorUciCallback",
+    "android.view.accessibility.IAccessibilityInteractionConnectionCallback",
+    "android.view.accessibility.IAccessibilityManager",
+    "android.view.accessibility.IMagnificationConnectionCallback",
+    "android.view.accessibility.IRemoteMagnificationAnimationCallback",
+    "android.view.autofill.IAutoFillManager",
+    "android.view.autofill.IAutofillWindowPresenter",
+    "android.view.contentcapture.IContentCaptureManager",
+    "android.view.IDisplayChangeWindowCallback",
+    "android.view.IDisplayWindowListener",
+    "android.view.IInputFilter",
+    "android.view.IInputFilterHost",
+    "android.view.IInputMonitorHost",
+    "android.view.IRecentsAnimationController",
+    "android.view.IRemoteAnimationFinishedCallback",
+    "android.view.ISensitiveContentProtectionManager",
+    "android.view.IWindowId",
+    "android.view.IWindowManager",
+    "android.view.IWindowSession",
+    "android.view.translation.ITranslationManager",
+    "android.view.translation.ITranslationServiceCallback",
+    "android.webkit.IWebViewUpdateService",
+    "android.window.IBackAnimationFinishedCallback",
+    "android.window.IDisplayAreaOrganizerController",
+    "android.window.ITaskFragmentOrganizerController",
+    "android.window.ITaskOrganizerController",
+    "android.window.ITransitionMetricsReporter",
+    "android.window.IUnhandledDragCallback",
+    "android.window.IWindowContainerToken",
+    "android.window.IWindowlessStartingSurfaceCallback",
+    "android.window.IWindowOrganizerController",
+    "androidx.core.uwb.backend.IUwb",
+    "androidx.core.uwb.backend.IUwbClient",
+    "com.android.clockwork.modes.IModeManager",
+    "com.android.clockwork.modes.IStateChangeListener",
+    "com.android.clockwork.power.IWearPowerService",
+    "com.android.devicelockcontroller.IDeviceLockControllerService",
+    "com.android.devicelockcontroller.storage.IGlobalParametersService",
+    "com.android.devicelockcontroller.storage.ISetupParametersService",
+    "com.android.federatedcompute.services.training.aidl.IIsolatedTrainingService",
+    "com.android.federatedcompute.services.training.aidl.ITrainingResultCallback",
+    "com.android.internal.app.IAppOpsActiveCallback",
+    "com.android.internal.app.ILogAccessDialogCallback",
+    "com.android.internal.app.ISoundTriggerService",
+    "com.android.internal.app.ISoundTriggerSession",
+    "com.android.internal.app.IVoiceInteractionAccessibilitySettingsListener",
+    "com.android.internal.app.IVoiceInteractionManagerService",
+    "com.android.internal.app.IVoiceInteractionSessionListener",
+    "com.android.internal.app.IVoiceInteractionSessionShowCallback",
+    "com.android.internal.app.IVoiceInteractionSoundTriggerSession",
+    "com.android.internal.app.procstats.IProcessStats",
+    "com.android.internal.appwidget.IAppWidgetService",
+    "com.android.internal.backup.ITransportStatusCallback",
+    "com.android.internal.compat.IOverrideValidator",
+    "com.android.internal.compat.IPlatformCompat",
+    "com.android.internal.compat.IPlatformCompatNative",
+    "com.android.internal.graphics.fonts.IFontManager",
+    "com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback",
+    "com.android.internal.inputmethod.IConnectionlessHandwritingCallback",
+    "com.android.internal.inputmethod.IImeTracker",
+    "com.android.internal.inputmethod.IInlineSuggestionsRequestCallback",
+    "com.android.internal.inputmethod.IInputContentUriToken",
+    "com.android.internal.inputmethod.IInputMethodPrivilegedOperations",
+    "com.android.internal.inputmethod.IInputMethodSessionCallback",
+    "com.android.internal.net.INetworkWatchlistManager",
+    "com.android.internal.os.IBinaryTransparencyService",
+    "com.android.internal.os.IDropBoxManagerService",
+    "com.android.internal.policy.IKeyguardDismissCallback",
+    "com.android.internal.policy.IKeyguardDrawnCallback",
+    "com.android.internal.policy.IKeyguardExitCallback",
+    "com.android.internal.policy.IKeyguardStateCallback",
+    "com.android.internal.statusbar.IAddTileResultCallback",
+    "com.android.internal.statusbar.ISessionListener",
+    "com.android.internal.statusbar.IStatusBarService",
+    "com.android.internal.telecom.IDeviceIdleControllerAdapter",
+    "com.android.internal.telecom.IInternalServiceRetriever",
+    "com.android.internal.telephony.IMms",
+    "com.android.internal.telephony.ITelephonyRegistry",
+    "com.android.internal.textservice.ISpellCheckerServiceCallback",
+    "com.android.internal.textservice.ITextServicesManager",
+    "com.android.internal.view.IDragAndDropPermissions",
+    "com.android.internal.view.IInputMethodManager",
+    "com.android.internal.view.inline.IInlineContentProvider",
+    "com.android.internal.widget.ILockSettings",
+    "com.android.net.IProxyPortListener",
+    "com.android.net.module.util.IRoutingCoordinator",
+    "com.android.ondevicepersonalization.libraries.plugin.internal.IPluginCallback",
+    "com.android.ondevicepersonalization.libraries.plugin.internal.IPluginExecutorService",
+    "com.android.ondevicepersonalization.libraries.plugin.internal.IPluginStateCallback",
+    "com.android.rkpdapp.IGetKeyCallback",
+    "com.android.rkpdapp.IGetRegistrationCallback",
+    "com.android.rkpdapp.IRegistration",
+    "com.android.rkpdapp.IRemoteProvisioning",
+    "com.android.rkpdapp.IStoreUpgradedKeyCallback",
+    "com.android.sdksandbox.IComputeSdkStorageCallback",
+    "com.android.sdksandbox.ILoadSdkInSandboxCallback",
+    "com.android.sdksandbox.IRequestSurfacePackageFromSdkCallback",
+    "com.android.sdksandbox.ISdkSandboxManagerToSdkSandboxCallback",
+    "com.android.sdksandbox.ISdkSandboxService",
+    "com.android.sdksandbox.IUnloadSdkInSandboxCallback",
+    "com.android.server.profcollect.IProviderStatusCallback",
+    "com.android.server.thread.openthread.IChannelMasksReceiver",
+    "com.android.server.thread.openthread.INsdPublisher",
+    "com.android.server.thread.openthread.IOtDaemonCallback",
+    "com.android.server.thread.openthread.IOtStatusReceiver",
+    "com.google.android.clockwork.ambient.offload.IDisplayOffloadService",
+    "com.google.android.clockwork.ambient.offload.IDisplayOffloadTransitionFinishedCallbacks",
+    "com.google.android.clockwork.healthservices.IHealthService",
+    "vendor.google_clockwork.healthservices.IHealthServicesCallback",
+)
diff --git a/tools/lint/utils/README.md b/tools/lint/utils/README.md
new file mode 100644
index 0000000..b5583c5
--- /dev/null
+++ b/tools/lint/utils/README.md
@@ -0,0 +1,11 @@
+# Utility Android Lint Checks for AOSP
+
+This directory contains scripts that execute utility Android Lint Checks for AOSP, specifically:
+* `enforce_permission_counter.py`: Provides statistics regarding the percentage of annotated/not
+  annotated `AIDL` methods with `@EnforcePermission` annotations.
+* `generate-exempt-aidl-interfaces.sh`: Provides a list of all `AIDL` interfaces in the entire
+  source tree.
+
+When adding a new utility Android Lint check to this directory, consider adding any utility or
+data processing tool you might require. Make sure that your contribution is documented in this
+README file.
diff --git a/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt b/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt
index fa61c42..9842881 100644
--- a/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt
+++ b/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt
@@ -19,6 +19,7 @@
 import com.android.tools.lint.client.api.IssueRegistry
 import com.android.tools.lint.client.api.Vendor
 import com.android.tools.lint.detector.api.CURRENT_API
+import com.google.android.lint.aidl.ExemptAidlInterfacesGenerator
 import com.google.android.lint.aidl.AnnotatedAidlCounter
 import com.google.auto.service.AutoService
 
@@ -27,6 +28,7 @@
 class AndroidUtilsIssueRegistry : IssueRegistry() {
     override val issues = listOf(
         AnnotatedAidlCounter.ISSUE_ANNOTATED_AIDL_COUNTER,
+        ExemptAidlInterfacesGenerator.ISSUE_PERMISSION_ANNOTATION_EXEMPT_AIDL_INTERFACES,
     )
 
     override val api: Int
@@ -38,6 +40,6 @@
     override val vendor: Vendor = Vendor(
         vendorName = "Android",
         feedbackUrl = "http://b/issues/new?component=315013",
-        contact = "tweek@google.com"
+        contact = "android-platform-abuse-prevention-withfriends@google.com"
     )
 }
diff --git a/tools/lint/utils/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfacesGenerator.kt b/tools/lint/utils/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfacesGenerator.kt
new file mode 100644
index 0000000..6ad223c
--- /dev/null
+++ b/tools/lint/utils/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfacesGenerator.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 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.google.android.lint.aidl
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Context
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import org.jetbrains.uast.UBlockExpression
+import org.jetbrains.uast.UMethod
+
+/**
+ * Generates a set of fully qualified AIDL Interface names present in the entire source tree with
+ * the following requirement: their implementations have to be inside directories whose path
+ * prefixes match `systemServicePathPrefixes`.
+ */
+class ExemptAidlInterfacesGenerator : AidlImplementationDetector() {
+    private val targetExemptAidlInterfaceNames = mutableSetOf<String>()
+    private val systemServicePathPrefixes = setOf(
+        "frameworks/base/services",
+        "frameworks/base/apex",
+        "frameworks/opt/wear",
+        "packages/modules"
+    )
+
+    // We could've improved performance by visiting classes rather than methods, however, this lint
+    // check won't be run regularly, hence we've decided not to add extra overrides to
+    // AidlImplementationDetector.
+    override fun visitAidlMethod(
+        context: JavaContext,
+        node: UMethod,
+        interfaceName: String,
+        body: UBlockExpression
+    ) {
+        val filePath = context.file.path
+
+        // We perform `filePath.contains` instead of `filePath.startsWith` since getting the
+        // relative path of a source file is non-trivial. That is because `context.file.path`
+        // returns the path to where soong builds the file (i.e. /out/soong/...). Moreover, the
+        // logic to extract the relative path would need to consider several /out/soong/...
+        // locations patterns.
+        if (systemServicePathPrefixes.none { filePath.contains(it) }) return
+
+        val fullyQualifiedInterfaceName =
+            getContainingAidlInterfaceQualified(context, node) ?: return
+
+        targetExemptAidlInterfaceNames.add("\"$fullyQualifiedInterfaceName\",")
+    }
+
+    override fun afterCheckEachProject(context: Context) {
+        if (targetExemptAidlInterfaceNames.isEmpty()) return
+
+        val message = targetExemptAidlInterfaceNames.joinToString("\n")
+
+        context.report(
+            ISSUE_PERMISSION_ANNOTATION_EXEMPT_AIDL_INTERFACES,
+            context.getLocation(context.project.dir),
+            "\n" + message + "\n",
+        )
+    }
+
+    companion object {
+        @JvmField
+        val ISSUE_PERMISSION_ANNOTATION_EXEMPT_AIDL_INTERFACES = Issue.create(
+            id = "PermissionAnnotationExemptAidlInterfaces",
+            briefDescription = "Returns a set of all AIDL interfaces",
+            explanation = """
+                Produces the exemptAidlInterfaces set used by PermissionAnnotationDetector
+            """.trimIndent(),
+            category = Category.SECURITY,
+            priority = 5,
+            severity = Severity.INFORMATIONAL,
+            implementation = Implementation(
+                ExemptAidlInterfacesGenerator::class.java,
+                Scope.JAVA_FILE_SCOPE
+            )
+        )
+    }
+}
diff --git a/tools/lint/utils/checks/src/test/java/com/google/android/lint/aidl/ExemptAidlInterfacesGeneratorTest.kt b/tools/lint/utils/checks/src/test/java/com/google/android/lint/aidl/ExemptAidlInterfacesGeneratorTest.kt
new file mode 100644
index 0000000..9a17bb4
--- /dev/null
+++ b/tools/lint/utils/checks/src/test/java/com/google/android/lint/aidl/ExemptAidlInterfacesGeneratorTest.kt
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2024 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.google.android.lint.aidl
+
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestLintTask
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+
+class ExemptAidlInterfacesGeneratorTest : LintDetectorTest() {
+    override fun getDetector(): Detector = ExemptAidlInterfacesGenerator()
+
+    override fun getIssues(): List<Issue> = listOf(
+        ExemptAidlInterfacesGenerator.ISSUE_PERMISSION_ANNOTATION_EXEMPT_AIDL_INTERFACES,
+    )
+
+    override fun lint(): TestLintTask = super.lint().allowMissingSdk(true)
+
+    fun testMultipleAidlInterfacesImplemented() {
+        lint()
+            .files(
+                java(
+                    createVisitedPath("TestClass1.java"),
+                    """
+                        package com.android.server;
+                        public class TestClass1 extends IFoo.Stub {
+                            public void testMethod() {}
+                        }
+                    """
+                )
+                    .indented(),
+                java(
+                    createVisitedPath("TestClass2.java"),
+                    """
+                        package com.android.server;
+                        public class TestClass2 extends IBar.Stub {
+                            public void testMethod() {}
+                        }
+                    """
+                )
+                    .indented(),
+                *stubs,
+            )
+            .run()
+            .expect(
+                """
+                    app: Information: "IFoo",
+                    "IBar", [PermissionAnnotationExemptAidlInterfaces]
+                    0 errors, 0 warnings
+                """
+            )
+    }
+
+    fun testSingleAidlInterfaceRepeated() {
+        lint()
+            .files(
+                java(
+                    createVisitedPath("TestClass1.java"),
+                    """
+                        package com.android.server;
+                        public class TestClass1 extends IFoo.Stub {
+                            public void testMethod() {}
+                        }
+                    """
+                )
+                    .indented(),
+                java(
+                    createVisitedPath("TestClass2.java"),
+                    """
+                        package com.android.server;
+                        public class TestClass2 extends IFoo.Stub {
+                            public void testMethod() {}
+                        }
+                    """
+                )
+                    .indented(),
+                *stubs,
+            )
+            .run()
+            .expect(
+                """
+                    app: Information: "IFoo", [PermissionAnnotationExemptAidlInterfaces]
+                    0 errors, 0 warnings
+                """
+            )
+    }
+
+    fun testAnonymousClassExtendsAidlStub() {
+        lint()
+            .files(
+                java(
+                    createVisitedPath("TestClass.java"),
+                    """
+                        package com.android.server;
+                        public class TestClass {
+                            private IBinder aidlImpl = new IFoo.Stub() {
+                                public void testMethod() {}
+                            };
+                        }
+                        """
+                )
+                    .indented(),
+                *stubs,
+            )
+            .run()
+            .expect(
+                """
+                    app: Information: "IFoo", [PermissionAnnotationExemptAidlInterfaces]
+                    0 errors, 0 warnings
+                """
+            )
+    }
+
+    fun testNoAidlInterfacesImplemented() {
+        lint()
+            .files(
+                java(
+                    createVisitedPath("TestClass.java"),
+                    """
+                        package com.android.server;
+                        public class TestClass {
+                            public void testMethod() {}
+                        }
+                    """
+                )
+                    .indented(),
+                *stubs
+            )
+            .run()
+            .expectClean()
+    }
+
+    fun testAidlInterfaceImplementedInIgnoredDirectory() {
+        lint()
+            .files(
+                java(
+                    ignoredPath,
+                    """
+                        package com.android.server;
+                        public class TestClass1 extends IFoo.Stub {
+                            public void testMethod() {}
+                        }
+                    """
+                )
+                    .indented(),
+                *stubs,
+            )
+            .run()
+            .expectClean()
+    }
+
+    private val interfaceIFoo: TestFile = java(
+        """
+            public interface IFoo extends android.os.IInterface {
+                public static abstract class Stub extends android.os.Binder implements IFoo {}
+                public void testMethod();
+            }
+        """
+    ).indented()
+
+    private val interfaceIBar: TestFile = java(
+        """
+            public interface IBar extends android.os.IInterface {
+                public static abstract class Stub extends android.os.Binder implements IBar {}
+                public void testMethod();
+            }
+        """
+    ).indented()
+
+    private val stubs = arrayOf(interfaceIFoo, interfaceIBar)
+
+    private fun createVisitedPath(filename: String) =
+        "src/frameworks/base/services/java/com/android/server/$filename"
+
+    private val ignoredPath = "src/test/pkg/TestClass.java"
+}
diff --git a/tools/lint/utils/generate-exempt-aidl-interfaces.sh b/tools/lint/utils/generate-exempt-aidl-interfaces.sh
new file mode 100755
index 0000000..44dcdd7
--- /dev/null
+++ b/tools/lint/utils/generate-exempt-aidl-interfaces.sh
@@ -0,0 +1,59 @@
+#
+# Copyright (C) 2024 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.
+#
+
+# Create a directory for the results and a nested temporary directory.
+mkdir -p $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/tmp
+
+# Create a copy of `AndroidGlobalLintChecker.jar` to restore it afterwards.
+cp $ANDROID_BUILD_TOP/prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar \
+    $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/AndroidGlobalLintChecker.jar
+
+# Configure the environment variable required for running the lint check on the entire source tree.
+export ANDROID_LINT_CHECK=PermissionAnnotationExemptAidlInterfaces
+
+# Build the target corresponding to the lint checks present in the `utils` directory.
+m AndroidUtilsLintChecker
+
+# Replace `AndroidGlobalLintChecker.jar` with the newly built `jar` file.
+cp $ANDROID_BUILD_TOP/out/host/linux-x86/framework/AndroidUtilsLintChecker.jar \
+    $ANDROID_BUILD_TOP/prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar;
+
+# Run the lint check on the entire source tree.
+m lint-check
+
+# Copy the archive containing the results of `lint-check` into the temporary directory.
+cp $ANDROID_BUILD_TOP/out/soong/lint-report-text.zip \
+    $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/tmp
+
+cd $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/tmp
+
+# Unzip the archive containing the results of `lint-check`.
+unzip lint-report-text.zip
+
+# Concatenate the results of `lint-check` into a single string.
+concatenated_reports=$(find . -type f | xargs cat)
+
+# Extract the fully qualified names of the AIDL Interfaces from the concatenated results. Output
+# this list into `out/soong/exempt_aidl_interfaces_generator_output/exempt_aidl_interfaces`.
+echo $concatenated_reports | grep -Eo '\"([a-zA-Z0-9_]*\.)+[a-zA-Z0-9_]*\",' | sort | uniq > ../exempt_aidl_interfaces
+
+# Remove the temporary directory.
+rm -rf $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/tmp
+
+# Restore the original copy of `AndroidGlobalLintChecker.jar` and delete the copy.
+cp $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/AndroidGlobalLintChecker.jar \
+    $ANDROID_BUILD_TOP/prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar
+rm $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/AndroidGlobalLintChecker.jar
diff --git a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt
index 0115339..245e802 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt
@@ -53,7 +53,7 @@
                         .setMessageId(key)
                         .setMessage(log.messageString)
                         .setLevel(
-                            ProtoLogLevel.forNumber(log.logLevel.ordinal + 1))
+                            ProtoLogLevel.forNumber(log.logLevel.id))
                         .setGroupId(groupId)
                         .setLocation(log.position)
             )